08 - Django应用第五步

Posted weihuchao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了08 - Django应用第五步相关的知识,希望对你有一定的参考价值。

1 自动测试

  自动测试与测试的不同在于, 自动测试的测试工作是交给系统完成的

  测试也有分类和级别, 有的用于一些细微的细节, 有的是针对整个软件整体

  测试会保证一些看起来正常运行的功能在实际的多种情况下验证, 这样可以保证很好的准确性

  测试的目的在于防止错误的产生

  测试可以帮助形成良好的团队合作

2 基本测试策略

  事实上有不少测试驱动开发(test-driven development)的情况

3 第一个测试

3.1 判断是最近发布的函数bug

  在polls中就存在一个bug

  在Question.was_published_recently() 函数中, 如果传入的参数是未来的一天内, 返回值也回事True 

  该情况测试如下

>>> 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

  常规情况下, 应用的测试应该将测试代码写入到test.py文件中

  polls/tests.py

import datetime
from django.utils import timezone
from django.test import TestCase
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(), False)

  基本写法就是写一个类继承自TestCase

  用assertIs()编写运行的实例和期望得到的结果

  然后编写一个方法用于验证

3.2 运行测试

  执行命令

python manage.py test polls

  运行结果为

  

  整个运行过程为:

    1) 现在polls应用下查找测试文件test.py

    2) 在文件中查找继承django.test.TestCase类的子类

    3) 创建一个特殊的数据库

    4) 在类中查找以test开头的方法

    5) 执行代码, 检查assertIs()的结果, 检查运行结果是否符合预期

3.3 修正bug

  修改为

  polls/models.py

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

3.4 更加全面的测试

  polls/tests.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)
    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)

4 关于视图的测试

4.1 测试环境

  Django提供了一个测试客户端, 用于模拟用户在视图级别与代码进行交互    

  启动测试环境

>>> from django.test.utils import setup_test_environment
>>> setup_test_environment()

  注意次测试不会创建专门的测试数据库, 测试结果都是源自于现有的数据库

  创建客户端

>>> client = Client()

  开始测试

>>> # get a response from \'/\'
>>> response = client.get(\'/\')
Not Found: /
>>> # we should expect a 404 from that address; if you instead see an
>>> # "Invalid HTTP_HOST header" error and a 400 response, you probably
>>> # omitted the setup_test_environment() call described earlier.
>>> response.status_code
404
>>> # on the other hand we should expect to find something at \'/polls/\'
>>> # we\'ll use \'reverse()\' rather than a hardcoded URL
>>> from django.urls import reverse
>>> response = client.get(reverse(\'polls:index\'))
>>> response.status_code
200
>>> response.content
b\'\\n    <ul>\\n    \\n        <li><a href="/polls/1/">What\'s up?</a></li>\\n    \\n    </ul>\\n\\n\'
>>> response.context[\'latest_question_list\']
<QuerySet [<Question: What\'s up?>]>

4.2 改进视图函数

  原有的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]

  修改get_query()将其数据限定到最近

def get_queryset(self):
    """
    Return the last five published questions (not including those set to be
    published in the future).
    """
    from django.utils import timezone
    return Question.objects.filter(
        pub_date__lte=timezone.now()
    ).order_by(\'-pub_date\')[:5]

4.3 测试

  polls/tests.py

from django.urls import reverse

def create_question(question_text, days):
    """
    Create a question with the given `question_text` and published the
    given number of `days` offset to now (negative for questions published
    in the past, positive for questions that have yet to be published).
    """
    time = timezone.now() + datetime.timedelta(days=days)
    return Question.objects.create(question_text=question_text, pub_date=time)


class QuestionIndexViewTests(TestCase):
    def test_no_questions(self):
        """
        If no questions exist, an appropriate message is 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_past_question(self):
        """
        Questions with a pub_date in the past are 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_future_question(self):
        """
        Questions with a pub_date in the future aren\'t 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_future_question_and_past_question(self):
        """
        Even if both past and future questions exist, only past questions
        are 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_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.>\']
        )

  

 

以上是关于08 - Django应用第五步的主要内容,如果未能解决你的问题,请参考以下文章

怎么把rstudio的快捷方式

如何在 Django 中显式重置模板片段缓存?

rstudio怎么终止当前操作

易于使用的 django 验证码或带有验证码的注册应用程序?

Python一键生成验证码并部署(django)

django 第五课自定义模板过滤器与标签