Alan Hou的个人博客

Django 3网页开发指南第4版 第11章 测试

完整目录请见:Django 3网页开发指南 – 第4版

本章中包含如下小节:

引言

要保证代码的质量及准确性,可以使用自动化软件测试。Django提供了编写网站测试套装的工具。测试套装自动检测网站及其组件来保障所有部分正常运行。在修改代码时,可以运行测试来检测所做修改是否对应用产生了负面影响。

自动化软件测试有很多分支和词汇。本书中我们将测试划分为如下分类:

技术要求

运行本章的代码要求安装最新稳定版的Python 3、MySQL或PostgreSQL数据库以及通过虚拟环境创建的Django项目。

可在GitHub仓库的Chapter11目录中查看本章的代码。

使用mock库测试视图

本节中我们学习如何编写单元测试。单元测试是一种检测单个函数或方法是否返回正确结果 的测试。我们会使用likes应用并编写测试来测试使用非登录用户向json_set_like()视图信息提交信息是否返回失败响应,而登录用户是否返回成功的结果。我们会使用Mock对象来模拟HttpRequest和AnonymousUser对象。

准备工作

我们使用第4章 模板和JavaScript实现Like微件一节中的locations和likes应用。

我使用的是mock库,自Python 3.3开始它内置于unittest.mock之中。

如何实现…

通过如下步骤来使用mock测试点赞的动作:

  1. 在likes应用中创建tests模块
  2. 在该模块中使用如下内容创建文件test_views.py:
  3. 对likes应用运行测试如下:

实现原理…

在对likes应用运行测试时,首先会创建一个临时测试数据库。然后,调用 setUpClass()方法。再后,名称以test起始的方法会进行执行,最后会调用tearDownClass()方法,会通过一项测试,在命令行中都出现一个点号(.),每项失败的测试则会出现字母,,而测试中的每个错误则会打印出字母 E。最后,我们可以看到失败和报错测试的一些提示信息。因为当前我们对likes应用的测试套装中仅有两个测试,所以在结果中会出现两个点号。

在setUpClass()中,我们创建一个地点和一个超级用户。财时,查找出Location模型的ContentType对象。我们需要在为其它对象设置或删除点赞的json_set_like()视图中使用到。提醒一下,视图类似下面这样,并会返回一个JSON字符串结果:

在test_authenticated_json_set_like() 和 test_anonymous_json_set_like()方法中,我们使用了Mock对象。这些对象可拥有任意属性或方法。Mock对象的每个未定义属性或方法是另一个Mock对象。因此,在shell中,可以试着链式访问属性,如下:

在测试中,我们合适Mock对象模拟HttpRequest对象。对于匿名用户,MockUser通过@mock.patch()装饰器生成为一个标准Django User对象的补丁。对于已登录用户,我们仍需要真实的User对象,因为视图对Like对象使用用户ID。

因此,我们调用了json_set_like()函数,并检测所返回的JSON响应是否正确:

最后会调用tearDownClass()类方法、从测试数据库中删除地点和超级用户。

扩展知识…

要测试使用了HttpRequest对象的代码,还可以使用Django请求工厂。详情请参阅https://docs.djangoproject.com/en/3.0/topics/testing/advanced/#the-request-factory。

相关内容

使用Selenium测试用户界面

实用验收测试检测业务逻辑来了解项目有没有按假定那样运作。本节中,我们将学习如何使用Selenium编写验收测试,它让我们可以在前台模拟活动,如填写表单或在浏览器中点击具体的DOM元素。

准备工作

我们使用第4章 模板和JavaScript实现Like微件一节中的locations和likes应用进行下面的学习。

本节我们使用Selenium库和Chrome浏览器以及ChromeDriver来对其进行控制。进行如下准备:

  1. 从https://www.google.com/chrome/下载 Chrome 浏览器。
  2. 在Django项目中创建drivers目录。从https://sites.google.com/a/chromium.org/chromedriver/下载稳定版ChromeDriver,解压缩并将其放入刚刚创建的drivers目录中。
  3. 在虚拟环境中安装Selenium如下:

如何实现…

执行如下步骤来通过Selenium测试基于Ajax的点赞功能:

  1. 在项目配置文件中,添加TESTS_SHOW_BROWSER的配置:
  2. 在locations应用中创建tests模型并使用如下内容添加一个test_frontend.py文件:
  3. 对locations应用运行测试如下:

实现原理…

在运行这些测试时,在URL下看到打开的一个后台登录页面Chrome窗口,例如http://localhost:63807/en/admin/login/?next=/en/locations/176255a9-9c07-4542-8324-83ac0d21b7c3/。

用户名和密码字段将会填入admin,我们会被重定向到地点Park Güell的详情页,链接类似于http://localhost:63807/en/locations/176255a9-9c07-4542-8324-83ac0d21b7c3/。在该页面会看到两次点击Like按钮,进行点赞和取消点赞的操作。

如果将TESTS_SHOW_BROWSER的配置修改为False(或删除),再次运行测试,测试会在后台以最小等待时间运行,不会打开浏览器窗口。

我们来看下测试套装是如何运作的。定义了一个继承LiveServerTestCase的类。这会创建一个测试套装,随机使用一个未占用的端口运行本地服务,如63807。默认LiveServerTestCase以非调试模式运行服务。但使用override_settings()装饰器将其切换到DEBUG模式会在无需转存的情况下即可访问静态文件,并在任何页面中发生错误时显示错误回溯信息。setUpClass()类方法会在所有测试的一开始执行,tearDownClass() 类方法会在运行了测试之后执行。在这中间,会执行测试套件中所有以test开头的方法的测试。

在开始测试时,新建测试数据库。在setUpClass()中,创建一个浏览器对象、一个地点及一个超级用户。然后执行test_login_and_like()方法,打开后台登录页面,查找用户名字段,输入管理员用户名,查找密码字段,输入管理员密码,查找提交按钮进行点击。然后查找页面中具有.like-button CSS类的DOM元素,等待最长10秒。

你可能记得在第4章 模板和JavaScript实现Like微件一节中,我们的微件由两个元素组成:

如果进行按钮的点击,会通过Ajax调用添加或删除Like实例。此外,数标上的记数会根据数据库中的点赞数进行更新。

在进一步的测试中,我们查看按钮的初始状态(是否有.active CSS 类),查看点赞的初始数并模拟按钮的点击。等待最多10秒直至数标发生更改。然后检查数标上的计数与数据库中的地点的总点赞数是否一致。我们还会对数据中数字发生的变化(增加)进行检测。并会再次模拟按钮的点击来将其切换到之前的状态。

最后调用tearDownClass() 方法,它关闭浏览器并从测试数据库中删除地点和超级用户。

相关内容

测试Django REST framework所创建的API

读者应当已经理解了如何编写单元测试和实用验收测试。本节中我们将对本书此前创建的RESTful API进行组件接口测试。

如果尚不熟悉RESTful API是什么以及如何使用API,请访问https://www.restapitutorial.com做进一步的学习。

准备工作

我们使用第9章 导入、导出数据使用Django REST framework创建API一节中的music进行下面的学习。

如何实现…

执行如下步骤来测试RESTful API:

  1. 在music应用中创建tests模块。在tests模块中,创建一个带有SongTests类的test_api.py文件。该类中有setUpClass() 和 tearDownClass()方法,如下:
  2. 添加API测试检测歌曲列表:
  3. 添加API测试检测单曲详情:
  4. 添加API测试检测新歌的成功创建:
  5. 添加测试尝试在不登录或失败的情况下创建歌曲,如:
  6. 添加测试检测歌曲的成功修改:
  7. 添加测试检测因未登录导致的无法修改:
  8. 添加测试检测歌曲删除的失败情况:
  9. 添加测试检测歌曲的成功删除:
  10. 对music应用运行测试,如下所示:

实现原理…

RESTful API测试套装继承APITestCase类。同样,在各测试之前及之后会执行类方法setUpClass() 和 tearDownClass()。测试套件还有一个APIClient类型客户端属性,可用于模拟API调用。客户端为所有标准HTTP请求提供方法:有get()、post()、put()、patch()、delete()、head()和 options()。

在我们测试中,使用了GET、POST和DELETE请求。同时客户端有基于登录认证信息、token或User对象强制用户登录的方法。在我们测试中,我们以第三种方式进行登录:直接将用户传递给force_authenticate()方法。

其它部分的代码根据字面即可理解。

相关内容

保障测试覆盖范围

Django让我们可以进行快速原型开发,并且快速地将项目由创意阶段并为实现阶段。但要让项目稳定并可用于生产环境,应当对尽可能多的功能进行测试。借助于测试范围,可以检测项目代码的测试量。我们来一起学习如何实现。

准备工作

在项目中准备一些测试。

在虚拟环境中安装coverage工具:

如何实现…

以下是如何在项目中进行测试覆盖量的检测:

  1. 使用如下代码为coverage工具创建setup.cfg配置文件:
  2. 如果使用了Git版本控制确保在 .gitignore文件中添加如下代码:
  3. 创建一个shell脚本run_tests_with_coverage.sh,包含通过coverage运行测试及报告结果的命令:
  4. 为该脚本添加执行权限:
  5. 运行该脚本:

实现原理…

coverage工具运行测试并检测测试覆盖了多少行代码。在本例中,我们所编写的测试覆盖了48%的代码。如果代码稳定性对你很重要,在有时间时尽量让其接近100%。

在覆盖量配置中,我们跳过了静态资源、模板以及其它非Python文件。

相关内容

退出移动版