I am currently testing my django model using pytest (and pytest-django), but I can not write a failing test case in which a required field is missing.
My Person
-model requires solely a name
and a company
. The other fields are nullable and therefore optional.
models.py
:
from django.db import models
# Create your models here.
class Person(models.Model):
name = models.CharField(max_length=64)
company = models.CharField(max_length=128)
position = models.CharField(max_length=64, null=True, blank=True)
date_of_birth = models.DateField(null=True, blank=True)
def __str__(self):
return (f"{self.name}"
(f", {self.position}" if self.position is not None else "")
f"({self.company})"
(f" born {self.date_of_birth}" if self.date_of_birth is not None else "")
)
test.py
from .models import Person
import pytest
from django.core.exceptions import ValidationError
pytestmark = pytest.mark.django_db
# Create your tests here.
def test_minimal_person():
"""Test if a minimal person can be created"""
valid_person = Person(name="Max Mustermann", company="ACME")
valid_person.save()
assert len(Person.objects.get_queryset()) == 1
def test_insufficient_params():
with pytest.raises(ValidationError):
invalid_person = Person()
invalid_person.save()
def test_missing_company():
with pytest.raises(ValidationError):
invalid_person = Person(name="Max")
invalid_person.save()
def test_missing_name():
with pytest.raises(ValidationError):
invalid_person = Person(company="ACME")
invalid_person.save()
def test_invalid_date_format():
"""Test if an invalid date format throws a ValidationError"""
with pytest.raises(ValidationError):
invalid_person = Person(name="Max", company="ACME", date_of_birth="not-a-date")
invalid_person.save()
The test test_invalid_date_format
and test_minimal_person
succeed, but the other ones do not throw an (expected) error.
What am I missing here?
CodePudding user response:
The save()
method doesn't do any validation for your fields, because they can go in the database when empty. See What happens when you save? The reason an invalid date throws a ValidationError
is because it's not a date. However, an empty string is still a string and can be stored in the database as such. To force validation, call the full_clean()
method of the model object.