CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/pytest-api-testing

Pytest patterns for Python APIs -- httpx AsyncClient, conftest fixtures, database isolation, parametrize edge cases, error response testing, auth flows, factory fixtures

99

1.23x
Quality

99%

Does it follow best practices?

Impact

100%

1.23x

Average score across 5 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

task.mdevals/scenario-3/

Test Input Validation and Duplicate Handling for a Membership Registration API

Problem/Feature Description

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.

Output Specification

Produce the following files:

  • tests/conftest.py — fixture(s) needed by the tests
  • tests/test_registration.py — the test suite
  • pyproject.toml — pytest configuration

Input Files

The 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}

evals

tile.json