Russ Tokuyama

How I Started With pytest

Last update: 08/01/2023
Back to home
Back to Posts

While I've known about test-driven development (TDD) for a while, I've always had trouble using it consistently. This is my perspective on trying to use TDD more often. I'm using Python 3 for the programming language in the examples but you should be able to use any programming language.

Which tool to use?

Python has the unittest module and you start by creating a test class. Run python -m unittest to run the tests in your test class. See unittest - Unit testing framework.

But, I wanted something a little easier to use. With pytest, you just create a test file with your tests in it. Then, run the pytest command. See Installation and Getting Started.

My first test

I needed a function that would capitalize the first letter of each word in a string composed of words separated by underscores ("_"). For example, I wanted to change "body_bytes" to "Body_Bytes". So, I started with this test_capitalize.py file:

def test_capitalize():
    given = 'body_bytes'
    want = 'Body_Bytes'

    got = capitalize(given)
    assert got == want

It has:

  • The thing I start with (given)
  • The thing I want to end up with (want)
  • The function that does what I want (capitalize).

The test is a simple function that pytest will automatically run. Here's what I got when I ran pytest:

============================= test session starts ==============================
platform darwin -- Python 3.8.8, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /Users/russ/Parse_Nginx_Logs
collected 1 item

test_capitalize.py F                                                     [100%]

=================================== FAILURES ===================================
_______________________________ test_capitalize ________________________________

    def test_capitalize():
        given = 'body_bytes'
        want = 'Body_Bytes'

>       got = capitalize(given)
E       NameError: name 'capitalize' is not defined

test_capitalize.py:5: NameError
=========================== short test summary info ============================
FAILED test_capitalize.py::test_capitalize - NameError: name 'capitalize' is ...
============================== 1 failed in 0.05s ===============================

This tells me that I haven't written the capitalize function yet.

While you can put the function to be tested in the test file, it wouldn't be as useful as putting it in its own file so that it can be used or reused by other code. So, I created a capitalize.py file.

def capitalize(s):
    """Capitalize individual words in a string separated by underscores ('_')"""

    return "_".join([w.capitalize() for w in s.split("_")])

This is what happened when I ran pytest:

============================= test session starts ==============================
platform darwin -- Python 3.8.8, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /Users/russ/Parse_Nginx_Logs
collected 1 item

test_capitalize.py F                                                     [100%]

=================================== FAILURES ===================================
_______________________________ test_capitalize ________________________________

    def test_capitalize():
        given = 'body_bytes'
        want = 'Body_Bytes'

>       got = capitalize(given)
E       NameError: name 'capitalize' is not defined

test_capitalize.py:5: NameError
=========================== short test summary info ============================
FAILED test_capitalize.py::test_capitalize - NameError: name 'capitalize' is ...
============================== 1 failed in 0.05s ===============================

OK, I forgot to tell the test where the capitalize function is defined. So, here's how I did that:

from capitalize import *

def test_capitalize():
    given = 'body_bytes'
    want = 'Body_Bytes'

    got = capitalize(given)
    assert got == want

This is what I got when I ran pytest:

============================= test session starts ==============================
platform darwin -- Python 3.8.8, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /Users/russ/Parse_Nginx_Logs
collected 1 item

test_capitalize.py .                                                     [100%]

============================== 1 passed in 0.02s ===============================

Call to action

Wasn't that easy? So, try it!