Pytest patterns for Python APIs -- httpx AsyncClient, conftest fixtures, database isolation, parametrize edge cases, error response testing, auth flows, factory fixtures
99
99%
Does it follow best practices?
Impact
100%
1.23xAverage score across 5 eval scenarios
Passed
No known issues
A fitness club is launching an online membership portal. Their backend engineer built a FastAPI endpoint that registers new members, enforcing rules like unique email addresses, password length minimums, and required fields. The QA lead has noticed that the test suite only has one test — a happy-path registration — and is worried that all the validation logic is untested.
Your job is to write a comprehensive test file that covers: the various invalid registration payloads that should be rejected, the duplicate email scenario, and a test that creates multiple members with varied attributes to verify each gets a unique ID. The goal is to detect regressions in validation logic without duplicating large blocks of test code.
Produce the following files:
tests/conftest.py — fixture(s) needed by the teststests/test_registration.py — the test suitepyproject.toml — pytest configurationThe following files are provided as inputs. Extract them before beginning.
=============== FILE: app/main.py =============== from fastapi import FastAPI, HTTPException from pydantic import BaseModel, EmailStr, field_validator from typing import List
app = FastAPI()
_members: List[dict] = [] _next_id = 1
class MemberCreate(BaseModel): email: str name: str password: str
@field_validator("email")
@classmethod
def validate_email(cls, v):
if "@" not in v or "." not in v.split("@")[-1]:
raise ValueError("Invalid email format")
return v.lower()
@field_validator("name")
@classmethod
def validate_name(cls, v):
if not v.strip():
raise ValueError("Name cannot be blank")
return v
@field_validator("password")
@classmethod
def validate_password(cls, v):
if len(v) < 8:
raise ValueError("Password must be at least 8 characters")
return v@app.post("/members", status_code=201) async def register_member(body: MemberCreate): global _next_id for m in _members: if m["email"] == body.email: raise HTTPException(status_code=409, detail="Email already registered") member = {"id": _next_id, "email": body.email, "name": body.name} _members.append(member) _next_id += 1 return {"data": member}
@app.get("/members") async def list_members(): return {"data": _members}