These built-ins cover most everyday test needs and are safer than hand-rolled temp dirs or global patches.
pytest ships fixtures you can request by name anywhere:
- `tmp_path`: a unique, empty
pathlib.Pathdirectory per test. Write files there instead of the working directory.tmp_path_factoryis the session-scoped variant. Old directories are cleaned up automatically, keeping the last few runs for inspection. - `capsys`: captures
stdoutandstderr;capsys.readouterr()returns an object with.outand.errand resets the buffer.capfddoes the same at file descriptor level, catching output from subprocesses and C extensions. - `monkeypatch`: temporarily changes things and undoes them after the test:
setattr(obj, "name", value),setenv("API_KEY", "x"),delenv,setitem(dict, key, value),chdir(path),syspath_prepend. - `caplog`: captures log records (covered later).
- `request`: information about the requesting test, used inside fixtures.
Because every change made through monkeypatch is reverted at teardown, tests can't leak modified environment variables or patched functions into each other, which is the main danger of patching by hand.
pytest --fixtures lists every available fixture, including those from plugins and your conftest files, with their docstrings.
Example
# test_builtins.py
import os
def save_report(path, lines):
path.write_text("\n".join(lines))
print(f"saved {len(lines)} lines")
def api_url():
return os.environ.get("API_URL", "https://api.example.com")
def test_save_report(tmp_path, capsys):
target = tmp_path / "report.txt"
save_report(target, ["a", "b"])
assert target.read_text() == "a\nb"
assert capsys.readouterr().out == "saved 2 lines\n"
def test_api_url_override(monkeypatch):
monkeypatch.setenv("API_URL", "http://localhost:8000")
assert api_url() == "http://localhost:8000"
def test_api_url_default(monkeypatch):
monkeypatch.delenv("API_URL", raising=False)
assert api_url() == "https://api.example.com"Remember
- tmp_path: fresh temp directory per test
- capsys.readouterr() returns captured .out and .err
- monkeypatch changes env, attributes and dicts and undoes them
- pytest --fixtures lists everything available
Watch out for
- Setting os.environ directly in a test and breaking later tests that expect the default.