DEV Community

Cover image for Python TDD with Pytest  -- Getting Started
Kelvin Wangonya
Kelvin Wangonya

Posted on • Originally published at wangonya.com

Python TDD with Pytest -- Getting Started

Test-Driven Development is great. If you're a Pythonista, it gets even better with pytest - a framework that makes building simple and scalable tests easy.

In this series, I'll be exploring the cool features that pytest offers to help make testing Python code a breeze.

Preparing your python environment

Let's set up our testing environment with virtualenv. We'll be working with Python 3. cd into your working directory and create a new virtual environment:

python3 -m venv env
Enter fullscreen mode Exit fullscreen mode

Activate the virtual environment:

source env/bin/activate
Enter fullscreen mode Exit fullscreen mode

Installing pytest

pip install pytest
Enter fullscreen mode Exit fullscreen mode

That's all you need to do to get pytest ready. You can check the installed version by running:

pytest --version
Enter fullscreen mode Exit fullscreen mode

Creating your first test

Say we need to create an app that says hello to the name you give it when it runs (I know, very original πŸ˜…).

# simple hello world test

def hello_world(name):
    pass

def test_hello():
    assert hello_world("World!") == "Hello World!"  
Enter fullscreen mode Exit fullscreen mode

You'll notice that our test function name begins with the word test. That's how pytest discoveres test methods. Also, :

  • Test files should be named test_<something>.py or <something>_test.py
  • Test classes should be named Test<Something>

Running pytest hello.py should return:

collected 1 item
hello.py F                         [100%]

===================== FAILURES ======================
    def test_hello():
>       assert hello_world("World!") == "Hello World!"
E       AssertionError: assert None == 'Hello World!'
E        +  where None = hello_world('World!')

hello.py:6: AssertionError
Enter fullscreen mode Exit fullscreen mode

Pytest shows why the test failed: AssertionError: assert None == 'Hello World!’. Obviously, we have no code in our hello function so let’s fix that.

def hello_world(name):
    return "Hello {}".format(name)

def test_hello():
    assert hello_world("World!") == "Hello World!"
Enter fullscreen mode Exit fullscreen mode

Running pytest hello.py should now return:

collected 1 item     
hello.py .                       [100%]

==================== 1 passed in 0.04 seconds ======================
Enter fullscreen mode Exit fullscreen mode

As you can see, it’s pretty easy to get started with testing in python with pytest. Now that we have everything set up, we’ll be going into more advanced features as the series continues.

Top comments (8)

Collapse
 
dmahely profile image
Doaa Mahely

Hey Kinyanjui. Thanks for this series.
I'm just getting started with pytest. I have a program that has multiple user inputs. I wrote 3 basic tests so far. All using if statements then asserts.
When I run pytest card.py -s, the program runs and I have to input all the data, then I get the message whether the tests have passed or not.
My question is, how can I run the tests without the code having to run? Does it depend on how I wrote the tests?

Collapse
 
wangonya profile image
Kelvin Wangonya

Hey @dmahely ! Thanks for reading, and I'm glad you liked it. Sorry for the late reply, it's been a while since I was here.

You can automate the tests by passing in mock data. Do you have the code hosted on GitHub or somewhere I can have a look so I can guide you on how to do it?

Collapse
 
dmahely profile image
Doaa Mahely

Is that what automated tests mean? πŸ˜…
The code was for a technical test that I've since submitted, and the instructions included not putting it on GitHub. May I reach out to you on Twitter?

Thread Thread
 
wangonya profile image
Kelvin Wangonya

Yeah, feel free to reach out on Twitter.

Collapse
 
aderchox profile image
aderchox • Edited

I receive an error which begins like this(I've called my python file "main.py" instead of "hello.py"):

ERRORS =================================================================
_______________________________________________________ ERROR collecting main.py ________________________________________________________
env\lib\site-packages_pytest\python.py:493: in _importtestmodule
...

Can you help me with that? By the way this is a great tutorial Kinyanjui, can't thank you enough.
(P.S: Also just since it might matter, I'm on Windows and I activated the env using ".\env\Scripts\activate.bat" instead of the one you did in your terminal. I tested pytest --version and it's installed successfully.)

P.S #2: Sorry, I fixed it. I had a typo. But the error was scary and unreadable! Thanks anyways I enjoyed it very much when the test passed! :) I didn't delete the error so if someone else bumps into the same error can see my comment.

P.S #3: How about writing the test functions in a separate file? How should we run them? Should we use globs in that case? e.g: pytest test_*.py?

Collapse
 
wangonya profile image
Kelvin Wangonya

Hey @aderchox . If the test is in a different file, still just running pytest while in the project directory should discover the test files, as long as they're named in the format test_*.py.
You can read more about test discovery here.

Collapse
 
wzorroman profile image
wzorroman • Edited

import re
import pytest

def check_email_format(email):
if not (re.match(r"([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$)", email)):
return False
return True

def test_email_exception():
assert check_email_format("good@email.com") == True
assert check_email_format("good.com") == False

Collapse
 
molecula451 profile image
Paul

Nice post.