DEV Community

Cover image for Let's Learn Unit Testing in Python with pytest! ๐Ÿš€
Jagroop Singh
Jagroop Singh

Posted on

30 5 5 4 5

Let's Learn Unit Testing in Python with pytest! ๐Ÿš€

Unit testing in Python can feel like magic โ€” a little preparation, and youโ€™re ready to squash bugs before they creep into your code. Today, weโ€™re diving into pytest, a powerful yet simple framework that makes testing fun! ๐Ÿ˜ƒ Let's learn through examples and keep theory to a minimum. Ready? Letโ€™s go! ๐Ÿƒ


What is pytest?

pytest is a Python testing framework thatโ€™s:

  • Simple to use: Write clean tests with minimal boilerplate.
  • Feature-rich: Handles fixtures, assertions, parameterized tests, and more.
  • Extensible: Add plugins to supercharge your tests.

Hereโ€™s how you install it:

pip install pytest
Enter fullscreen mode Exit fullscreen mode

Boom! Thatโ€™s it. Youโ€™re ready. ๐Ÿš€


Writing Your First Test ๐Ÿ”ฌ

Hereโ€™s the simplest test you can write:

# test_sample.py

def test_addition():
    assert 1 + 1 == 2
Enter fullscreen mode Exit fullscreen mode

To run this test, type:

pytest test_sample.py
Enter fullscreen mode Exit fullscreen mode

Youโ€™ll see this output:

output

Hooray! ๐ŸŽ‰ Your test passed.


The Power of Assertions ๐Ÿ”ฅ

pytestโ€™s magic lies in assertions. You use assert statements to test if your code behaves as expected. Here are some examples:

# test_math.py

def test_operations():
    assert 2 * 2 == 4
    assert 10 / 2 == 5
    assert 5 - 2 == 3
Enter fullscreen mode Exit fullscreen mode

Youโ€™ll see this output:

output

If any assert fails, pytest will show you a detailed error message. ๐ŸŽ‰ No need to learn a special syntax!


Fixtures: Setting the Stage ๐ŸŽก

Fixtures are a way to set up reusable context for your tests. Imagine youโ€™re testing a database. Instead of connecting to the database in every test, you can create a fixture.

Hereโ€™s an example:

import pytest

@pytest.fixture
def sample_data():
    return {"name": "Alice", "age": 30}

def test_sample_data(sample_data):
    assert sample_data["name"] == "Alice"
    assert sample_data["age"] == 30
Enter fullscreen mode Exit fullscreen mode

pytest automatically provides the sample_data fixture to the test function. ๐Ÿš€


Parameterized Tests: Test More with Less ๐Ÿ”„

Letโ€™s say you want to test multiple inputs. Instead of writing multiple test functions, you can use @pytest.mark.parametrize:

import pytest

@pytest.mark.parametrize("x, y, result", [
    (1, 2, 3),
    (5, 5, 10),
    (10, -2, 8),
])
def test_add(x, y, result):
    assert x + y == result
Enter fullscreen mode Exit fullscreen mode

pytest will run the test for every combination of inputs! ๐Ÿ”ง


Organizing Your Tests ๐Ÿ—‚

Keep your tests organized:

  • Test files: Name them test_*.py or *_test.py.
  • Test functions: Start with test_.

Example structure:

project/
|-- app.py
|-- tests/
    |-- test_app.py
    |-- test_utils.py
Enter fullscreen mode Exit fullscreen mode

pytest will automatically discover your tests. Neat, right? ๐Ÿ˜‰


pytest Plugins: Level Up Your Testing ๐Ÿ†

pytest has tons of plugins to make your life easier. Here are a few favorites:

  • pytest-cov: Measure code coverage.
  pip install pytest-cov
  pytest --cov=your_module
Enter fullscreen mode Exit fullscreen mode
  • pytest-mock: Mock objects for unit tests.

  • pytest-django: For testing Django applications.

Find more plugins at pytest-dev/plugins.


Handling Expected Errors โš ๏ธ

To test if a function raises an error, use pytest.raises:

import pytest

def divide(a, b):
    if b == 0:
        raise ValueError("Cannot divide by zero!")
    return a / b

def test_divide_by_zero():
    with pytest.raises(ValueError, match="Cannot divide by zero!"):
        divide(1, 0)
Enter fullscreen mode Exit fullscreen mode

pytest will check that the error is raised and matches the message. ๐Ÿ”“


Interactive Quiz ๐Ÿ•บ

Question: What does this test output?

def test_example():
    assert 2 * 3 == 5
Enter fullscreen mode Exit fullscreen mode
  • A: Test passes โœ…
  • B: Test fails with an error โŒ

Spoiler: It fails! ๐Ÿ˜… pytest will output something like:

error


Final Tips ๐Ÿ™Œ

  1. Start small: Write simple tests as you learn.
  2. Test early: Write tests as you code, not after.
  3. Use coverage: Aim for high code coverage but focus on meaningful tests.

Unit testing with pytest is straightforward, powerful, and fun! ๐Ÿš€ Start writing tests today and watch your codebase become more robust and reliable. Happy testing! ๐ŸŽฎ

Top comments (10)

Collapse
 
canmingir profile image
Can Mingir โ€ข

Can you do BDD style like Jasmine in pytest?

Collapse
 
jagroop2001 profile image
Jagroop Singh โ€ข

Yes,I have implement Behavior-Driven Development style tests similar to Jasmine in pytest by using a plugin called pytest-bdd.

Collapse
 
hraifi profile image
sewiko โ€ข

Option B: Test fails with an error โŒ is correct.

Collapse
 
jagroop2001 profile image
Jagroop Singh โ€ข

Yes, it's correct. That's a simple one.

Collapse
 
anurag_nagar profile image
Anurag Nagar โ€ข

I think you can create one post on how to write advanced test cases.

Thread Thread
 
jagroop2001 profile image
Jagroop Singh โ€ข

Sure

Collapse
 
hbthepencil profile image
HB_the_Pencil โ€ข

Thanks! This is a really great and in-depth tutorial. I expect to get more use out of it in the near future :D

Collapse
 
jagroop2001 profile image
Jagroop Singh โ€ข

Thanks @hbthepencil

Collapse
 
draven_locke_039584510230 profile image
Draven Locke โ€ข

You really make it seem easy and fun especially with how simple the syntax is. I love how you included examples for common scenarios. The tips at the end are really helpful too.

Collapse
 
jagroop2001 profile image
Jagroop Singh โ€ข