这一篇说一下 django
框架的自动化测试, django
自动化测试的不同之处在于,测试工作由系统完成。
我们只需创建一组测试,然后在对应用进行更改时,就可以检查代码是否仍按原计划运行,而无需执行耗时的手动测试。
基本测试策略
为了测试我们的代码,我们先定义一个错误,然后通过我们创建测试来暴露这个错误。
打开 members/model.py
文件,在 question
模型中添加判断发布日期方法,判断我们 question
的发布日期,小于24小时,例子如下:
from django.utils import timezone from datetime import timedelta class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') def was_published_recently(self): """ Return True if the question was published recently (within the last day). """ now = timezone.now() return now - timedelta(days=1) <= self.pub_date <= now
还记得我们的 django
的 api
命令行吗:
python manage.py shell
然后编写并执行调用 was_published_recently
方法的测试脚本
>>> import datetime >>> from django.utils import timezone >>> from polls.models import Question >>> # create a Question instance with pub_date 30 days in the future >>> future_question = Question(pub_date=timezone.now() + datetime.timedelta(days=30)) >>> # was it published recently? >>> future_question.was_published_recently()
可以看到返回的是
这是我数据库保存的记录,最新一条距离当前时间不超过24小时,根据自身的环境做测试数据:
根据代码很明显,应用程序中有一个小bug,如果查询数据是在最近一天内发布的,该 question.was_published_recently()
方法将返回 true
;
但如查询数据是在在未来发布的(这种情况当然不可能当然不是),该方法也将返回 fasle
。
我们刚刚写的脚本测试其实就是自动化测试的一种,现在我们就将脚本测试完全转化为django自动化测试。
进入 members
目录,添加 test.py
文件,写入下面代码:
import datetime from django.test import TestCase from django.utils import timezone from .models import Question class QuestionModelTests(TestCase): def test_was_published_recently_with_future_question(self): """ was_published_recently() returns 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(), True)
然后进入项目根目录,进入 django
的 api
命令行:
python manage.py test members
通过编写自动测试方法,我们能很明确的看到是哪个测试失败了,失败发生在哪条线路上,
- •
manage.py test members
会在应用程序中寻找测试 - • 第二步
django.test.TestCase
先找到了该类的一个子类 - • 第三步创建了一个特殊的数据库用于测试
- • 第四步它寻找测试方法名称以
xxx
开头方法的test
,其中test_was_published_recently_with_future_question
创建了一个question
实例,其pub_date
字段为未来 30 天,并使用该assertIs()
方法, - • 第五步发现它
was_published_recently()
返回了False
,而我们希望它返回True
。
我们来修复错误:打开 members/test.py
,将我们期望的 True
改成 False
:
class QuestionModelTests(TestCase): def test_was_published_recently_with_future_question(self): """ was_published_recently() returns 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 members
得到下面返回结果:
测试通过。
如果想更全面的测试,我们向同一个类中添加两个测试方法,以更全面地测试该方法的行为
打开 members/test.py
,添加两个测试方法:
def test_was_published_recently_with_old_question(self): """ was_published_recently() returns False for questions whose pub_date is older than 1 day. """ time = timezone.now() - datetime.timedelta(days=1, seconds=1) 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() returns True for questions whose pub_date is within the last day. """ time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59) recent_question = Question(pub_date=time) self.assertIs(recent_question.was_published_recently(), True)
执行测试命令:
python manage.py test members
得到下面返回结果:
可以看得出来,无我们的方法变得多么复杂,或者与什么其他代码交互,我们现在都可以保证我们编写测试的方法将按照预期的方式运行。
四、总结
这篇做完基础测试,印象中对 django
测试会有个基本概念。
基础测试只是基于方法的测试,适用于我们服务层的部分公共方法,逻辑方法和工具类。
下一篇我们会接着说一下 django
自动化测试的视图测试。