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
str
type.int
type.unittest
output is a GUI(ish) summary of the test run, e.g.
F.
meaning one test failed and one passed. The outputs I've seen so far are:
E
Error, F
Failure, and .
Pass.+
only works with str
typed arguments.len()
.str
type has a strip()
function for removing leading and trailing
whitespace characters from a string.str
type has a replace()
function for replacing all occurrences of a
string with another string. In this case replace(" ", "")
to remove all whitespace.57-exercises-python/src/exercises/Ex02_counting_the_number_of_characters/