How to use the command 'pytest' (with examples)
Pytest is a powerful Python testing framework that makes it easy to write simple as well as scalable test cases for applications and libraries. With its detailed error reporting, flexible test discovery, and the ability to easily run a subset of tests, pytest is widely used by developers to ensure that their code behaves as expected. Offering plugins and various command-line options, pytest provides versatility and simplicity in running tests, making it a preferred choice for both beginners and experienced developers. The following sections will explore different use cases of running tests using pytest, showcasing the flexibility and functionality it offers to users through specific command options.
Use case 1: Run tests from specific files
Code:
pytest path/to/test_file1.py path/to/test_file2.py
Motivation:
When you are interested in executing tests from certain files only, especially when working on large projects, this command comes in handy. By specifying file paths directly, you can target specific areas of your codebase, allowing for a more focused testing approach. This can be particularly useful during development when changes are limited to certain modules, and running all tests would be unnecessarily time-consuming.
Explanation:
pytest
: Invokes the pytest testing framework.path/to/test_file1.py path/to/test_file2.py
: Specifies the paths to the test files you wish to run. Here, you can list one or more paths, separated by spaces, to selectively execute the tests contained in those files.
Example Output:
============================= test session starts =============================
collected 4 items
path/to/test_file1.py .. [ 50%]
path/to/test_file2.py .. [100%]
============================== 4 passed in 0.04s ==============================
Use case 2: Run tests with names matching a specific keyword expression
Code:
pytest -k expression
Motivation:
This use case is particularly helpful when you need to run only a subset of your tests that correspond to a particular functionality or feature. By using keyword expressions, you can efficiently filter and run tests based on partial matches to test names and node IDs. It allows targeted testing, which speeds up the development cycle by focusing on areas affected by recent changes.
Explanation:
pytest
: Begins the invocation of pytest.-k
: This option selects tests that match the specified expression. The expression is checked against the test names and node IDs, allowing for a flexible filtering mechanism.
Example Output:
============================= test session starts =============================
collected 10 items / 6 deselected / 4 selected
test_module.py::test_feature_a PASSED [ 25%]
test_module.py::test_feature_b PASSED [ 50%]
test_module.py::test_feature_c PASSED [ 75%]
test_module.py::test_feature_d PASSED [100%]
========================== 4 passed, 6 deselected in 0.03s ====================
Use case 3: Exit as soon as a test fails or encounters an error
Code:
pytest --exitfirst
Motivation:
While developing software, it’s often useful to stop the test run immediately upon encountering a failure. This way, you can immediately address and investigate the cause of the failing test without waiting for the entire test suite to run. This use case is ideal when performing iterative development and debugging, as it quickly highlights the first point of failure, allowing developers to take corrective action without delay.
Explanation:
pytest
: Initiates the pytest run.--exitfirst
: Instructs pytest to stop execution immediately after the first failure or error is encountered.
Example Output:
============================= test session starts =============================
collected 5 items
test_functions.py::test_success PASSED [ 20%]
test_functions.py::test_failure FAILED [ 40%]
- Test aborted due to failure.
================================ FAILURES =====================================
___________________________ test_functions.py::test_failure ___________________
...
AssertionError: assert 1 == 2
========================= 1 failed, 1 passed in 0.02s =========================
Use case 4: Run tests matching or excluding markers
Code:
pytest -m marker_name1 and not marker_name2
Motivation:
In larger test suites, it’s necessary to distinguish tests by categories or types using markers. By using markers, you can tag tests based on their purpose, component, or any other criteria you define. This use case allows you to run tests that are marked with certain identifiers while excluding others, providing a high level of control over which tests are run based on their relevance to the current task or goal.
Explanation:
pytest
: Starts the process of running tests with pytest.-m
: This option selects tests that have been associated with specific markers.marker_name1
: Represents the marker you want to include in the test run.and not marker_name2
: Excludes tests that have this particular marker.
Example Output:
============================= test session starts =============================
collected 10 items / 7 deselected / 3 selected
test_feature_set.py::test_case_1 PASSED [ 33%]
test_feature_set.py::test_case_2 PASSED [ 67%]
test_feature_set.py::test_case_3 PASSED [100%]
========================== 3 passed, 7 deselected in 0.02s ====================
Use case 5: Run until a test failure, continuing from the last failing test
Code:
pytest --stepwise
Motivation:
For projects where understanding the sequence of failing tests is important, the stepwise execution of tests is extremely valuable. Using this option, you can run your test suite up to the point where a test fails and then fix the issue. Upon the next run, pytest will resume testing from the last failing test. This method aids in resolving issues one at a time without needing to rerun previously passed tests, enhancing debugging efficiency.
Explanation:
pytest
: Initiates the test run using pytest.--stepwise
: Directs pytest to walk through the tests stepwise, stopping at failures and resuming from the last point of failure in subsequent runs.
Example Output:
============================= test session starts =============================
collected 5 items
test_app.py::test_init PASSED [ 20%]
test_app.py::test_setup PASSED [ 40%]
test_app.py::test_process FAILED [ 60%]
- Test execution stopped.
================================ FAILURES =====================================
_____________________________ test_app.py::test_process _______________________
...
AssertionError: assert <unexpected result>
========================= 1 failed, 2 passed in 0.01s =========================
Use case 6: Run tests without capturing output
Code:
pytest --capture=no
Motivation:
Sometimes the real-time output of your test scripts (such as print statements or logs) can provide insights while tests are in progress. This can be particularly critical for debugging purposes, where you need immediate feedback from your test execution. Disabling output capturing with this command ensures that all print statements are immediately visible, which is invaluable during development or debugging sessions, allowing for quicker insights and responses to issues.
Explanation:
pytest
: Begins the execution of pytest.--capture=no
: Disables the capturing of output, ensuring that any standard output (e.g., viaprint
) or standard error messages are immediately displayed on the console.
Example Output:
============================= test session starts =============================
collected 3 items
test_output.py::test_logging
Printing log statement from within test
PASSED [ 33%]
test_output.py::test_warning
Printing warning message from within test
PASSED [ 67%]
test_output.py::test_error
Error: Something went wrong
PASSED [100%]
=========================== 3 passed in 0.03s ================================
Conclusion
Pytest is a powerful and flexible testing framework for Python that empowers developers to easily write and run test cases. Its various command-line options cater to different testing needs, whether you need to run specific tests, filter tests with keyword expressions, handle failures efficiently, work with test markers, or debug effectively with real-time outputs. Each use case presented above highlights different facets of pytest’s functionality, ensuring comprehensive testing solutions tailored to specific scenarios and project requirements.