DEV Community

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

Posted on

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 (4)

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.