跟着Django手册建立Blog(三)--引入自动测试

来源:互联网 发布:系统动力学仿真软件 编辑:程序博客网 时间:2024/05/22 11:45

1. 引入自动测试.

a. 识别一个bug

在Python shell中写以下代码测试是否有bug

>>> import datetime>>> from django.utils import timezone>>> from polls.models import Question>>> future_question = Question(pub_date=timezone.now() + datetime.timedelta(days=30))>>> future_question.was_published_recently()True

b. 在polls/tests.py中写入代码

一个app的tests.py就是用来写测试代码的.

import datetimefrom django.test import TestCasefrom django.utils import timezonefrom .models import Questionclass QuestionMethodTests(TestCase):    def test_was_published_recently_with_future_question(self):        time = timezone.now() + datetime.timedelta(day=30)        future_question = Question(pub_date=time)        # 下面一句断言如果判断的对象是未来的日期,was_published_recently()应该返回False.        self.assertIs(future_question.was_published_recently(), False)

c. 运行Tests

在cmd环境下运行test, 

cd到当前project目录下输入python manage.py test polls



2. 修复bug

a. 在polls/models.py中修改bug.

修改前:

    def was_published_recently(self):        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
修改后:

    def was_published_recently(self):        return timezone.now() >= self.pub_date >= timezone.now() - datetime.timedelta(days=1)

b. 再run一次test, 通过.


3. 更全面的测试

a. 为了更全面的测试出bug, 再写两个test方法.

polls/tests.py下增加代码

    def test_was_published_recently_with_old_question(self):        # was_published_recently()对于一天以前的问题应该返回false        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()对于一天之内的问题应该返回true        time = timezone.now() - datetime.timedelta(hours=1)        recent_question = Question(pub_date=time)        self.assertIs(recent_question.was_published_recently(), True)
b. run test, 通过.



4. 测试view

这个polls app没有对pub_date作区分, 发布时间在未来的问题也会显示出来. 改善方向是, 如果发布时间是在未来的问题, 则需等到那一天那一刻才显示出来.

a. 测试IndexView

假装是用户通过浏览器访问页面, django提供了一个test client, 即假用户.

如果时区没有设置对, 测试结果可能出错, 在myblog/settings.py下修改 TIME_ZONE = 'Asia/Shanghai'

打开shell输入以下代码:

>>> from django.test.utils import setup_test_environment>>> setup_test_environment()>>> from django.test import Client>>> client = Client()>>> response = client.get('/')Not Found: />>> response.status_code404>>> from django.urls import reverse>>> response = client.get(reverse('polls:index'))>>> response.status_code200>>> response.contentb'\n    <ul>\n        \n            <li><a href="/polls/1/">What&#39;s up?</a></li>\n        \n    </ul>\n    '>>> response.context['latest_question_list']<QuerySet [<Question: What's up?>]>
b. 改善我们的index view

polls/views.py下修改:

修改前:

class IndexView(generic.ListView):    template_name = 'polls/index.html'    context_object_name = 'latest_question_list'    def get_queryset(self):        # Return the last five published questions.        return Question.objects.order_by('-pub_date')[:5]
修改后:

class IndexView(generic.ListView):    template_name = 'polls/index.html'    context_object_name = 'latest_question_list'    def get_queryset(self):        # Return the last five published questions.        return Question.objects.filter(            pub_date__lte=timezone.now()  # __lte意思是less than or equal to        ).order_by('-pub_date')[:5]

c. 测试我们的新view

在polls/tests.py下加入代码

from django.urls import reverse
def create_question(question_text, days):    # 创建的问题的发布时间可能在未来或者过去, 当days设定为负值时, 是过去时间, 当days设定为正值时,是未来时间.    time = timezone.now() + datetime.timedelta(days = days)    return Question.objects.create(question_text=question_text, pub_date=time)class QuestionViewTests(TestCase):    def test_index_view_with_no_questions(self):        # 如果没有问题存在时, 需显示合适的信息        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):        # 若问题的发布时间在过去, 应该显示出来        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):        # 若问题的发布时间在未来, 不应该显示出来        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):        # 若同时存在过去的问题和未来的问题, 则只显示过去的问题        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_question(self):        # 若有多个过去的问题, question首页应该显示多个问题        create_question(question_text="Past question.", days=-30)        create_question(question_text="Past question.", days=-5)        response = self.client.get(reverse('polls:index'))        self.assertQuerysetEqual(            response.context['latest_question_list'],            ['<Question: Past question.>', '<Question: Past question.>']        )


d.测试DetailView

用户可以通过猜测正确的URL来访问未来问题的detail页面, 因此, 需要为DetailView添加类似的约束.

修改polls/views.py的代码:

class DetailView(generic.DetailView):    model = Question    template_name = 'polls/detail.html'        def get_queryset(self):        # 排除那些尚未发布的问题.        return Question.objects.filter(pub_date__lte=timezone.now())
写测试代码测试DetailView

在polls/tests.py写以下代码:

class QuestionIndexDetailTests(TestCase):    def test_detail_view_with_a_future_question(self):        # 访问尚未发布的问题时, 应该得到一个404        future_question = create_question(question_text='Future question.', days=5)        url = reverse('polls:detail', args=(future_question.id,))        response = self.client.get(url)        self.assertEqual(response.status_code, 404)    def test_detail_view_with_a_past_question(self):        # 访问已发布的问题, 应该显示问题的内容        past_question = create_question(question_text='Future question.', days=-5)        url = reverse('polls:detail', args=(past_question.id,))        response = self.client.get(url)        self.assertContains(response, past_question.question_text)
再运行一次测试, 通过.



原创粉丝点击