Skip to main content

Pytest plugin for automatic integration test marking and management

Project description

pytest-mark-integration

PyPI version Python versions License

A pytest plugin for automatic integration test marking and management.

Features

  • ๐ŸŽฏ Automatic Test Marking: Automatically marks tests as integration tests based on file path patterns
  • ๐ŸŽ›๏ธ Flexible Configuration: Configure default behavior via pytest.ini or pyproject.toml
  • โšก Smart Test Ordering: Runs unit tests before integration tests for faster feedback
  • ๐Ÿšฆ Fail-Fast Support: Optionally skip integration tests when unit tests fail
  • ๐Ÿ”Œ Plugin Integration: Seamlessly integrates with pytest-cov and pytest-timeout
  • ๐ŸŽš๏ธ Command-Line Control: Override default behavior with --with-integration and --without-integration flags

Installation

Install using pip:

pip install pytest-mark-integration

Or using uv:

uv add pytest-mark-integration --dev

Quick Start

Once installed, the plugin automatically activates. By default:

  1. Tests are automatically marked if their file path contains integration
  2. Integration tests run by default (configurable)
  3. Unit tests run before integration tests (for faster feedback)

Example Test Structure

your_project/
โ”œโ”€โ”€ tests/
โ”‚   โ”œโ”€โ”€ unit/
โ”‚   โ”‚   โ””โ”€โ”€ test_utils.py           # Not marked (runs first)
โ”‚   โ”œโ”€โ”€ integration/
โ”‚   โ”‚   โ””โ”€โ”€ test_api.py              # Auto-marked as integration
โ”‚   โ””โ”€โ”€ test_db_integration.py       # Auto-marked (path contains "integration")

Running Tests

# Run all tests (including integration tests)
pytest

# Skip integration tests
pytest --without-integration

# Run only integration tests
pytest --with-integration -m integration

# Run tests with coverage (integration tests excluded from coverage by default)
pytest --cov

Configuration

Configuration Options

Configure via pytest.ini:

[pytest]
# Run integration tests by default (default: true)
run_integration_by_default = true

# Skip integration tests if unit tests fail (default: true)
fail_fast_on_unit_test_failure = true

Or via pyproject.toml:

[tool.pytest.ini_options]
run_integration_by_default = true
fail_fast_on_unit_test_failure = true

Command-Line Options

Option Description
--with-integration Run integration tests (overrides config)
--without-integration Skip integration tests (overrides config)
--integration-cover Include integration tests in coverage reports
--integration-timeout SECONDS Set timeout for integration tests (requires pytest-timeout)
--integration-timeout-method METHOD Timeout method: thread or signal (requires pytest-timeout)

How It Works

Automatic Marking

The plugin automatically adds the @pytest.mark.integration marker to tests when:

  1. The test file path contains the word integration (case-insensitive)
  2. The test is manually decorated with @pytest.mark.integration

Note: The plugin uses paths relative to the pytest root directory to avoid false positives from parent directory names containing "integration".

Examples of auto-marked tests:

# tests/integration/test_api.py - โœ… Auto-marked
def test_api_endpoint():
    pass

# tests/test_database_integration.py - โœ… Auto-marked
def test_db_connection():
    pass

# integration_tests/test_system.py - โœ… Auto-marked
def test_full_system():
    pass

# tests/unit/test_helpers.py - โŒ Not marked
def test_helper_function():
    pass

Test Execution Priority

The plugin ensures integration tests run after unit tests:

Execution Order:
1. Unit tests (no integration marker) โšก Fast
2. Integration tests (@pytest.mark.integration) ๐Ÿข Slower

This provides:

  • Faster feedback during development
  • Efficient CI/CD pipelines (fail fast on basic issues)

Fail-Fast Behavior

When fail_fast_on_unit_test_failure = true (default):

Unit Test โ†’ FAIL โŒ
  โ†“
Integration Tests โ†’ SKIPPED โญ๏ธ
  โ†“
Reason: "Skipping integration tests due to unit test failure"

This saves time by not running expensive integration tests when basic functionality is broken.

Manual Marking

You can still manually mark tests:

import pytest

@pytest.mark.integration
def test_external_api():
    """This test will be treated as an integration test"""
    pass

Integration with Other Plugins

pytest-cov (Coverage)

By default, integration tests do not contribute to coverage reports (since unit tests should cover all code).

# Integration tests excluded from coverage
pytest --cov

# Include integration tests in coverage
pytest --cov --integration-cover

pytest-timeout

Set timeouts specifically for integration tests:

# Set 60-second timeout for integration tests
pytest --integration-timeout 60

# Use signal-based timeout method
pytest --integration-timeout 60 --integration-timeout-method signal

pytest-xdist (Parallel Execution)

The plugin is compatible with pytest-xdist for parallel test execution:

# Run tests in parallel across 4 workers
pytest -n 4

Note: In parallel mode, fail-fast behavior may not work perfectly since tests are distributed across multiple processes.

Configuration Priority

The plugin respects the following priority order:

  1. Command-line flags (highest priority)

    • --with-integration โ†’ Always run integration tests
    • --without-integration โ†’ Always skip integration tests
  2. Configuration file (medium priority)

    • run_integration_by_default = true/false
  3. Default behavior (lowest priority)

    • Run integration tests (run_integration_by_default defaults to true)

Use Cases

Local Development

Fast feedback loop - skip slow integration tests:

# In pytest.ini
run_integration_by_default = false
pytest  # Only unit tests run

CI/CD Pipeline

Run all tests in CI:

# In pyproject.toml
run_integration_by_default = true
fail_fast_on_unit_test_failure = true
pytest  # All tests run, fail fast if unit tests fail

Pre-commit Hook

Quick validation before committing:

pytest --without-integration

Integration Test Suite

Run only integration tests:

pytest --with-integration -m integration

Examples

Example 1: Mixed Test Suite

# tests/unit/test_calculator.py
def test_add():
    assert 1 + 1 == 2  # Runs first

# tests/integration/test_api.py
def test_api_health():
    response = requests.get("http://api.example.com/health")
    assert response.status_code == 200  # Runs second

# tests/test_database_integration.py
def test_database_connection():
    db = Database()
    assert db.connect()  # Runs third (auto-marked due to filename)
$ pytest -v
tests/unit/test_calculator.py::test_add PASSED             [ 33%]
tests/integration/test_api.py::test_api_health PASSED      [ 66%]
tests/test_database_integration.py::test_database_connection PASSED [100%]

Example 2: Skip Integration Tests

$ pytest --without-integration -v
tests/unit/test_calculator.py::test_add PASSED             [100%]
tests/integration/test_api.py::test_api_health SKIPPED     (Integration tests skipped)
tests/test_database_integration.py::test_database_connection SKIPPED (Integration tests skipped)

Example 3: Fail-Fast Behavior

# tests/unit/test_calculator.py
def test_add():
    assert 1 + 1 == 3  # โŒ FAILS

# tests/integration/test_api.py
def test_api_health():
    # This test is skipped because unit test failed
    pass
$ pytest -v
tests/unit/test_calculator.py::test_add FAILED             [50%]
tests/integration/test_api.py::test_api_health SKIPPED     [100%]
(Skipping integration tests due to unit test failure)

Troubleshooting

Integration Tests Not Being Marked

Problem: Tests in integration paths aren't being marked.

Solution: Ensure the file path (not just the directory name) contains integration:

# โœ… Correct
tests/integration/test_api.py
tests/test_integration_api.py

# โŒ Won't work
int/test_api.py  # "integration" not in path

Note: The plugin uses paths relative to the pytest root directory. If you're running tests from a subdirectory, ensure the relative path from the project root contains "integration".

Integration Tests Still Running After Unit Test Failure

Problem: Integration tests run even when unit tests fail.

Solution: Enable fail-fast in configuration:

[pytest]
fail_fast_on_unit_test_failure = true

Coverage Reports Include Integration Tests

Problem: Integration tests are included in coverage reports.

Solution: Remove --integration-cover flag (it's disabled by default):

pytest --cov  # Integration tests excluded

Development

Setup Development Environment

# Clone repository
git clone https://github.com/yourusername/pytest-mark-integration.git
cd pytest-mark-integration

# Install dependencies with uv
uv sync --all-extras

# Or with pip
pip install -e ".[dev]"

Run Tests

make test

Code Quality

# Format code
make format

# Lint code
make lint

# Type check
make typecheck

Build and Publish

# Build distribution
make build

# Publish to TestPyPI
make publish-test

# Publish to PyPI
make publish

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Comparison with Similar Projects

This plugin combines and improves upon features from two existing projects:

Feature Comparison

Feature pytest-mark-integration (This Project) pytest-integration pytest-integration-mark
Auto-marking by path โœ… integration in path โŒ Manual only โœ… tests/integration/ folder only
Configurable folder โœ… Any path with "integration" โŒ N/A โœ… Via --integration-tests-folder
Default behavior โœ… Run by default (configurable) โœ… Run by default โŒ Skip by default
Smart test ordering โœ… Unit โ†’ Integration โœ… Unit โ†’ Integration โ†’ Slow โŒ No ordering
Fail-fast on unit failure โœ… Yes (configurable) โœ… Yes โŒ No
Multi-tier integration tests โŒ Single tier โœ… Two tiers (quick/slow) โŒ Single tier
Coverage integration โœ… Exclude by default โœ… Exclude by default โŒ Not handled
Timeout support โœ… Via --integration-timeout โœ… Via --integration-timeout โŒ No
Configuration file โœ… pytest.ini / pyproject.toml โŒ Command-line only โŒ Command-line only
CLI override โœ… --with/without-integration โœ… --with/without-integration โœ… --with-integration only
pytest-xdist compatible โœ… Yes โš ๏ธ Partial (documented limitation) โœ… Yes
Marker name @pytest.mark.integration @pytest.mark.integration_test @pytest.mark.integration
Python version 3.10+ Any 3.7+
Active maintenance โœ… 2025 โš ๏ธ Last updated 2020 โš ๏ธ Last updated 2021

Detailed Comparison

vs. pytest-integration

pytest-integration is the original project that pioneered integration test management in pytest. Our project builds upon its foundation with modern improvements:

Advantages of pytest-mark-integration:

  • โœ… Automatic path-based marking: No need to manually add @pytest.mark.integration_test to every test
  • โœ… Flexible configuration: Configure behavior via pytest.ini or pyproject.toml, not just command-line
  • โœ… Better defaults: Integration tests run by default (matches CI/CD workflows)
  • โœ… Simpler marker name: integration vs. integration_test
  • โœ… Modern codebase: Type hints, Python 3.10+, uses current pytest APIs
  • โœ… Better path detection: Uses relative paths from project root to avoid false positives

Advantages of pytest-integration:

  • โœ… Multi-tier tests: Supports both quick and slow integration tests (two-tier hierarchy)
  • โœ… Cascading fail-fast: Stops slow integration tests if quick integration tests fail

Best for:

  • pytest-mark-integration: Projects wanting automatic marking, modern Python, and simpler configuration
  • pytest-integration: Projects needing multi-tier integration test hierarchies

vs. pytest-integration-mark

pytest-integration-mark focuses on automatically marking tests in a specific folder. Our project extends this concept significantly:

Advantages of pytest-mark-integration:

  • โœ… Flexible path matching: Any path containing "integration", not just tests/integration/
  • โœ… Run by default: Better for CI/CD (skip integration tests locally, run in CI)
  • โœ… Smart ordering: Unit tests always run before integration tests
  • โœ… Fail-fast support: Skip integration tests when unit tests fail (saves time)
  • โœ… Coverage integration: Automatically excludes integration tests from coverage
  • โœ… Timeout support: Set timeouts specifically for integration tests
  • โœ… Configuration file: Persistent settings via pytest.ini or pyproject.toml
  • โœ… Both CLI options: --with-integration and --without-integration

Advantages of pytest-integration-mark:

  • โœ… Simpler: Fewer features, easier to understand
  • โœ… Skip by default: Integration tests won't run unless explicitly requested

Best for:

  • pytest-mark-integration: Production projects needing comprehensive integration test management
  • pytest-integration-mark: Simple projects wanting basic auto-marking with minimal configuration

Migration Guide

From pytest-integration

# Old (pytest-integration)
@pytest.mark.integration_test
def test_api():
    pass

@pytest.mark.slow_integration_test
def test_slow_api():
    pass
# New (pytest-mark-integration)
# Automatic marking - no decorator needed if in integration path!
def test_api():  # Auto-marked if in tests/integration/test_api.py
    pass

# Or manual marking with simpler name
@pytest.mark.integration
def test_api():
    pass

# Note: No slow_integration_test tier (use timeout instead)

Configuration:

# pytest-integration (command-line only)
pytest --without-integration

# pytest-mark-integration (persistent config)
[pytest]
run_integration_by_default = false

From pytest-integration-mark

# Old (pytest-integration-mark)
# File: tests/integration/test_api.py
def test_api():  # Auto-marked only in tests/integration/
    pass
# New (pytest-mark-integration)
# File: tests/integration/test_api.py
def test_api():  # Auto-marked (same behavior)
    pass

# File: tests/test_db_integration.py
def test_db():  # ALSO auto-marked (path contains "integration")
    pass

Command-line:

# pytest-integration-mark
pytest --with-integration  # Run integration tests

# pytest-mark-integration
pytest --with-integration   # Run integration tests
pytest --without-integration # Skip integration tests (new option!)
pytest                       # Run by default (configurable)

Why Choose pytest-mark-integration?

Choose this plugin if you want:

  1. ๐ŸŽฏ Zero-configuration auto-marking: Just name your files/folders with "integration"
  2. โš™๏ธ Flexible configuration: Persistent settings in config files, not just CLI
  3. โšก Smart execution: Unit tests first, fail-fast on failures
  4. ๐Ÿ”Œ Ecosystem integration: Works seamlessly with pytest-cov, pytest-timeout, pytest-xdist
  5. ๐Ÿ“Š Better defaults: Designed for modern CI/CD workflows
  6. ๐Ÿ› ๏ธ Active maintenance: Modern codebase with ongoing updates

Acknowledgments

Inspired by:

Changelog

See CHANGELOG.md for version history.

Support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pytest_mark_integration-1.0.0.tar.gz (25.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pytest_mark_integration-1.0.0-py3-none-any.whl (14.0 kB view details)

Uploaded Python 3

File details

Details for the file pytest_mark_integration-1.0.0.tar.gz.

File metadata

File hashes

Hashes for pytest_mark_integration-1.0.0.tar.gz
Algorithm Hash digest
SHA256 b085bd4ceb9f9ad1a4c1defc342fec29b4aa024c43da02cc6b6dd09c270b7483
MD5 e1ed88578e47090a0ae2d2707cee46b6
BLAKE2b-256 b8463c04f90d1c32dc50d98f9fef487fdbaa45229dd5295d689b794e49492bcc

See more details on using hashes here.

File details

Details for the file pytest_mark_integration-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pytest_mark_integration-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2eb4a796169aafc0f057c86d983a4d54a46626468ffc153fda2f066522b527af
MD5 74538e495b2ee72210a16ee1ec7c3c51
BLAKE2b-256 e218a1731c8594dd61e5bb6485c2e7e35c8e807deba4a9b63a5233f95c6f3515

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page