Bird
Raised Fist0
PyTesttesting~15 mins

Test functions in PyTest - Deep Dive

Choose your learning style10 modes available
Overview - Test functions
What is it?
Test functions are small pieces of code that check if parts of your program work correctly. In pytest, these functions start with 'test_' and use simple assertions to compare expected and actual results. They help find mistakes early by running automatically. Anyone can write them without special setup.
Why it matters
Without test functions, bugs can hide unnoticed and cause bigger problems later. They save time and effort by catching errors early, making software more reliable and easier to fix. Imagine building a house without checking if each part is solid; test functions are like inspecting each brick before moving on.
Where it fits
Before learning test functions, you should know basic Python programming and how to write simple functions. After mastering test functions, you can learn about test fixtures, parameterized tests, and test organization for bigger projects.
Mental Model
Core Idea
A test function is a small, automatic check that confirms a specific part of your code behaves as expected.
Think of it like...
Test functions are like recipe taste tests: after cooking a dish, you try a bite to make sure it tastes right before serving it to guests.
┌───────────────┐
│  Test Runner  │
└──────┬────────┘
       │ runs
┌──────▼────────┐
│ Test Function │
│  (test_xyz)   │
└──────┬────────┘
       │ asserts
┌──────▼────────┐
│  Code Output  │
│  vs Expected  │
└───────────────┘
Build-Up - 7 Steps
1
FoundationWriting Your First Test Function
🤔
Concept: Learn how to write a simple test function using pytest naming rules and assertions.
Create a Python file named test_sample.py. Write a function starting with 'test_' like test_addition(). Inside, use assert to check if 2 + 2 equals 4. Run pytest in the terminal to see the test pass.
Result
pytest runs the test and shows '1 passed' indicating the code works as expected.
Understanding the naming and assertion basics is key to making pytest recognize and run your tests automatically.
2
FoundationUsing Assertions to Check Results
🤔
Concept: Assertions compare actual results with expected values to confirm correctness.
Inside a test function, use assert statements like assert function_call() == expected_value. If the assertion fails, pytest reports an error showing what was expected and what was received.
Result
When assertion passes, test passes silently; when it fails, pytest shows a clear error message.
Assertions are the heart of test functions; they express what your code should do in a simple, readable way.
3
IntermediateOrganizing Multiple Test Functions
🤔Before reading on: do you think pytest runs tests in the order they appear or in a random order? Commit to your answer.
Concept: Learn how pytest discovers and runs multiple test functions in a file and across files.
Write several test functions in one file, each testing different parts of your code. Pytest finds all functions starting with 'test_' and runs them independently. The order is not guaranteed, so tests should not depend on each other.
Result
Pytest runs all tests and reports which pass or fail, regardless of their order.
Knowing that tests run independently helps you write reliable tests that don't interfere with each other.
4
IntermediateHandling Expected Failures Gracefully
🤔Before reading on: do you think a test that is expected to fail should be marked or just left as is? Commit to your answer.
Concept: Pytest allows marking tests that are expected to fail to keep track without breaking the test suite.
Use the @pytest.mark.xfail decorator above a test function that is known to fail due to a bug or unimplemented feature. Pytest will report it as an expected failure, not a test error.
Result
Tests marked xfail show as 'expected fail' in reports, keeping the suite clean while tracking issues.
Marking expected failures helps manage work-in-progress code and prevents noise in test results.
5
IntermediateUsing Setup Code Inside Test Functions
🤔
Concept: Sometimes tests need preparation steps before assertions, done inside the test function.
Inside a test function, create variables or call setup functions to prepare data or state. Then perform assertions on the prepared setup. This keeps tests self-contained and clear.
Result
Tests run with their own setup, making them independent and easier to understand.
Including setup inside tests avoids hidden dependencies and makes debugging easier.
6
AdvancedAvoiding Test Interdependence Pitfalls
🤔Before reading on: do you think tests that share data or state can cause hidden bugs? Commit to your answer.
Concept: Tests should be independent; sharing state can cause flaky or misleading results.
If one test modifies shared data, another test might fail unexpectedly. Use fresh data or pytest fixtures to isolate tests. Avoid global variables or shared mutable objects.
Result
Tests become reliable and repeatable, passing or failing only due to their own code.
Understanding test independence prevents hard-to-find bugs and builds trust in test results.
7
ExpertHow Pytest Discovers and Runs Test Functions
🤔Before reading on: do you think pytest uses file names, function names, or both to find tests? Commit to your answer.
Concept: Pytest uses naming conventions and internal hooks to find and run test functions efficiently.
Pytest looks for files named test_*.py or *_test.py, then inside those files finds functions starting with 'test_'. It collects these and runs them in isolated environments, capturing output and exceptions. Plugins can extend discovery and execution.
Result
Tests run automatically without manual registration, with detailed reports and support for advanced features.
Knowing pytest's discovery mechanism helps write tests that integrate smoothly and leverage pytest's power.
Under the Hood
Pytest scans your project folders for files matching test naming patterns. It imports these files as modules and inspects their contents for functions starting with 'test_'. Each test function runs in isolation, with pytest capturing exceptions and assertion failures. It uses Python's assert rewriting to provide detailed error messages. Test results are collected and summarized in a report.
Why designed this way?
Pytest was designed for simplicity and power. Using naming conventions avoids complex configuration. Running tests as simple functions lowers the barrier for beginners. Isolating tests prevents side effects. The assert rewriting feature was added to give clear feedback without extra code. This design balances ease of use with advanced capabilities.
Project Folder
  ├─ test_example.py
  │    ├─ test_func1()
  │    └─ test_func2()
  └─ test_utils.py
       └─ test_func3()

Pytest Discovery
  └─ Finds test files and functions

Test Execution
  ├─ Runs test_func1()
  ├─ Runs test_func2()
  └─ Runs test_func3()

Result Collection
  └─ Aggregates pass/fail info

Report Generation
  └─ Displays summary to user
Myth Busters - 4 Common Misconceptions
Quick: Do you think a test function must return a value to be valid? Commit to yes or no before reading on.
Common Belief:Test functions must return True or False to indicate pass or fail.
Tap to reveal reality
Reality:Test functions do not return anything; they use assertions to signal failure by raising exceptions. If no assertion fails, the test passes.
Why it matters:Expecting return values can confuse beginners and lead to incorrect test writing, causing tests to be ignored or misinterpreted.
Quick: Do you think tests should depend on each other to save time? Commit to yes or no before reading on.
Common Belief:Tests can rely on previous tests to set up data or state to avoid repetition.
Tap to reveal reality
Reality:Tests should be independent and self-contained. Dependencies cause flaky tests and make debugging hard.
Why it matters:Dependent tests can pass or fail unpredictably, hiding real bugs and wasting developer time.
Quick: Do you think pytest runs tests in the order they appear in the file? Commit to yes or no before reading on.
Common Belief:Pytest runs tests in the order they are written in the file.
Tap to reveal reality
Reality:Pytest does not guarantee test order; tests may run in any order or even in parallel.
Why it matters:Assuming order can cause hidden bugs if tests rely on side effects from previous tests.
Quick: Do you think a failing assertion always means your code is wrong? Commit to yes or no before reading on.
Common Belief:If a test assertion fails, the code under test is definitely broken.
Tap to reveal reality
Reality:A failing test can also mean the test itself is incorrect or outdated.
Why it matters:Blindly trusting failing tests can waste time chasing non-existent bugs or ignoring real issues.
Expert Zone
1
Pytest's assert rewriting transforms simple assert statements into rich error messages without extra code.
2
Test functions can be dynamically generated or parameterized to cover many cases with minimal code duplication.
3
Pytest supports fixtures that inject setup and teardown logic, keeping test functions clean and focused.
When NOT to use
Test functions are not suitable for testing asynchronous code without async support; use pytest-asyncio or similar plugins instead. For UI testing, use specialized tools like Selenium or Playwright. For performance testing, use dedicated profiling tools rather than simple test functions.
Production Patterns
In real projects, test functions are grouped into modules and folders by feature. They use fixtures for setup, parameterization for coverage, and markers to categorize tests (e.g., slow, integration). Continuous integration systems run these tests automatically on code changes.
Connections
Unit Testing
Test functions are the basic building blocks of unit testing.
Understanding test functions clarifies how unit tests isolate and verify small code parts.
Continuous Integration (CI)
Test functions run automatically in CI pipelines to catch bugs early.
Knowing test functions helps grasp how automated testing fits into modern software delivery.
Scientific Method
Test functions embody hypothesis testing by checking if code behaves as expected.
Seeing tests as experiments helps appreciate their role in validating assumptions and learning from failures.
Common Pitfalls
#1Writing test functions that depend on each other's side effects.
Wrong approach:def test_a(): global shared shared = 5 def test_b(): assert shared == 5
Correct approach:def test_a(): value = 5 assert value == 5 def test_b(): value = 5 assert value == 5
Root cause:Misunderstanding that tests run independently and should not share or rely on global state.
#2Using print statements instead of assertions to check results.
Wrong approach:def test_sum(): print(2 + 2 == 4)
Correct approach:def test_sum(): assert 2 + 2 == 4
Root cause:Confusing output for verification; tests must use assertions to signal pass/fail.
#3Naming test functions without the 'test_' prefix so pytest ignores them.
Wrong approach:def check_addition(): assert 1 + 1 == 2
Correct approach:def test_addition(): assert 1 + 1 == 2
Root cause:Not following pytest naming conventions prevents test discovery.
Key Takeaways
Test functions are simple Python functions named with 'test_' that use assertions to check code correctness.
Pytest automatically finds and runs test functions, reporting clear pass or fail results.
Tests must be independent, self-contained, and use assertions, not print statements or return values.
Understanding pytest's discovery and execution helps write effective and reliable tests.
Marking expected failures and organizing tests properly improves test suite maintenance and clarity.

Practice

(1/5)
1. What is the main purpose of a test function in pytest?
easy
A. To create user interfaces
B. To run the program faster
C. To check if the code works as expected
D. To store data permanently

Solution

  1. Step 1: Understand the role of test functions

    Test functions are written to verify that the code behaves correctly.
  2. Step 2: Identify the main goal

    The main goal is to check if the code works as expected, catching bugs early.
  3. Final Answer:

    To check if the code works as expected -> Option C
  4. Quick Check:

    Test functions = Verify code correctness [OK]
Hint: Test functions verify code behavior, not speed or UI [OK]
Common Mistakes:
  • Thinking test functions improve program speed
  • Confusing test functions with UI code
  • Assuming test functions store data
2. Which of the following is the correct way to name a test function in pytest?
easy
A. check_function()
B. TestFunction()
C. function_test()
D. test_function()

Solution

  1. Step 1: Recall pytest naming rules

    Pytest requires test functions to start with 'test_' to be recognized automatically.
  2. Step 2: Identify the correct naming

    Only 'test_function()' starts with 'test_', so it is correct.
  3. Final Answer:

    test_function() -> Option D
  4. Quick Check:

    Test function names start with 'test_' [OK]
Hint: Test functions must start with 'test_' prefix [OK]
Common Mistakes:
  • Using names without 'test_' prefix
  • Capitalizing function names incorrectly
  • Placing 'test' at the end of the name
3. What will be the result of running this pytest test function?
def test_sum():
    result = 2 + 3
    assert result == 5
medium
A. Test passes successfully
B. Test fails with AssertionError
C. SyntaxError occurs
D. Test is skipped automatically

Solution

  1. Step 1: Analyze the test code

    The function calculates 2 + 3 and stores in 'result'.
  2. Step 2: Check the assertion

    The assertion checks if 'result' equals 5, which is true.
  3. Final Answer:

    Test passes successfully -> Option A
  4. Quick Check:

    2 + 3 == 5 means test passes [OK]
Hint: If assert condition is true, test passes [OK]
Common Mistakes:
  • Assuming assertion fails when it is true
  • Confusing syntax errors with assertion errors
  • Thinking tests skip without skip decorators
4. Identify the error in this pytest test function:
def test_multiply():
    result = 4 * 5
    assert result = 20
medium
A. Incorrect assert syntax using '=' instead of '=='
B. Function name does not start with 'test_'
C. Multiplication operator '*' is invalid
D. Missing return statement in test function

Solution

  1. Step 1: Check the assert statement syntax

    The assert statement uses '=' which is assignment, not comparison.
  2. Step 2: Identify correct syntax

    Assert requires '==' to compare values, so '=' causes a syntax error.
  3. Final Answer:

    Incorrect assert syntax using '=' instead of '==' -> Option A
  4. Quick Check:

    Use '==' in assert, not '=' [OK]
Hint: Assert needs '==' for comparison, '=' causes error [OK]
Common Mistakes:
  • Using '=' instead of '==' in assert
  • Ignoring function naming rules
  • Thinking return is needed in test functions
5. You want to test a function that returns the maximum number from a list. Which pytest test function below correctly tests this behavior including an edge case for an empty list?
def max_number(numbers):
    return max(numbers)

# Choose the correct test function:
hard
A. def test_max_number(): assert max_number([1, 3, 2]) == 3 assert max_number([]) == None
B. def test_max_number(): assert max_number([1, 3, 2]) == 3 import pytest with pytest.raises(ValueError): max_number([])
C. def test_max_number(): assert max_number([1, 3, 2]) == 2 assert max_number([0]) == 0
D. def test_max_number(): assert max_number([1, 3, 2]) == 3 assert max_number([1, 3, 2]) == 1

Solution

  1. Step 1: Understand max() behavior on empty list

    Calling max([]) raises ValueError, so test must expect this error.
  2. Step 2: Check which test handles empty list correctly

    def test_max_number(): assert max_number([1, 3, 2]) == 3 import pytest with pytest.raises(ValueError): max_number([]) uses pytest.raises to check for ValueError, correctly testing the edge case.
  3. Final Answer:

    Test function that asserts max and expects ValueError on empty list -> Option B
  4. Quick Check:

    Use pytest.raises for exceptions in tests [OK]
Hint: Use pytest.raises to test expected errors [OK]
Common Mistakes:
  • Assuming max([]) returns None instead of error
  • Wrong expected max value in assertions
  • Testing same input with conflicting expected outputs
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard