I spent quite a lot of time to set some unit test, and one of the issues was the setting of some fields that I define to be nullable and blankable. Putting dummy values was not an issue, but I wonder: how to deal with fields that need to be blank, in particular for numbers?
Let me write as an example an extract of my code.
The model:
class Company(models.Model):
company_name = models.CharField("nom", max_length=200)
comp_slug = models.SlugField("slug")
logo = models.ImageField(upload_to="img/", null=True, blank=True)
street_num = models.IntegerField("N° de rue", null=True, blank=True)
street_cplt = models.CharField("complément", max_length=50, null=True, blank=True)
address = models.CharField("adresse", max_length=300)
@classmethod
def get_company(cls, comp_slug):
return cls.objects.filter(comp_slug=comp_slug).get()
The form:
class CompanyForm(forms.ModelForm):
company_name = forms.CharField(label="Société", disabled=True)
class Meta:
model = Company
exclude = []
The view:
def adm_options(request, comp_slug):
"""
Manage Company options
"""
company = Company.get_company(comp_slug)
comp_form = CompanyForm(request.POST or None, instance=company)
if request.method == "POST":
if comp_form.is_valid():
comp_form.save()
return render(request, "polls/adm_options.html", locals())
A simple unit test:
def create_dummy_company(name):
return Company.objects.create(
company_name=name,
comp_slug=slugify(name),
logo=SimpleUploadedFile(name='logo.jpg', content=b'content', content_type='image/jpeg'),
street_num=1,
street_cplt='',
address='dummy address'
)
class TestOptions(TestCase):
def test_adm_options_update(self):
self.company = create_dummy_company("Test company")
url = reverse("polls:adm_options", args=[self.company.comp_slug])
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.company.address = 'new address'
response = self.client.post(
reverse("polls:adm_options", args=[self.company.comp_slug]),
self.company.__dict__,
)
self.company.refresh_from_db()
self.assertEqual(response.status_code, 200)
self.assertEqual(self.company.address, "new address")
The key part is posting the form after the update. The different cases I met were the following:
No problem with the test as written above.
If I omit
street_numorstreet_cplt, the post raises:TypeError: Cannot encode None as POST data. Did you mean to pass an empty string or omit the value?
If I omit
logo, it raises:ValueError: The 'logo' attribute has no file associated with it.
This is my main issue as far as, in my opinion, the fields should stay blank with no error.
Then, what about number fields? How can I set
street_numto blank? If I trystreet_num='', it raises:ValueError: invalid literal for int() with base 10: ''
So how could I deal with that, to build a unit test that checks that I can post a form with no values for each single field set to null=True, blank=True?