PyTest Tutorial: Install, Write, and Run Python Tests with Confidence
What is PyTest?
PyTest is a powerful, open‑source testing framework that lets developers write concise, scalable test cases for Python projects—be it unit tests, integration tests, or end‑to‑end API checks. It supports parallel execution, fixture injection, parameterization, and rich reporting out of the box.
Why Choose PyTest?
- Simple, readable syntax that reduces boilerplate
- Automatic test discovery and execution
- Run specific tests or groups with
-kand markers - Built‑in support for parallel runs via
pytest-xdist - Extensible through fixtures, hooks, and plugins
- Free and actively maintained by the community
Installing PyTest
Install the latest stable release with pip:
pip install pytest
Verify the installation:
pytest --version
For specific version control, you can pin to a release, e.g., pip install pytest==7.4.0.
Getting Started: A Basic Test
Create a project directory and add a test file named test_sample1.py:
import pytest
def test_file1_method1():
x = 5
y = 6
assert x + 1 == y, "Addition failed"
assert x == y, "Values should match"
def test_file1_method2():
x = 5
y = 6
assert x + 1 == y, "Addition failed"
Run the test suite:
pytest
Output example:
==================== test session starts ====================
collected 2 items
test_sample1.py F. [100%]
=================================== FAILURES ===================================
...
Understanding Assertions
PyTest assertions behave like standard Python assert statements. On failure, the test stops executing and PyTest reports the exact location and message:
assert "hello" == "Hai", "Mismatched greeting"
Test Discovery Rules
- Files must begin with
test_or end with_test.py. - Test functions must start with
test_. - Other files or functions are ignored unless explicitly specified.
Running Specific Tests
Execute all tests in a directory:
pytest
Run a single file:
pytest test_sample1.py
Filter by substring:
pytest -k method1 -v
Run by marker:
pytest -m set1
Parallel Execution
Install the xdist plugin and launch a 4‑worker parallel run:
pip install pytest-xdist pytest -n 4
Using Fixtures
Define reusable setup logic once and inject it into tests:
import pytest
@pytest.fixture
def supply_data():
return [25, 35, 45]
def test_compare_with_first(supply_data):
assert supply_data[0] == 25
Place fixture code in conftest.py to share across multiple test modules.
Parameterized Tests
Run a single test with many inputs:
import pytest
@pytest.mark.parametrize("a, b, expected", [(5, 5, 10), (3, 5, 8)])
def test_add(a, b, expected):
assert a + b == expected
Skipping and Expected Failures
Use markers to skip or expect failures without polluting the results:
import pytest
@pytest.mark.skip(reason="Feature not yet available")
def test_future_feature():
pass
@pytest.mark.xfail(reason="Known bug")
def test_known_issue():
assert 1 == 2
Generating XML Reports
Generate a JUnit‑compatible XML file for CI pipelines:
pytest -v --junitxml=result.xml
Practical Example: Testing a Public API
Below is a minimal framework that exercises https://reqres.in/:
# conftest.py
import pytest
@pytest.fixture
def base_url():
return "https://reqres.in/api"
# test_list_user.py
import requests, json
import pytest
@pytest.mark.parametrize("user_id, first_name", [(1, "George"), (2, "Janet")])
def test_valid_user(base_url, user_id, first_name):
resp = requests.get(f"{base_url}/users/{user_id}")
data = json.loads(resp.text)
assert resp.status_code == 200
assert data["data"]["id"] == user_id
assert data["data"]["first_name"] == first_name
def test_invalid_user(base_url):
resp = requests.get(f"{base_url}/users/50")
assert resp.status_code == 404
# test_login_user.py
import requests, json
import pytest
def test_login_success(base_url):
payload = {"email": "test@test.com", "password": "something"}
resp = requests.post(f"{base_url}/login/", data=payload)
data = json.loads(resp.text)
assert resp.status_code == 200
assert data["token"] == "QpwL5tke4Pnpja7X"
def test_login_missing_password(base_url):
payload = {"email": "test@test.com"}
resp = requests.post(f"{base_url}/login/", data=payload)
data = json.loads(resp.text)
assert resp.status_code == 400
assert data["error"] == "Missing password"
Conclusion
This tutorial covered installing PyTest, writing clear tests, using fixtures and markers, running tests in parallel, generating XML reports, and building a simple API test suite. With these foundations, you can scale your Python testing practices confidently.
Python
- How to Install WordPress on Google Cloud: A Step‑by‑Step Guide
- Coded UI Test Automation Framework: A Comprehensive Beginner’s Guide
- Spring Framework 2026: Comprehensive Overview, Features, Architecture, MVC, AOP, and Installation Guide
- Install Python and PyCharm on Windows: Step‑by‑Step Guide
- Master Python Unit Testing with PyUnit: A Practical Guide & Example
- Exploring 6G: The Future of Ultra-Fast Connectivity
- Expert Guide: Installing Dock Levelers for Maximum Efficiency
- Master Arduino Multithreading with Protothreading: A Step‑by‑Step Tutorial
- Copper Brazing Explained: Techniques & Tips for Strong, Reliable Connections
- Megohmmeter Explained: The Essential Tool for High-Resistance Electrical Testing