Django Testing ************** .. highlight:: python Download ======== :: assert HTTPStatus.OK == response.status_code content = io.BytesIO(b"".join(response.streaming_content)) assert "1-2-3" == content.read().decode("utf-8").strip() assert ( 'inline; filename="{}-1-2-3.txt"'.format(record.pk) == response["Content-Disposition"] ) CSV --- .. tip:: The view under test is :doc:`dev-django-view`. :: import io @pytest.mark.django_db def test_report_consent_user(): with io.StringIO() as response: result = _report(response) response.seek(0) result = response.readlines() header = "name,email,consent\r\n" assert [ header, "A Kimber,a@test.com,Y\r\n", "B Orange,b@b.com,\r\n", ] == result Database ======== :: from django.db import IntegrityError with pytest.raises(IntegrityError): # ... # not sure if the following is sensible (or not)? assert "duplicate key value violates unique constraint" in str(e.value) assert "pipeline_pipelinestep_pipeline_id_order" in str(e.value) Errors ====== :: form = response.context["form"] assert { "comments": ["This field is required."], "result": ["This field is required."], } == form.errors factory ======= If you have a factory which includes a ``FileField``:: import factory class DocumentFactory(factory.django.DjangoModelFactory): class Meta: model = Document document_file = factory.django.FileField(filename="my_document.doc") You can supply a different file in the actual test as follows:: from django.core.files.uploadedfile import SimpleUploadedFile document = DocumentFactory( document_file=SimpleUploadedFile("your_document.doc", b"file contents"), ) Or:: sample_pdf_file = pathlib.Path( pathlib.Path.cwd(), "document", "tests", "data", "sample.pdf" ) with open(sample_pdf_file, "rb") as f: document_file = SimpleUploadedFile("my_blank_form.pdf", f.read()) document = DocumentFactory(document_file=document_file) .. tip:: Don't forget ``rb`` in the ``open`` if this is a binary file. Initial ======= Use ``form.initial``:: assert HTTPStatus.OK == response.status_code assert "form" in response.context form = response.context["form"] assert user == form.initial["name"] If there are no initial values set on a form:: assert {} == form.initial Messages ======== :: assert "messages" in response.context messages = response.context["messages"] assert 1 == len(messages) assert ["Cannot create invoice - no hourly rate"] == [ str(x) for x in messages ] Queryset ======== :: form = response.context["form"] name = form.fields["name"] assert ["a", "c"] == [x.username for x in name.queryset] RequestFactory ============== It might be easier to test views using a request factory. ``pytest-django`` includes ``rf``, a request factory fixture:: def test_title(rf): url = reverse("mailing.list") request = rf.post(url, data={"category_id": category_id}) request.user = UserFactory(is_staff=True) response = MailingListReportFormView.as_view()(request) assert HTTPStatus.FOUND == response.status_code .. note:: If the view needs an authenticated user, we set the ``user`` on the request.