pkgcore.bugzilla.testing module¶
Replay helpers for testing code that talks to Bugzilla.
Subclassing the real urllib handler rather than patching urlopen keeps the
genuine urllib.request.Request in the loop, so header, method, body
and encoding mistakes are caught, and an unexpected request fails loudly
instead of reaching the network.
Nothing here imports pytest, so it is usable from a plain unittest suite or
a script; pkgcore.pytest.plugin wraps it in a bugzilla_cassette fixture that
downstream projects get for free.
A cassette used as a context manager takes over the opener every client builds, which is what lets it intercept a client constructed somewhere the test can’t reach, such as inside a CLI command:
with Cassette().expect_created(12345) as cassette:
main(["pkgdev", "bugs", "..."])
assert cassette.calls[0].body["summary"] == "cat/pkg-1: stablereq"
When the client is reachable, skip the patching and hand it the opener:
cassette = Cassette().expect_bugs({"id": 1, ...})
bugs = cassette.client().search()
- class pkgcore.bugzilla.testing.Call(method: str, url: str, headers: dict[str, str], body: dict[str, Any] | None)[source]¶
Bases:
objectA request the code under test actually made
- class pkgcore.bugzilla.testing.Cassette(*recordings: Recording, api_key: str | None = 'fake-api-key-for-tests', base_url: str = 'https://bugs.example.org')[source]¶
Bases:
objectQueued responses, the requests they answered, and a client to drive.
Recordings queued with
expect()are consumed in order; once they run out analways()fallback answers, or an unexpected request fails.- creates_bugs(first: int = 1) Cassette[source]¶
Answer every creation with the next id, for unbounded filing
- expect(*recordings: Recording) Cassette[source]¶
Queue responses, returning self so calls can be chained
- expect_error(code: int, message: str = 'error', status: int = 400) Cassette[source]¶
Queue a Bugzilla error body
- expect_whoami(name: str = 'dev@gentoo.org', real_name: str = 'A Dev', id: int = 7) Cassette[source]¶
- installed() Generator[Self, None, None][source]¶
Make every client built while active use this cassette
- transport(**kwargs: Any) UrllibTransport[source]¶
A transport wired to this cassette
- class pkgcore.bugzilla.testing.Recording(body: _Body = None, status: int = 200, raw: bytes | None = None, headers: dict[str, str]=<factory>, content_type: str = 'application/json; charset=UTF-8', reason: str = 'OK')[source]¶
Bases:
objectA canned response.
bodyis serialized to JSON, or may be a callable taking theCallfor responses that vary per request.rawoverrides it with exact bytes, for testing non-JSON replies.- body: _Body¶
- class pkgcore.bugzilla.testing.ReplayHandler(cassette: Cassette)[source]¶
Bases:
HTTPHandler,HTTPSHandlerServe queued recordings in order, recording what was asked for.
Subclasses both handlers so
urllib.request.build_opener()drops its defaults for either scheme; inheriting only the https one leaves plain http going to the network.