Pengujian fitur baru di Django 3.2


Django 3.2 merilis terbitan alfa pertamanya beberapa minggu lalu, dengan terbitan terakhir jatuh tempo pada bulan April. Ini berisi campuran fitur baru, yang dapat Anda baca di catatan rilis. Artikel ini berfokus pada perubahan dalam pengujian, beberapa di antaranya dapat diperoleh dari versi Django sebelumnya dengan paket backport



.





1.  setUpTestData() 

:





«, TestCase.setUpTestData()



».





setUpTestData()



— , .





TestCase.setUp()



- , :





from django.test import TestCase

from example.core.models import Book

class ExampleTests(TestCase):
    def setUp(self):
        self.book = Book.objects.create(title="Meditations")
      
      



- setUp()



. , . , setUp()



, .





setUpTestData()



TestCase



. setUp()



, :





from django.test import TestCase

from example.core.models import Book

class ExampleTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        cls.book = Book.objects.create(title="Meditations")
      
      



Django (rollback) , . , Django 3.2 rollback , . , .





, , :





from django.test import TestCase
from example.core.models import Book

class SetUpTestDataTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        cls.book = Book.objects.create(title="Meditations")

    def test_that_changes_title(self):
        self.book.title = "Antifragile"

    def test_that_reads_title_from_db(self):
        db_title = Book.objects.get().title
        assert db_title == "Meditations"

    def test_that_reads_in_memory_title(self):
        assert self.book.title == "Meditations"
      
      



Django 3.1, :





$ ./manage.py test example.core.tests.test_setuptestdata
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.F.
======================================================================
FAIL: test_that_reads_in_memory_title (example.core.tests.test_setuptestdata.SetUpTestDataTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/.../example/core/tests/test_setuptestdata.py", line 19, in test_that_reads_in_memory_title
    assert self.book.title == "Meditations"
AssertionError

----------------------------------------------------------------------
Ran 3 tests in 0.002s

FAILED (failures=1)
Destroying test database for alias 'default'...
      
      



, in-memory test_that_changes_title()



. Django 3.2 , in-memory. :





$ ./manage.py test example.core.tests.test_setuptestdata
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
...
----------------------------------------------------------------------
Ran 3 tests in 0.002s

OK
Destroying test database for alias 'default'...
      
      



Simon Charette django-testdata, Django. Django django - ,    @wrap_testdata



setUpTestData()



. , , .





( Django , , ).





2. faulthandler

:





DiscoverRunner faulthandler .





, . Python faulthandler «» , Python.  runner Django faulthandler. pytest, .





, faulthandler, C, , . , OS SIGSEGV , , . Python, :





import os
import signal

from django.test import SimpleTestCase


class FaulthandlerTests(SimpleTestCase):
    def test_segv(self):
        # Directly trigger the segmentation fault
        # signal, which normally occurs due to
        # unsafe memory access in C
        os.kill(os.getpid(), signal.SIGSEGV)
      
      



Django 3.1, :





$ ./manage.py test example.core.tests.test_faulthandler
System check identified no issues (0 silenced).
[1]    31127 segmentation fault  ./manage.py test
      
      



, , .





Django 3.2:





$ ./manage.py test example.core.tests.test_faulthandler
System check identified no issues (0 silenced).
Fatal Python error: Segmentation fault

Current thread 0x000000010ed1bdc0 (most recent call first):
  File "/.../example/core/tests/test_faulthandler.py", line 12 in test_segv
  File "/.../python3.9/unittest/case.py", line 550 in _callTestMethod
  ...
  File "/.../django/test/runner.py", line 668 in run_suite
  ...
  File "/..././manage.py", line 17 in main
  File "/..././manage.py", line 21 in <module>
[1]    31509 segmentation fault  ./manage.py test
      
      



 ( )





Faulthandler , Python, .





3. Timing ()

:





DiscoverRunner , .





manage.py test



--timing



, - :





$ ./manage.py test --timing
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
...
----------------------------------------------------------------------
Ran 3 tests in 0.002s

OK
Destroying test database for alias 'default'...
Total database setup took 0.019s
  Creating 'default' took 0.019s
Total database teardown took 0.000s
Total run took 0.028s
      
      



. Google Summer of Code 2020.





pytest, --durations N







- pytest «» (setup time) , , .





4. (callbacks)  transaction.on_commit() 

:





TestCase.captureOnCommitCallbacks()



(callbacks functions), transaction.on_commit()



. callbacks, TransactionTestCase



.





, .





, ,  ATOMIC_REQUESTS  Django, ( , !). transaction.on_commit() , , . , :





from django.db import transaction
from django.views.decorators.http import require_http_methods

from example.core.models import ContactAttempt


@require_http_methods(("POST",))
def contact(request):
    message = request.POST.get('message', '')
    attempt = ContactAttempt.objects.create(message=message)

    @transaction.on_commit
    def send_email():
        send_contact_form_email(attempt)

    return redirect('/contact/success/')
      
      



, , ContactAttempt.





, callback ( ), on_commit()



. Django callback , TestCase



, (rollback) , .





TransactionTestCase



, . , TestCase



, .





( TransactionTestCase



TestCase



.)





Django 3.2 captureOnCommitCallbacks()



, . callbacks . , :





from django.core import mail
from django.test import TestCase

from example.core.models import ContactAttempt


class ContactTests(TestCase):
    def test_post(self):
        with self.captureOnCommitCallbacks(execute=True) as callbacks:
            response = self.client.post(
                "/contact/",
                {"message": "I like your site"},
            )

        assert response.status_code == 302
        assert response["location"] == "/contact/success/"
        assert ContactAttempt.objects.get().message == "I like your site"
        assert len(callbacks) == 1
        assert len(mail.outbox) == 1
        assert mail.outbox[0].subject == "Contact Form"
        assert mail.outbox[0].body == "I like your site"
      
      



, captureOnCommitCallbacks()



, execute , , « ()» callbacks. HTTP- , , (callback). , !





captureOnCommitCallbacks()



Django, django-capture-on-commit-callbacks.





5. assertQuerysetEqual() 

:





TransactionTestCase.assertQuerysetEqual()



Django





assertQuerysetEqual() , !





Django 3.2, assertQuerysetEqual()



QuerySet . repr()



. , , , repr() strings



:





from django.test import TestCase

from example.core.models import Book


class AssertQuerySetEqualTests(TestCase):
    def test_comparison(self):
        Book.objects.create(title="Meditations")
        Book.objects.create(title="Antifragile")

        self.assertQuerysetEqual(
            Book.objects.order_by("title"),
            ["<Book: Antifragile>", "<Book: Meditations>"],
        )

      
      



, . repr()



.





Django 3.2 QuerySet



, :





from django.test import TestCase

from example.core.models import Book


class AssertQuerySetEqualTests(TestCase):
    def test_comparison(self):
        book1 = Book.objects.create(title="Meditations")
        book2 = Book.objects.create(title="Antifragile")

        self.assertQuerysetEqual(
            Book.objects.order_by("title"),
            [book2, book1],
        )
      
      



, . Django.





, Django 3.2 backport.






«Web- Python».





« django». django; : django-debug-toolbar, django-cms, django-cleanup ..








All Articles