Skip to content

Testing Guide

This guide covers testing strategies for FastHTML apps built with Faststrap.


Test Setup

pip install pytest httpx

Create tests/conftest.py:

import pytest
from fasthtml.test import TestClient
from main import app

@pytest.fixture
def client():
    return TestClient(app)

Testing Routes

def test_home_page(client):
    response = client.get("/")
    assert response.status_code == 200
    assert "Welcome" in response.text

def test_contact_form_get(client):
    response = client.get("/contact")
    assert response.status_code == 200
    assert "Contact Us" in response.text

def test_contact_form_post_valid(client):
    response = client.post("/contact", data={
        "name": "John Doe",
        "email": "john@example.com",
        "message": "Hello, this is a test message.",
    })
    assert response.status_code == 200
    assert "Message sent" in response.text

def test_contact_form_post_invalid(client):
    response = client.post("/contact", data={
        "name": "J",
        "email": "invalid",
        "message": "Short",
    })
    assert response.status_code == 200
    assert "Name must be at least 2 characters" in response.text

Testing HTMX Requests

def test_search_htmx(client):
    response = client.get(
        "/search",
        headers={"HX-Request": "true"},
        params={"q": "test"},
    )
    assert response.status_code == 200
    assert "result" in response.text.lower()

Testing Components

def test_button_renders():
    from faststrap import Button
    button = Button("Click me", variant="primary")
    html = to_html(button)
    assert 'class="btn btn-primary"' in html
    assert "Click me" in html

def test_card_renders():
    from faststrap import Card
    card = Card("Hello", header="Title")
    html = to_html(card)
    assert "Title" in html
    assert "Hello" in html

Testing Validation

def test_form_error_summary():
    from faststrap import FormErrorSummary
    errors = {"email": "Invalid email", "password": "Too short"}
    result = FormErrorSummary(errors)
    html = to_html(result)
    assert "Invalid email" in html
    assert "Too short" in html

def test_form_group_from_errors():
    from faststrap import FormGroupFromErrors, Input
    errors = {"email": "Invalid email"}
    result = FormGroupFromErrors(
        Input(name="email", type="email", value="bad"),
        "email",
        errors=errors,
    )
    html = to_html(result)
    assert "is-invalid" in html
    assert "Invalid email" in html

Test Patterns

Pattern 1: Happy Path

def test_create_item_success(client):
    response = client.post("/items", data={
        "name": "New Item",
        "description": "Test item",
    })
    assert response.status_code == 200
    assert "New Item" in response.text

Pattern 2: Validation Errors

def test_create_item_validation_error(client):
    response = client.post("/items", data={
        "name": "",
        "description": "",
    })
    assert response.status_code == 200
    assert "Name is required" in response.text

Pattern 3: Not Found

def test_item_not_found(client):
    response = client.get("/items/99999")
    assert response.status_code == 404

Running Tests

pytest tests/ -v

With coverage:

pytest tests/ --cov=src --cov-report=html

See Also