Django测试文件——tests.py
本文档主要分为两部分。首先,我们介绍如何利用 Django 编写测试。接着,我们介绍如何运行它们。
编写测试¶
Django 的单元测试采用 Python 的标准模块: unittest
。该模块以类的形式定义测试。
下面是一个例子,它是 django.test.TestCase
的子类,同时父类也是 unittest.TestCase
的子类,在事务内部运行每个测试以提供隔离:
from django.test import TestCase from myapp.models import Animalclass AnimalTestCase(TestCase):def setUp(self):Animal.objects.create(name="lion", sound="roar")Animal.objects.create(name="cat", sound="meow")def test_animals_can_speak(self):"""Animals that can speak are correctly identified"""lion = Animal.objects.get(name="lion")cat = Animal.objects.get(name="cat")self.assertEqual(lion.speak(), 'The lion says "roar"')self.assertEqual(cat.speak(), 'The cat says "meow"')
当你 运行你的测试 时,测试工具的默认行为是在任何名字以 test
开头的文件中找到所有的测试用例(也就是 unittest.TestCase
的子类),从这些测试用例中自动构建一个测试套件,然后运行该套件。
更多关于 unittest
的细节,参考 Python 文档。
测试代码应该放在哪?
默认的 startapp
会在新的应用程序中创建一个 tests.py
文件。如果你只有几个测试,这可能是好的,但随着你的测试套件的增长,你可能会想把它重组为一个测试包,这样你就可以把你的测试分成不同的子模块,如 test_models.py
、test_views.py
、test_forms.py
等。你可以自由选择任何你喜欢的组织方案。
另请参阅 使用 Django 测试运行器测试可重用的应用程序。
警告
如果你的测试依赖数据库连接,比如创建或查询模型,请确保继承 django.test.TestCase
实现你的测试类,而不是 unittest.TestCase
。
使用 unittest.TestCase
避免了在事务中运行每个测试并刷新数据库的成本,但如果你的测试与数据库交互,它们的行为将根据测试运行器执行它们的顺序而变化。这可能导致单元测试在单独运行时通过,但在套件中运行时失败。
运行测试¶
编写完测试后,使用项目的 manage.py
实用程序的 test
命令运行它们:
$ ./manage.py test
测试发现是基于 unittest 模块的 内建测试发现。默认情况下,这将发现当前工作目录下任何名为“test*.py”的文件中的测试。
你可以通过向 ./manage.py test
提供任意数量的“测试标签”来指定要运行的特定测试。每个测试标签可以是指向包、模块、TestCase
子类或测试方法的点分隔 Python 路径。例如:
# Run all the tests in the animals.tests module $ ./manage.py test animals.tests# Run all the tests found within the 'animals' package $ ./manage.py test animals# Run just one test case $ ./manage.py test animals.tests.AnimalTestCase# Run just one test method $ ./manage.py test animals.tests.AnimalTestCase.test_animals_can_speak
你还可以提供目录路径,以发现该目录下的测试:
$ ./manage.py test animals/
如果你的测试文件的命名与 test*.py
模式不同,你可以使用 -p``(或 ``--pattern
)选项指定一个自定义文件名模式匹配:
$ ./manage.py test --pattern="tests_*.py"
如果你在测试运行时按 Ctrl-C
,测试运行器将等待当前运行的测试完成,然后优雅地退出。在优雅退出过程中,测试运行器将输出任何测试失败的细节,报告运行了多少次测试,遇到了多少次错误和失败,并像往常一样销毁任何测试数据库。因此,如果你忘记了传入 --failfast
选项,注意到一些测试意外地失败了,并且想在不等待整个测试运行完成的情况下获得失败的细节,那么按下 Ctrl-C
就会非常有用。
如果你不想等待当前正在进行的测试结束,你可以按两次 Ctrl-C
,测试运行将立即停止,但不会优雅地停止。不会报告中断前运行的测试细节,也不会销毁运行中创建的任何测试数据库。
在启用警告的情况下进行测试
启用 Python 警告来运行测试是个好主意:python -Wa manage.py test
。-Wa
标志告诉 Python 显示弃用警告。Django 和其他 Python 库一样,使用这些警告标志着功能的消失。它也可以标记你的代码中严格来说没有错误的但可以从更好的实现中受益的地方。
测试数据库¶
需要数据库的测试(即模型测试)将不会使用“实际”(生产)数据库。 将为测试创建单独的空白数据库。
无论测试是通过还是失败,当所有测试执行完毕后,测试数据库都会被销毁。
你可以通过使用 test --keepdb
选项来防止测试数据库被破坏。 这将在两次运行之间保留测试数据库。 如果数据库不存在,将首先创建它。 任何迁移都将被应用,以使其保持最新状态。
如上一节所述,如果测试运行被强行中断,测试数据库可能不会被销毁。在下一次运行时,你会被问到是要重新使用还是销毁数据库。使用 test --noinput
选项禁止显示该提示并自动销毁数据库。 例如,在持续集成服务器上运行测试时这很有用,该测试可能会因超时而中断。
默认的测试数据库名称是通过在 DATABASES
中每个 NAME
的值前加上 test_
来创建的。当使用 SQLite时,默认情况下测试将使用内存数据库(即数据库将在内存中创建,完全绕开文件系统!)。DATABASES
中的 TEST
字典提供了许多设置来配置你的测试数据库。例如,如果你想使用不同的数据库名称,给 DATABASES
中的每个数据库在 TEST
字典中指定 NAME
。
在 PostgreSQL 上,USER
也需要对内置的 postgres
数据库进行读取访问。
除了使用单独的数据库外,测试运行器还将使用你在配置文件中的所有相同的数据库设置: ENGINE
、USER
、HOST
等。测试数据库是由 USER
指定的用户创建的,所以你需要确保给定的用户账户有足够的权限在系统上创建一个新的数据库。
为了对测试数据库的字符编码进行精细控制,请使用 CHARSET
TEST 选项。如果你使用的是 MySQL,你也可以使用 COLLATION
选项来控制测试数据库使用的特定字符序。请参阅 配置文档 了解这些和其他高级设置的细节。
如果使用 SQLite 内存数据库,启用了 共享缓存,你就可以编写线程之间共享数据库的测试。
运行测试时从生产数据库中查找数据?
如果你的代码在编译模块时试图访问数据库,这将在测试数据库建立 之前 发生,可能会产生意想不到的结果。例如,如果你在模块级代码中进行数据库查询,并且存在真实的数据库,则生产数据可能会污染你的测试。 无论如何,在代码中都包含这样的导入时数据库查询是一个坏主意——重写代码,使其不会执行此操作。
这也适用于 ready()
的自定义实现。
参见
进阶多数据库测试主题。
执行测试的顺序¶
为了保证所有的 TestCase
代码都从干净的数据库开始,Django 测试运行器以如下方式重新排序测试:
- 所有
TestCase
的子类首先运行。 - 然后,所有其他基于Django的测试(基于
SimpleTestCase
的测试用例,包括TransactionTestCase
)都会被运行,它们之间不保证也不强制执行特定的顺序。 - 然后运行任何其他的
unittest.TestCase
测试(包括 doctests),这些测试可能会改变数据库而不将其恢复到原始状态。
注解
新的测试顺序可能会意外的揭示出测试用例对顺序的依赖性。在 doctests 依赖于数据库中给定的 TransactionTestCase
测试的情况下,必须更新它们才能独立运行。
你可以使用 test --reverse
选项反转组内的执行顺序。 这可以帮助确保你的测试彼此独立。
回滚模拟¶
任何在迁移中加载的初始数据将只能在 TestCase
测试中使用,而不能在 TransactionTestCase
测试中使用,此外,只有在支持事务的后端(最重要的例外是 MyISAM)上才能使用。对于依赖 TransactionTestCase
的测试也是如此,比如 LiveServerTestCase
和 StaticLiveServerTestCase
。
Django 可以通过在 TestCase
或 TransactionTestCase
中设置 serialized_rollback
选项为 True
来为你重新加载每个测试用例的数据,但请注意,这将使测试套件的速度降低约 3 倍。
第三方应用程序或那些针对 MyISAM 开发的应用程序将需要设置这个功能;但是,一般来说,你应该针对事务性数据库开发你自己的项目,并在大多数测试中使用 TestCase
,因此不需要这个设置。
初始序列化通常是非常快的,但如果你希望从这个过程中排除一些应用程序(并稍微加快测试运行速度),你可以将这些应用程序添加到 TEST_NON_SERIALIZED_APPS
。
为了防止序列化数据被加载两次,设置 serialized_rollback=True
在刷新测试数据库时禁用 post_migrate
信号。
其他测试条件¶
无论配置文件中的 DEBUG
设置值是多少,所有的 Django 测试都以 DEBUG
=False 运行。这是为了确保你的代码观察到的输出与生产环境下的输出一致。
每次测试后都不会清除缓存,如果在生产环境中运行测试,则运行 "manage.py test fooapp" 可以将测试中的数据插入实时系统的缓存中,因为与数据库不同的是,没有使用单独的“测试缓存”。这种行为在未来 可能改变。
了解测试输出¶
当你运行测试时,你会看到一些消息,因为测试运行器正在做准备。你可以通过命令行上的 verbosity
选项来控制这些消息的详细程度:
Creating test database... Creating table myapp_animal Creating table myapp_mineral
这告诉你测试运行程序正在创建测试数据库,如上一节所述。
创建测试数据库后,Django 将运行你的测试。 如果一切顺利,你会看到类似以下内容的信息:
---------------------------------------------------------------------- Ran 22 tests in 0.221sOK
但是,如果有测试失败,你会看到关于哪些测试失败的完整细节:
====================================================================== FAIL: test_was_published_recently_with_future_poll (polls.tests.PollMethodTests) ---------------------------------------------------------------------- Traceback (most recent call last):File "/dev/mysite/polls/tests.py", line 16, in test_was_published_recently_with_future_pollself.assertIs(future_poll.was_published_recently(), False) AssertionError: True is not False---------------------------------------------------------------------- Ran 1 test in 0.003sFAILED (failures=1)
对这个错误输出的完整解释超出了本文的范围,但它非常直观。你可以参考 Python 的 unittest
库的文档以了解详细信息。
请注意,对于任何数量的失败和错误测试,test-runner 脚本的返回码均为 1。 如果所有测试均通过,则返回码为 0。如果你在 shell 脚本中使用 test-runner 脚本,并且需要在该级别上测试成功或失败,则此功能很有用。
加快测试¶
并行运行测试¶
只要测试正确隔离,你就可以并行运行它们以加快多核硬件的运行速度。 参见 test --parallel
.
密码哈希¶
默认密码哈希器在设计上相当慢。 如果要在测试中对许多用户进行身份验证,则可能需要使用自定义设置文件,并将 PASSWORD_HASHERS
设置为更快的哈希算法:
PASSWORD_HASHERS = ['django.contrib.auth.hashers.MD5PasswordHasher', ]
不要忘记在 PASSWORD_HASHERS
中包含在辅助工具中使用的任何哈希算法,如果有的话。
保留测试数据库¶
test --keepdb
选项在两次测试运行之间保留测试数据库。 它跳过了创建和销毁操作,这可以大大减少运行测试的时间。
Django测试文件——tests.py相关推荐
- python eel 安卓_测试Eel——进行py与js文件数据传输
前言 放假在家无聊,翻开吃灰的收藏夹 收藏了这么久的的吗(=・ω・=) 看着这些尘封已久的宝典,自责不已,下定决心要好好学习一番(误)!编程新手,兴趣使然,纯属分享学习经历!有错误欢迎大佬指正. 准备 ...
- Django常用命令django-admin.py和manage.py用法详解
学习Django你需要了解常见命令的使用,比如创建项目,创建应用,创建超级用户,数据表创建及更新,启动服务器等.这些命令都包含在django-admin.py和manage.py里.除此以外manag ...
- 系统学习Python——单元测试unittest:批量执行测试文件
分类目录:<系统学习Python>总目录 相关文章: · 单元测试unittest:框架结构 · 单元测试unittest:测试固件 · 单元测试unittest:编写测试用例 · 单元测 ...
- 组合使用Laravel和vfsStream测试文件上传
核心要点 \ 在应用开发中,测试是很重要的,在诸多的开发工具中,测试驱动开发是很伟大的一项: \ 测试文件上传并不像人们想象的那么简单: \ 目前,有很多很棒,但不为大家所熟知的测试工具: \ Lar ...
- Django静态文件处理、中间件及Admin站点
Django静态文件处理.中间件及Admin站点 文章目录 Django静态文件处理.中间件及Admin站点 一.静态文件 1.简介 2.示例 3.配置静态文件 二.中间件 1.简介 2.示例 3.异 ...
- 《Python Cookbook 3rd》笔记(5.12):测试文件是否存在
测试文件是否存在 问题 你想测试一个文件或目录是否存在. 解法 使用 os.path 模块来测试一个文件或目录是否存在.比如: >>> import os >>> ...
- 解决Django静态文件配置pycharm高光问题
就困扰了我半天的Django静态文件配置问题 更改了setting 文件后 文件参考问题总会高亮让然觉得又错误怪怪的 所以索性直接眼不见心不烦 具体操作如下图: 就这样就可以啦 大功告成! 也顺便提一 ...
- Django 静态文件处理
Django 静态文件处理 前言 配置 staticfiles STATIC_URL STATICFILES_DIRS STATIC_ROOT 前言 Django的静态文件不能像html那样直接放上图 ...
- TUM数据集官方说明相应的评估文件evaluate_rpe.py和evaluate_ate.py的使用
一.TUM数据集使用方法 TUM数据集的格式解读地址:https://vision.in.tum.de/data/datasets/rgbd-dataset/file_formats TUM的RGBD ...
- Django实现文件分享系统
Django实现文件分享系统 一.效果展示 文件上传和展示: 文件搜索: 文件下载: 删除文件: 二.关键代码 #urls.py from django.urls import path,re_pat ...
最新文章
- Unknown CMake command add_compile_definitions
- 成功解决Git Bash运行脚本命令下载文件到默认C盘路径的问题
- 开始→运行→命令 总结大全
- mysql 字符串 截取字母_MySQL字符串函数:字符串截取
- java计算棋盘上的麦粒
- centos安装DHCP服务器
- Ajax_jquery库中Ajax方法的使用
- 【ERP流程图】:生产制造
- android 滚动条 惯性,Android ScrollView取消惯性滚动的方法
- OVM虚拟化,做Openstack的减法
- webgl1到webgl2_我如何使用WebGL重建Gorillaz Andromeda音乐视频
- 地图作业平台低代码实战(搭建能力提升)
- 频繁用电脑打字 武汉大三女生求职提笔忘字
- 业界首个,冲量在线联合海光信息发布异构隐私计算一体机!
- vscode 下载 安装
- 打电话显示短信呼服务器,已启用短信呼服务 已启用短信呼服务是什么意思
- (六) kityminder 协同编辑执行用例时,如果做到不相互干扰
- 猫猫学IOS(六)UI之iOS热门游戏_超级猜图
- 小程序mpvue图片绘制水印_mpvue开发小程序如何使用腾讯官方小程序插件--地图
- GBaseDataStudio 管理工具
热门文章
- 计算机与电视如何通过网络连接,怎么设置电脑和电视共用一根网线上网
- 对Orders订单表中的常见统计查询
- Think:研究生期间的迷茫、困惑——放平心态,奋力拼搏
- pyimagesearch-5 霍比特人和直方图 - 使用Python构建您的第一个图像搜索引擎的操作指南
- 核磁谱图分析步骤_核磁共振解析图谱的步骤
- Go的编译原理系列二之编译过程
- 点燃我温暖你 李峋 两种爱心代码
- 【数据库系统】考虑题4所示的日志记录,假设开始时A、B、C的值都是0 (1) 如果系统故障发生在14之后,写出系统恢复后A、B、C的值
- 用c语言编程,统计大写字母,小写字母,数字,其他字符的个数,用C语言:输入一行字符,不超过50个,统计出其中英文大写字母,小写字母,数字,空格以及其他字符个数...
- Service Temporarily Unavailable