docs
v1 Pricing Dashboard
Getting started / quickstart-pytest

Quickstart: pytest

A conftest.py fixture hands every test its own real inbox. The SDK is stdlib-only (Python 3.9+), so it works with requests-driven API tests, playwright-python, or whatever else drives your app.

1 · Install

Zero dependencies — the client is plain urllib under the hood.

terminal
$ pip install mailfixture

2 · Authenticate

Create a key in Dashboard → API keys and export it. The SDK reads MAILFIXTURE_API_KEY automatically — keep it in CI secrets, not in the repo.

.env / CI secret
MAILFIXTURE_API_KEY=mfx_••••••••••••••••••••

3 · The fixture

Session-scoped client, function-scoped inbox: every test gets a fresh address and tears it down afterward. The 15-minute TTL is the backstop for runs that die mid-flight.

conftest.py
import pytest
from mailfixture import MailFixture

@pytest.fixture(scope="session")
def mail():
    return MailFixture()  # reads MAILFIXTURE_API_KEY

@pytest.fixture
def inbox(mail):
    inbox = mail.create_inbox(ttl_seconds=900)
    yield inbox
    inbox.delete()

4 · Write the test

wait_for_otp() long-polls the server — it returns the moment the email lands or raises MailFixtureTimeout. No time.sleep, no retry loop, nothing to tune.

test_signup.py
import requests

APP = "https://staging.example.com"

def test_signup_sends_otp(inbox):
    requests.post(f"{APP}/api/signup", json={"email": inbox.address})

    otp = inbox.wait_for_otp(timeout=30)  # held open server-side

    r = requests.post(f"{APP}/api/verify",
                      json={"email": inbox.address, "code": otp})
    assert r.status_code == 200
tip Several emails racing into one inbox? Filter the wait: inbox.wait_for_otp(match="subject:code", timeout=30)match takes subject:, from:, and to: prefixes. Driving a browser instead? Swap requests for playwright-python's page and this reads like the Playwright quickstart.

5 · Run it

terminal
$ pytest test_signup.py

test_signup.py .                                    [100%]

========== 1 passed in 1.62s ==========

Parallelism with xdist

Inbox-per-test means pytest -n auto needs no coordination: no shared mailbox, no cross-worker message collisions, nothing to lock. The fixture above is already parallel-safe.

Next steps

Testing OTP flows
The flake-free patterns, in depth.
Quickstart: Playwright
The JS/TS version of this page.
Quickstart: Cypress
Same flow through cy.task.
Was this page useful? yes no Guide: Testing OTP flows →
ON THIS PAGE
edit this page ↗
report an issue ↗