Django基础,Day6 - 单元测试tests
在django项目app目录下,有个tests.py,我们通常可以直接在这文件中写我们的单元测试代码。
test for a model
根据前面章节的操作步骤下来,在Question Model中有一个函数 was_published_recently(),判断文章发表时间在当前一天之内。代码如
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
仔细检查,可发现上述函数有个bug。如果发表时间在未来呢,按照上面的代码是会返回true的,显然不对。
编写测试用例 polls/tests.py:
from django.test import TestCase
import datetime
from django.utils import timezone
from .models import Question
class QuestionMethodTests(TestCase):
def test_was_published_recently_with_future_question(self):
"""
was_published_recently() should return False for questions whose
pub_date is in the future.
"""
time = timezone.now() + datetime.timedelta(days=30)
future_question = Question(pub_date=time)
self.assertIs(future_question.was_published_recently(), False)
运行测试用例
$ python manage.py test polls
运行结果如:
Creating test database for alias 'default'... F ====================================================================== FAIL: test_was_published_recently_with_future_question (polls.tests.QuestionMethodTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "E:\workspace_python\mysite\polls\tests.py", line 16, in test_was_published_recently_with_future_question self.assertIs(future_question.was_published_recently(), False) AssertionError: True is not False ---------------------------------------------------------------------- Ran 1 test in 0.002s FAILED (failures=1) Destroying test database for alias 'default'...
What happened is this:
python manage.py test pollslooked for tests in thepollsapplication- it found a subclass of the
django.test.TestCaseclass - it created a special database for the purpose of testing
- it looked for test methods - ones whose names begin with
test - in
test_was_published_recently_with_future_questionit created aQuestioninstance whosepub_datefield is 30 days in the future - ... and using the
assertIs()method, it discovered that itswas_published_recently()returnsTrue, though we wanted it to returnFalse
修复该bug,代码如
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
重新运行测试代码,则用例通过。
$ python manage.py test polls Creating test database for alias 'default'... . ---------------------------------------------------------------------- Ran 1 test in 0.001s OK Destroying test database for alias 'default'...
添加更多的测试用例,如
from django.test import TestCase
import datetime
from django.utils import timezone
from .models import Question
class QuestionMethodTests(TestCase):
def test_was_published_recently_with_future_question(self):
"""
was_published_recently() should return False for questions whose
pub_date is in the future.
"""
time = timezone.now() + datetime.timedelta(days=30)
future_question = Question(pub_date=time)
self.assertIs(future_question.was_published_recently(), False)
def test_was_published_recently_with_old_question(self):
"""
was_published_recently() should return False for questions whose
pub_date is older than 1 day.
"""
time = timezone.now() - datetime.timedelta(days=30)
old_question = Question(pub_date=time)
self.assertIs(old_question.was_published_recently(), False)
def test_was_published_recently_with_recent_question(self):
"""
was_published_recently() should return True for questions whose
pub_date is within the last day.
"""
time = timezone.now() - datetime.timedelta(hours=1)
recent_question = Question(pub_date=time)
self.assertIs(recent_question.was_published_recently(), True)
test for a view
以view.index 为例,显然现在的代码也有bug,显示了发布时间属于将来的文章,代码如

测试之前,先修复view.index 中应该不显示发布时间在将来的文章。测试代码代码如
polls/views.py:

polls/index.html:

测试用例代码
Django provides a test Client to simulate a user interacting with the code at the view level
from django.test import TestCase
import datetime
from django.urls import reverse
from django.utils import timezone
from .models import Question
class QuestionViewTests(TestCase):
def test_index_view_with_no_questions(self):
"""
If no questions exist, an appropriate message should be displayed.
"""
response = self.client.get(reverse('polls:index'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "No polls are available.")
self.assertQuerysetEqual(response.context['latest_question_list'], [])
def test_index_view_with_a_past_question(self):
"""
Questions with a pub_date in the past should be displayed on the
index page.
"""
create_question(question_text="Past question.", days=-30)
response = self.client.get(reverse('polls:index'))
self.assertQuerysetEqual(
response.context['latest_question_list'],
['<Question: Past question.>']
)
def test_index_view_with_a_future_question(self):
"""
Questions with a pub_date in the future should not be displayed on
the index page.
"""
create_question(question_text="Future question.", days=30)
response = self.client.get(reverse('polls:index'))
self.assertContains(response, "No polls are available.")
self.assertQuerysetEqual(response.context['latest_question_list'], [])
def test_index_view_with_future_question_and_past_question(self):
"""
Even if both past and future questions exist, only past questions
should be displayed.
"""
create_question(question_text="Past question.", days=-30)
create_question(question_text="Future question.", days=30)
response = self.client.get(reverse('polls:index'))
self.assertQuerysetEqual(
response.context['latest_question_list'],
['<Question: Past question.>']
)
def test_index_view_with_two_past_questions(self):
"""
The questions index page may display multiple questions.
"""
create_question(question_text="Past question 1.", days=-30)
create_question(question_text="Past question 2.", days=-5)
response = self.client.get(reverse('polls:index'))
self.assertQuerysetEqual(
response.context['latest_question_list'],
['<Question: Past question 2.>', '<Question: Past question 1.>']
)

浙公网安备 33010602011771号