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应用第五步的更多相关文章

  1. 五步教你实现使用Nginx+uWSGI+Django方法部署Django程序

    Django的部署可以有很多方式,采用nginx+uwsgi的方式是其中比较常见的一种方式. 在这种方式中,我们的通常做法是,将nginx作为服务器最前端,它将接收WEB的所有请求,统一管理请求.ng ...

  2. Django 08 Django模型基础3(关系表的数据操作、表关联对象的访问、多表查询、聚合、分组、F、Q查询)

    Django 08 Django模型基础3(关系表的数据操作.表关联对象的访问.多表查询.聚合.分组.F.Q查询) 一.关系表的数据操作 #为了能方便学习,我们进入项目的idle中去执行我们的操作,通 ...

  3. ASP.NET五步打包下载Zip文件

    本文版权归博客园和作者吴双共同所有,转载和爬虫请注明原文地址:www.cnblogs.com/tdws 首先分享几个振奋人心的新闻: 1.谷歌已经宣布加入.NET基金会 2.微软加入Linux基金会, ...

  4. 软件工程 Coding.net代码托管平台 Git初学者的使用总结 五步完成 程序,文件,文件夹的Git

    一.前言 第一次用git相关的命令行,我使用的是Coding.net代码托管平台.Coding.net 自主打造的基于 Git 的代码托管平台,提供高性能的远端仓库,还有保护分支,历史版本分屏对比. ...

  5. HTML5离线Web应用实战:五步创建成功

    [IT168 技术]HTML5近十年来发展得如火如荼,在HTML 5平台上,视频,音频,图象,动画,以及同电脑的交互都被标准化.HTML功能越来越丰富,支持图片上传拖拽.支持localstorage. ...

  6. C语言程序设计入门学习五步曲(转发)

    笔者在从事教学的过程中,听到同学抱怨最多的一句话是:老师,上课我也能听懂,书上的例题也能看明白,可是到自己动手做编程时,却不知道如何下手.发生这种现象的原因有三个: 一.所谓的看懂听明白,只是很肤浅的 ...

  7. 五步搞定Android开发环境部署

    引言   在windows安装Android的开发环境不简单也说不上算复杂,本文写给第一次想在自己Windows上建立Android开发环境投入 Android浪潮的朋友们,为了确保大家能顺利完成开发 ...

  8. 五步搞定Android开发环境部署——非常详细的Android开发环境搭建教程

      在windows安装Android的开发环境不简单也说不上算复杂,本文写给第一次想在自己Windows上建立Android开发环境投入Android浪潮的朋友们,为了确保大家能顺利完成开发环境的搭 ...

  9. java入门第五步之数据库项目实战【转】

    在真正进入代码编写前些进行一些工具的准备: 1.保证有一个可用的数据库,这里我用sql server 2000为例,2.拥有一个ide,如ecelise或myeclipse等,这里我使用的是myecl ...

随机推荐

  1. Android Studio报Error:Execution failed for task &#39;:Companion:preDexDebug&#39;.

    错误例如以下: Error:Execution failed for task ':Companion:preDexDebug'. > com.android.ide.common.proces ...

  2. Labview新建项目步骤

    打开Labview软件,点击工具栏中文件选项卡,如图所示. 2 点击新建一个空白项目. 3 此时为未命名项目,按下Ctrl+S保存项目到自己指定的目录并完成命名. 4 如图示在我的电脑上点击右键,新建 ...

  3. 体验DNN演示平台《A Neural Network Playground》(一)

    0 本次博客内容简介 本次博客标(一),是因为我自知有些地方还是不理解.本篇博客仅暂时记录第一次玩 A Neural Network Playground的体验,如果后面有了进一步体会,会更新新的内容 ...

  4. node.js实现国标GB28181设备接入的sip服务器解决方案

    方案背景 在介绍GB28181接入服务器的方案前,咱们先大概给大家介绍一下为什么我们选择了用nodejs开发国标GB28181的服务,我大概给很多人介绍过这个方案,大部分都为之虎躯一震,nodejs在 ...

  5. 小米4s经常断网

    https://zhidao.baidu.com/question/1387985910554061020.html

  6. POJ 1518 A Round Peg in a Ground Hole【计算几何=_=你值得一虐】

    链接: http://poj.org/problem?id=1584 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22013#probl ...

  7. css3 transition效果

    <meta charset="UTF-8"> <style> .btn { display: inline-block; font-size: 12px; ...

  8. Python中为什么要使用线程池?如何使用线程池?

    系统处理任务时,需要为每个请求创建和销毁对象.当有大量并发任务需要处理时,再使用传统的多线程就会造成大量的资源创建销毁导致服务器效率的下降.这时候,线程池就派上用场了.线程池技术为线程创建.销毁的开销 ...

  9. 代替print输出的PY调试库:PySnooper

      PySnooper¶ Github:https://github.com/lotapp/PySnooper pip install pysnooper 使用:分析整个代码 @pysnooper.s ...

  10. overflow-y:auto 回到顶部

    overflow-y     内容溢出元素框时发生的事情. overflow-y:auto        内容溢出元素框时自动出现滚动条,滑动滚动条显示溢出的内容. 滚动条回到顶部 var conta ...