Frontend Labs
⋯

66. Running the tests and making a change

66.1 How the tests are built

pytest tests/test_requests.py -q -k "redirect" -x
pytest tests/ --cov=requests --cov-report=term-missing -q
# tests/test_requests.py  (a typical test: real HTTP against a local httpbin)
def test_HTTP_302_ALLOW_REDIRECT_GET(self, httpbin):
    r = requests.get(httpbin("redirect", "1"))
    assert r.status_code == 200
    assert r.history[0].status_code == 302
    assert r.history[0].is_redirect

The httpbin fixture (from pytest-httpbin, wrapped in tests/conftest.py) starts a local server and returns a URL builder. The tests exercise the full stack, through urllib3 and real sockets on 127.0.0.1, which is why they catch integration bugs that mocks would miss. test_lowlevel.py goes further: it runs a raw socket server (tests/testserver/server.py) that sends hand-written, sometimes malformed, HTTP responses to test edge cases like broken chunked encoding.

66.2 Exercise: add a feature in your fork

Add a default_timeout to your local copy, so a session can set one timeout for every request:

  1. Write the failing test first (Ch 20):
# tests/test_default_timeout.py
import pytest
import requests

def test_session_default_timeout(httpbin):
    s = requests.Session()
    s.default_timeout = 0.5
    with pytest.raises(requests.exceptions.ReadTimeout):
        s.get(httpbin("delay", "2"))        # httpbin waits 2 s before answering

def test_explicit_timeout_wins(httpbin):
    s = requests.Session()
    s.default_timeout = 0.5
    assert s.get(httpbin("delay", "1"), timeout=3).status_code == 200
  1. Implement it in Session.__init__ (self.default_timeout = None) and in Session.request (if timeout is None: timeout = self.default_timeout).
  2. Run the whole suite, ruff check, and read HISTORY.md to see how changes are recorded.

Then read how the ecosystem solved the same problem without changing requests: a custom HTTPAdapter subclass whose send sets a timeout when none is given. Compare the two designs: which one keeps the library's API smaller?

66.3 Contributing to open source, in general

  • Read CONTRIBUTING.md and the code of conduct; find the issue tracker's "good first issue" label.
  • Comment on an issue before writing a large change; maintainers may already have a plan, or a reason not to.
  • Keep pull requests small, with a test that fails before and passes after, and a description of why.
  • Documentation fixes, reproductions of reported bugs, and triage are real contributions, and the fastest way to learn a codebase.

Next codebases to read, in rough order of size: httpx (async and sync from one codebase), click (decorators and composition, Ch 14), rich (the data model and rendering), pydantic (metaclasses and a Rust core, Ch 30–31), fastapi (introspection, Ch 30.4), and Karpathy's nanoGPT (PyTorch training in about 300 lines, the companion to AI Ch 41).


Generated from real-life-python-guide.md · 8 Oct 2026 16:36