Tim Cooke

Exercises for Programmers (Python): 1 of 57 - Saying Hello

26th July 2020

I'm really bad at Python and I want to get better, so I've chosen this book by Brian P. Hogan as a way to do that. Exercises for Programmers: 57 Challenges to Develop Your Coding Skills.

Create a program that prompts for your name and prints a greeting using your name.

Example Output

What is your name? Brian
Hello, Brian, nice to meet you!

From previous tinkerings with Python I know that it's a scripted language as well as Object Oriented, so I'm going to start with a script because that's what I know. I created file hello.py containing the following:

name = input("What is your name? ")
print("Hello, " + name + ", nice to meet you!")

And run it with this:

$ python3 hello.py
What is your name? Tim
Hello, Tim, nice to meet you!

Happy days!

Next up I want to learn how to write and run unit tests. A quick Google for 'python unit testing' informed me of two seemingly popular options, namely unittest and pytest. Since unittest is part of the Python library I went with that, figured out the syntax, created file test_hello.py, and wrote the following failing test:

import unittest
import hello
            
            
class TestHello(unittest.TestCase):
            
def test_givenValidName_returnsExpectedString(self):
self.assertEqual(hello.sayhello('Tim'), 'Hello, Tim, nice to meet you!')

I've made an assumption with my test here that I will extract the greeting generation code into its own function called sayhello that takes a single 'name' argument, and returns the appropriate string. I know the function doesn't exist yet and I expect the test to fail, but let's see what command I need to run the test.

$ python3 -m unittest
What is your name? Tim
Hello, Tim, nice to meet you!
E
======================================================================
ERROR: test_givenValidName_returnsExpectedString (test_hello.TestHello)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/Development/github/57-exercises-python/01-saying-hello/test_hello.py", line 8, in test_givenValidName_returnsExpectedString
    self.assertEqual(hello.sayhello('Tim'), 'Hello, Tim, nice to meet you!')
AttributeError: module 'hello' has no attribute 'sayhello'
        
----------------------------------------------------------------------
Ran 1 test in 0.001s
        
FAILED (errors=1)

Well that was not what I expected at all. I expected the test to fail but not in this way. What's going on:

  1. The hello.py file is running as a script and prompting me for keyboard input, which is not what I want from automated tests.
  2. It can't find the sayhello function, which is fair enough because it doesn't exist yet but the error message is rather cryptic with AttributeError: module 'hello' has no attribute 'sayhello'. Perhaps that'll make more sense one day.

Let's address problem 1. I want to see if I can stop the unit test running the file as a script. Again with a little searching I have discovered that there is a Top-level script environment which provides the following template to run certain code only when run as a script.

if __name__ == "__main__":
    # execute only if run as a script

Now, if I extract the greeting generation into its own function and put the keyboard input and terminal output code in the __main__ function I have this

def sayhello(name):
    return "Hello, " + name + ", nice to meet you!"
    
    
if __name__ == "__main__":
    print(sayhello(input("What is your name? ")))

And passing tests

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

OK

Learning review

Github

57-exercises-python/src/exercises/Ex01_saying_hello/