Test Your Validator
Exit

Test Your Validator

Write unit tests that verify your custom date validator works correctly

💻

Writing code and entering commands is only available on desktop. Open this page on a larger screen to complete this chapter.

What makes these tests useful

Your validate_date_format method contains real logic: a null check, a format parse, and a custom error message. Each of those can have bugs. A unit test verifies each case directly — no server, no HTTP, just your code.

Compare this to testing Field(gt=0). That constraint is a single declaration handled entirely by Pydantic. There is no custom logic to test. But your date validator has branching (if v is not None), error handling (try/except), and a specific error message. Those are worth testing.

Three cases to test

A good test suite for a validator covers three scenarios:

  • Valid input: a correctly formatted date should be accepted
  • Invalid input: a badly formatted string should be rejected with a ValidationError
  • Edge case: None should still be allowed since the field is optional

Testing for errors with pytest.raises

When you expect code to raise an error, use pytest's with pytest.raises(...) block. Any code inside the block must raise the specified error, or the test fails.

with pytest.raises(ValidationError):
    Expense(description="Lunch", amount=10, category="food", date="banana")

This test passes only if creating an Expense with date="banana" raises a ValidationError.

Instructions

Write unit tests for your date validator.

  1. Add three imports, each on its own line: pytest, Expense from main, and ValidationError from pydantic.
  2. Define test_valid_date.
    • Create an Expense with description="Lunch", amount=12.50, category="food", date="2024-01-15".
    • Assert that expense.date equals "2024-01-15".
  3. Define test_invalid_date_format.
    • Open a with pytest.raises(ValidationError): block.
    • Inside it, create an Expense with description="Lunch", amount=12.50, category="food", date="banana".
  4. Define test_date_none_allowed.
    • Create an Expense with description="Lunch", amount=12.50, category="food" and no date argument.
    • Assert that expense.date is None.