2010-02-02 1 views
27

Я никогда не писал никаких тестов в своей жизни, но я бы хотел начать писать тесты для своих проектов 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 и спросить:

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

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

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

мой 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) 

ответ

18

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

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

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

Тем не менее, быстрая проверка тестовых функций:

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

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

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

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

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

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

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

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

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

5

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

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

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

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

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

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