Skip to main content

PyPI version Python Development Status Maintenance PyPI License


💡 pytest-fail2skip

A pytest plugin that reports failures of marked tests as skipped, so known failures don't block your CI gate. The failure stays visible by default: conversion only happens when you opt in with --fail2skip.


📦 Installation

uv add pytest-fail2skip

🚀 Features

  • ✅ Opt-in conversion — failures are converted only when --fail2skip is passed; locally you still see the real failure
  • ✅ Targeted with raises= — convert only the expected exception; a new, different failure still fails the run
  • ✅ Reason in the output — shown in the -rs summary and exposed as the fail2skip_reason user property (JUnit XML, custom reporters)
  • ✅ Strict-markers safe — the marker is always registered, with or without the flag
  • ✅ Standalone — changes only pytest's own report; works with any reporting plugin

🛠️ How to Use

  1. Mark the known-failing test:
    import pytest
    
    @pytest.mark.fail2skip(reason="BUG-123: flaky upstream service", raises=ConnectionError)
    def test_sync_with_upstream():
        ...
    
  2. Run normally to see the real result: pytest
  3. In CI, opt in to the conversion: pytest --fail2skip

⚙️ Marker Reference

@pytest.mark.fail2skip(reason=None, raises=None)

Argument Description
reason Shown as fail2skip: <reason>. Can also be passed positionally. Defaults to no reason given.
raises An exception type or tuple of types. When set, only these failures are converted.

Behavior when --fail2skip is set:

Test result Reported as
Fails in the test body (and matches raises, if given) skipped
Fails with an exception not in raises failed
Passes passed
Errors in setup/teardown (e.g. a broken fixture) error — not converted

The marker can also be applied to a class, or to a whole module with pytestmark.


🤔 fail2skip vs. xfail

@pytest.mark.xfail is close, but differs in two ways that matter for a release gate:

  • Default direction — xfail hides the failure unless you pass --runxfail. fail2skip shows it unless you pass --fail2skip, so forgetting the flag fails loudly instead of silently.
  • Passing tests — a passing xfail test is reported as XPASS; a passing fail2skip test is simply passed.

If neither matters to you, xfail(raises=..., strict=False) is the built-in alternative.


▶️ Usage Examples

Convert only expected exceptions

Pass a single exception type:

import pytest

@pytest.mark.fail2skip(reason="BUG-123: upstream service is unstable", raises=ConnectionError)
def test_sync_with_upstream():
    ...

Or a tuple, to convert any of several known failures:

import pytest

@pytest.mark.fail2skip(
    reason="BUG-456: device sometimes drops the session",
    raises=(ConnectionError, TimeoutError),
)
def test_device_handshake():
    ...

Subclasses match too (ConnectionResetError is converted by raises=ConnectionError). Any other failure, such as an AssertionError from a real regression, still fails the run.

Enable in pytest.ini for CI

[pytest]
addopts =
    --fail2skip

Read the reason from a custom plugin

def pytest_runtest_logreport(report):
    reason = dict(report.user_properties).get("fail2skip_reason")
    if report.skipped and reason:
        print(f"{report.nodeid} was converted: {reason}")

🔁 Migrating from pytest-plugins

This plugin was previously the fail2skip feature of pytest-plugins. Both register the --fail2skip option, so don't install them together until you're on a pytest-plugins release without fail2skip. Changes when migrating:

  • Converted tests are now reported as skipped instead of xfailed.
  • The pytest-plugins report records them as skipped (not failed-skipped); the reason is available via user_properties.

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/my-addition
  3. Make your changes
  4. Commit your changes: git commit -m 'Add my addition'
  5. Push to the branch: git push origin feature/my-addition
  6. Open a Pull Request

Additions that promote clean, productive, and maintainable development are always welcome.


📄 License

MIT License — see LICENSE for details.


🙏 Thanks

Thanks for exploring this repository!
Happy coding!

GitHub   PyPI   Blog   LinkedIn

Metadata

Release files for pytest-fail2skip 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-fail2skip 1.0.0
File Size Uploaded Provenance Actions
pytest_fail2skip-1.0.0.tar.gz 6.0 kB Without provenance Details for pytest_fail2skip-1.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pytest-fail2skip 1.0.0
File Interpreter ABI Platform Actions
pytest_fail2skip-1.0.0-py3-none-any.whl Python 3 none any Details for pytest_fail2skip-1.0.0-py3-none-any.whl

Total release size: 12.4 kB

Release files / pytest_fail2skip-1.0.0.tar.gz

Download URL pytest_fail2skip-1.0.0.tar.gz
Size 6.0 kB
Tags Source
SHA-256 checksum
How to use checksums
3245699940cd6db49283d5cff42146eb6d6a7359c04a477b34f9286c14fe0ee6
BLAKE2b-256 checksum
How to use checksums
d421fbac56a27d4bcdb33f45bec8afbd91e435f2d4d25593b6186874c549be2d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pytest_fail2skip-1.0.0-py3-none-any.whl

Download URL pytest_fail2skip-1.0.0-py3-none-any.whl
Size 6.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
07998a361631c3d5f7b2b28d2c950d0ad48f2ceae0b169417815d12cb75c7434
BLAKE2b-256 checksum
How to use checksums
f3e903748a93b5d5cbbbcfc09f9feb7fbcbeb9b60f9fcd2ec62d4001eaca3729
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Security for pytest-fail2skip 1.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page