Testy

prawie jednostkowe w Django

Przemek Lewandowski

@haxoza

O mnie

Przegląd prezentacji

  • Dlaczego testy jednostkowe
  • Testowanie z Django
    • Narzędzia
    • Problemy
  • Djet na ratunek
    • Przegląd
    • Przykłady
  • Jak zacząć z Djet

Testy jednostkowe

  • Wczesne wykrywanie błędów
  • Odeseparowują implementacje
  • Szybkie w wykonaniu
  • Żywa dokumentacja

Testowanie w Django

  • Modele
  • Formulrze
  • Widoki
  • ...

Testowanie widoków

  • django.tests.TestCase
  • django.tests.Client
  • django.tests.RequestFactory

django.tests.TestCase

  • Dodatkowe asercje
  • Wczytywanie fixture-ów
  • Każdy test jako transakcja
  • Tworzy instancję django.tests.Client

django.tests.testcases

Django fixtures

factory_boy

https://github.com/rbarrois/factory_boy

django.tests.Client

  • Udaje przeglądarkę
  • Integruje się z django.contrib.auth
  • Przechodzi przez wszystkie
    warstwy Django
  • Do testów integracyjnych

Django Middlewares

django.tests.RequestFactory

  • Samodzielnie wywołanie widoku 
  • Omijamy middleware-y
  • Nadzieja na testy jednostkowe
  • Trudne w użyciu

Problemy 

  • Testy integracyjne widoków
  • Wszystkie warstwy aplikacji
  • Mocne związanie komponentów
  • Narzut middleware-ów
  • Domyślny FileStorage pisze po dysku

Djet

na ratunek

Django Extended Tests

https://github.com/sunscrapers/djet

Cechy Djet

  • Pozwala łatwo testować jednostkowo widoki
  • Wspiera widoki klasowe i funkcyjne
  • Uruchamia tylko podane middleware-y
  • Wspiera autoryzację django.contrib.auth

Djet w akcji

class YourViewTest(assertions.StatusCodeAssertionsMixin,
                   assertions.MessagesAssertionsMixin,
                   testcases.ViewTestCase):
    view_class = YourView
    view_kwargs = {'some_kwarg': 'value'}
    middleware_classes = [
        SessionMiddleware,
        (MessageMiddleware, testcases.MiddlewareType.PROCESS_REQUEST),
    ]

    def test_post_should_redirect_and_add_message_when_next_parameter(self):
        user = UserFactory()
        request = self.factory.post(data={'next': '/'}, user=user)

        response = self.view(request)

        self.assert_redirect(response, '/')
        self.assert_message_exists(request, messages.SUCCESS, 'Success!')

Cechy Djet - cd.

  • Ułatwia operacje na plikach
  • Integruje się z Django Rest Framework
  • Zawiera dodatkowe asercje
  • Jeszcze więcej asercji

Djet combo

class TestModel(models.Model):
    field = models.CharField(max_length=100)
    file = models.FileField(upload_to='files')

class CreateAPIView(generics.CreateAPIView):
    model = models.TestModel

class CreateAPIViewTest(assertions.StatusCodeAssertionsMixin,
                        files.InMemoryStorageMixin,
                        restframework.APIViewTestCase):
    view_class = CreateAPIView

    def test_post_should_create_model(self):
        data = {
            'field': 'test value',
            'file': files.create_inmemory_file('test.txt', content=b'Hello multipart!'),
        }
        request = self.factory.post(data=data, format='multipart')

        response = self.view(request)

        self.assert_status_equal(response, status.HTTP_201_CREATED)

Asercje w Djet

  • response status codes (StatusCodeAssertionsMixin)
  • emails (EmailAssertionsMixin)
  • messages (MessagesAssertionsMixin)
  • model instances (InstanceAssertionsMixin)

Dlaczego używać Djet?

  • Zwięzły kod testujący widoki
  • Szybsze wykonanie testów
  • Naprawiony domyślny
    FileStorage w testach
  • Wiele funkcji pomocniczych

Co dalej?

pip install djet

Django >= 1.3

Python >= 2.6

Fork & pull request

Zadowoleni użytkownicy

Contributors

Inspiracje

  • http://pyvideo.org/video/699/testing-and-django
  • http://www.rkblog.rk.edu.pl/w/p/temporary-files-django-tests-and-fly-file-manipulation/
  • http://www.django-rest-framework.org/api-guide/testing
  • https://docs.djangoproject.com/en/dev/topics/testing/

Python Developer

Wanted

Dziękuję!

Pytania?

https://github.com/sunscrapers/djet

Testy prawie jednostkowe w Django

By Przemek Lewandowski

Testy prawie jednostkowe w Django

  • 2,836