v0.166.0
 1"""
 2Skipping a test from inside its body.
 3
 4`@skip` declares that a test never runs. `skip_test()` is for the case only
 5the running test can see — a condition computed from its arguments, or an
 6outcome it has to try for first.
 7"""
 8
 9from typing import NoReturn
10
11__all__ = ["TestSkipped", "skip_test"]
12
13
14class TestSkipped(BaseException):
15    """
16    Raised by `skip_test()`. The runner reports the test as skipped.
17
18    A BaseException, so an `except Exception:` in the test or in the code it
19    exercises can't swallow the skip and let the test carry on.
20    """
21
22    def __init__(self, reason: str) -> None:
23        super().__init__(reason)
24        self.reason = reason
25
26
27def skip_test(reason: str) -> NoReturn:
28    """
29    Stop this test here and report it as skipped, with the reason shown.
30
31        def test_upload_to_bucket():
32            if not bucket_is_reachable():
33                skip_test("No bucket reachable from this machine")
34            ...
35
36    Everything the test entered is still exited: `with` blocks unwind, and
37    the database transaction is rolled back like any other test's.
38    """
39    if not isinstance(reason, str) or not reason.strip():
40        raise TypeError('skip_test() requires a reason: skip_test("why")')
41    raise TestSkipped(reason)