在django项目app目录下,有个tests.py,我们通常可以直接在这文件中写我们的单元测试代码。
test for a model
根据前面章节的操作步骤下来,在Question Model中有一个函数 was_published_recently(),判断文章发表时间在当前一天之内。代码如
1
2
|
def
was_published_recently(
self
):
return
self
.pub_date >
=
timezone.now()
-
datetime.timedelta(days
=
1
)
|
仔细检查,可发现上述函数有个bug。如果发表时间在未来呢,按照上面的代码是会返回true的,显然不对。
编写测试用例 polls/tests.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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 polls
looked for tests in thepolls
application- it found a subclass of the
django.test.TestCase
class - 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_question
it created aQuestion
instance whosepub_date
field 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,代码如
1
2
3
|
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'...
添加更多的测试用例,如
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
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.>'
]
)
|