Let's Learn Unit Testing in Python with pytest! 🚀
Jagroop Singh

Jagroop Singh @jagroop2001

About: 👨‍💻 Full Stack Developer | 🤖 Machine Learning Developer | 🤝 Dev Relations Pro – 💼 Available for Hire | 24k+ Followers | 355k+ Views

Location:
India
Joined:
Apr 5, 2022

Let's Learn Unit Testing in Python with pytest! 🚀

Publish Date: Dec 11 '24
49 10

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! 🎮

Comments 10 total

  • sewiko
    sewikoDec 11, 2024

    Option B: Test fails with an error ❌ is correct.

  • Can Mingir
    Can MingirDec 11, 2024

    Can you do BDD style like Jasmine in pytest?

    • Jagroop Singh
      Jagroop SinghDec 11, 2024

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

  • HB_the_Pencil
    HB_the_PencilDec 12, 2024

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

  • Draven Locke
    Draven LockeDec 13, 2024

    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.

Add comment