Tim Cooke

Exercises for Programmers (Python): 2 of 57 - Counting the Number of Characters

27th July 2020

Exercise 2 in book Exercises for Programmers: 57 Challenges to Develop Your Coding Skills by Brian P. Hogan.

Create a program that prompts for an input string and displays output that shows the input string and the number of characters the string contains.

Example Output

What is the input string? Homer
Homer has 5 characters

I'll start with a test. Again I'm making assumptions about the structure of the code and expecting a function called charcount() that takes a string and returns a number. Python is a dynamically typed system so I'm not entirely sure what type a string and a number are, but maybe I'll find out along the way.

import unittest
import counting


class TestHello(unittest.TestCase):

    def test_givenValidString_returnsExpectedCount(self):
        self.assertEqual(counting.charcount('Tim'), 3)

Run test test

$ python3 -m unittest
E
======================================================================
ERROR: test_givenValidString_returnsExpectedCount (test_counting.TestHello)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/Development/github/57-exercises-python/02-counting-the-number-of-characters/test_counting.py", line 8, in test_givenValidString_returnsExpectedCount
    self.assertEqual(counting.charcount('Tim'), 3)
AttributeError: module 'counting' has no attribute 'charcount'

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)

Failed. Expected because I haven't written anything yet. My first approach is always to make the test pass in the simplest way possible which may not look like the right thing to do but is part of my process.

def charcount(string):
    return 3


if __name__ == "__main__":
    inputstring = input("What is the input string? ")
    count = charcount(input)
    print(inputstring + " has " + count + " characters")

Run tests again

$ python3 -m unittest
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

The unit tests are passing which is great. I've used the same approach I learned last time about how to use the __main__ check to exclude the keyboard input and terminal output code from the automated tests, so let's go for a manual test of the code run as a script:

$ python3 counting.py 
What is the input string? Tim
Traceback (most recent call last):
  File "counting.py", line 8, in 
    print(inputstring + " has " + count + " characters")
TypeError: can only concatenate str (not "int") to str

Not quite as expected but I'm learning about the type system which is a positive. Strings are a str type and 3 is an int type. I figure out how to convert an int to a str using the str() function so updated the print fuction to use it.

print(inputstring + " has " + str(count) + " characters")

Try again

$ python3 counting.py 
What is the input string? Homer
Homer has 3 characters

That's fixed the type problems but has now highlighted the flaw in my simple solution earlier, "Homer" does not have 3 characters. How do you figure out how many characters are in a string? A flit round the Python library docs suggests that len() might be what I'm looking for. But first, another test

def test_givenValidString_returnsExpectedCount(self):
    self.assertEqual(counting.charcount('Tim'), 3)

def test_givenLongerString_returnsExpectedCount(self):
    self.assertEqual(counting.charcount('Situation'), 9)

Confirm it fails

$ python3 -m unittest
F.
======================================================================
FAIL: test_givenLongerString_returnsExpectedCount (test_counting.TestHello)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/Development/github/57-exercises-python/02-counting-the-number-of-characters/test_counting.py", line 11, in test_givenLongerString_returnsExpectedCount
    self.assertEqual(counting.charcount('Situation'), 9)
AssertionError: 3 != 9

----------------------------------------------------------------------
Ran 2 tests in 0.000s

FAILED (failures=1)

Make it pass

def charcount(string):
    return len(string)
$ python3 -m unittest
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

And when run as a script

$ python3 counting.py 
What is the input string? Homer
Homer has 5 characters

At this point I'm essentially done, but I'm wondering if whitespace should be included when counting characters and I think it should not so onwards with more tests.

def test_givenUntrimmedString_returnsTrimmedCount(self):
    self.assertEqual(counting.charcount('   Tim   '), 3)

def test_givenStringWithWhitespace_returnsCharacterCountOnly(self):
    self.assertEqual(counting.charcount('   Tim    Cooke  '), 8)

I discover that the str type has a strip() function that strips leading and trailing whitespace

def charcount(string):
    return len(string.strip())

This takes care of the leading and trailing spaces but does not take care of the rest. Let's try the replace() function instead.

def charcount(string):
    return len(string.replace(" ", ""))

That did it.

$ python3 -m unittest
....
----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK

Learning review

Github

57-exercises-python/src/exercises/Ex02_counting_the_number_of_characters/