Подтвердить что ты не робот

Написание хороших тестов для приложений Django

Я никогда не писал никаких тестов в своей жизни, но я бы хотел начать писать тесты для своих проектов Django. Я прочитал несколько статей об испытаниях и решил попробовать некоторые тесты для чрезвычайно простого приложения Django или запуска.

Приложение имеет два вида (представление списка и подробное представление) и модель с четырьмя полями:

class News(models.Model):
    title = models.CharField(max_length=250)
    content = models.TextField()
    pub_date = models.DateTimeField(default=datetime.datetime.now)
    slug = models.SlugField(unique=True)

Я хочу показать вам файл tests.py и спросить:

Имеет ли смысл?

Я даже тестирую правильные вещи?

Есть ли лучшие практики, которых я не соблюдаю, и вы могли бы указать мне?

my tests.py(он содержит 11 тестов):

# -*- coding: utf-8 -*-
from django.test import TestCase
from django.test.client import Client
from django.core.urlresolvers import reverse
import datetime
from someproject.myapp.models import News

class viewTest(TestCase):
    def setUp(self):
        self.test_title = u'Test title: bąrekść'
        self.test_content = u'This is a content 156'
        self.test_slug = u'test-title-bareksc'
        self.test_pub_date = datetime.datetime.today()

        self.test_item = News.objects.create(
            title=self.test_title,
            content=self.test_content,
            slug=self.test_slug,
            pub_date=self.test_pub_date,
        )

        client = Client()
        self.response_detail = client.get(self.test_item.get_absolute_url())
        self.response_index = client.get(reverse('the-list-view'))

    def test_detail_status_code(self):
        """
        HTTP status code for the detail view
        """
        self.failUnlessEqual(self.response_detail.status_code, 200)

    def test_list_status_code(self):
        """
        HTTP status code for the list view 
        """
        self.failUnlessEqual(self.response_index.status_code, 200)

    def test_list_numer_of_items(self):
        self.failUnlessEqual(len(self.response_index.context['object_list']), 1)      

    def test_detail_title(self):
        self.failUnlessEqual(self.response_detail.context['object'].title, self.test_title)    

    def test_list_title(self):
        self.failUnlessEqual(self.response_index.context['object_list'][0].title, self.test_title)

    def test_detail_content(self):
        self.failUnlessEqual(self.response_detail.context['object'].content, self.test_content)    

    def test_list_content(self):
        self.failUnlessEqual(self.response_index.context['object_list'][0].content, self.test_content) 

    def test_detail_slug(self):
        self.failUnlessEqual(self.response_detail.context['object'].slug, self.test_slug)    

    def test_list_slug(self):
        self.failUnlessEqual(self.response_index.context['object_list'][0].slug, self.test_slug)

    def test_detail_template(self):
        self.assertContains(self.response_detail, self.test_title)
        self.assertContains(self.response_detail, self.test_content)

    def test_list_template(self):       
        self.assertContains(self.response_index, self.test_title) 
4b9b3361

Ответ 1

Я не совершенен в тестировании, но несколько соображений:

В основном вы должны проверять каждую функцию, метод, класс, независимо от того, что вы написали сами.

Это означает, что вам не нужно проверять функции, классы и т.д., которые предоставляет инфраструктура.

Это говорит о быстрой проверке ваших тестовых функций:

  • test_detail_status_code и test_list_status_code:
    Хорошо проверить, правильно ли вы настроили маршрутизацию. Еще более важно, когда вы предоставляете свою собственную реализацию get_absolute_url().

  • test_list_numer_of_items:
    Хорошо, если определенное количество элементов должно быть возвращено представлением. Не обязательно, если число не важно (т.е. Произвольно).

  • test_detail_template и test_list_template:
    Хорошо проверить, правильно ли установлены шаблонные переменные.

  • Все остальные функции: не нужно.
    В основном вы тестируете, правильно ли работает ORM, работают ли списки в ожидании и доступны ли свойства объекта (или нет). Пока вы не меняете, например. метод save() модели и/или предоставляет вашу пользовательскую логику, я бы не тестировал это. Вы должны доверять разработчикам фреймворка, что это работает правильно.

Вам нужно только проверить, что у вас написано.

Классы моделей могут быть особым случаем. В основном вы должны протестировать их, как я сказал, если вы предоставите пользовательскую логику. Но вы также должны проверить их на свои требования. Например. это может быть то, что поле не может быть null (или что он должен быть определенным типом данных, например целым числом). Поэтому вы должны проверить, что хранение объекта не выполняется, если оно имеет значение null в этом поле.
Это означает, что не проверяет ORM на правильное соответствие вашим спецификациям, но проверяет, соответствует ли спецификация вашим требованиям. Возможно, вы изменили модель и изменили некоторые настройки (случайно или потому, что вы забыли о требованиях).
Но вам не нужно тестировать, например. методы, подобные save(), или вы можете получить доступ к свойству.

Конечно, когда вы используете неверный код третьей стороны... все может быть по-другому. Но поскольку Django использует саму тестовую среду, чтобы убедиться, что все работает, я бы предположил, что она работает.

Подводя итог:
Протестируйте свои требования, проверьте свой собственный код.

Это только моя точка зрения. Возможно, у других есть лучшие предложения.

Ответ 2

Разделите свои тесты на два совершенно разных типа.

  • Модельные тесты. Поместите их в свой models.py файл с вашей моделью. Эти тесты будут использовать методы в ваших классах моделей. Вы можете сделать простой CRUD (Create, Retrieve, Update, Delete), чтобы просто доказать, что ваша модель работает. Не проверяйте каждый атрибут. Если вы заинтересованы, задайте значения полей по умолчанию и правила save().

    В качестве примера создайте класс TestNews, который создает, получает, обновляет и удаляет элемент News. Обязательно проверьте результаты по умолчанию. Этот класс должен быть коротким и точным. Вы можете, если ваше приложение требует этого, протестировать различные виды обработки фильтров. Ваш unit test код может (и должен) предоставить примеры "правильного" способа фильтрации News.

  • Тесты пользовательского интерфейса. Поместите их в отдельный файл tests.py. Эти тесты будут проверять функции просмотра и шаблоны.

    • Назовите TestCase "созданным" условием. "TestNotLoggedIn". "TestLoggedIn". "TestNoValidThis". "TestNotAllowedToDoThat". Ваш setUp выполнит логин и любые другие действия, необходимые для установления требуемого условия.

    • Назовите каждый тестовый метод действием и результатом. "test_get_noquery_should_list", "test_post_should_validate_with_errors", "test_get_query_should_detail".