Django4.0 进阶测试主题-使用不同的测试框架
显然,unittest
并不是唯一的 Python 测试框架。虽然 Django 并没有提供对替代框架的明确支持,但它确实提供了一种方法来调用为替代框架构建的测试,就像它们是正常的 Django 测试一样。
当你运行 ./manage.py test
时,Django 会查看 TEST_RUNNER
的配置来决定做什么。默认情况下, TEST_RUNNER
指向 django.test.runner.DiscoverRunner
。这个类定义了默认的 Django 测试行为。这个行为包括:
- 进行全局性的测试前设置。
- 在当前目录下的任何文件中寻找名称符合 test*.py 模式的测试。
- 创建测试数据库。
- 运行 migrate 将模型和初始数据安装到测试数据库中。
- 运行 系统检查。
- 运行找到的测试。
- 销毁测试数据库。
- 进行全局性的测试后拆解。
如果你定义了自己的测试运行器类,并将 TEST_RUNNER
指向该类,那么每当你运行 ./manage.py test
时,Django 就会执行你的测试运行器。通过这种方式,可以使用任何可以从 Python 代码中执行的测试框架,也可以修改 Django 测试执行过程来满足你的任何测试需求。
定义测试运行器
测试运行器是一个类,他定义了 run_tests()
方法。Django 自带一个 DiscoverRunner
类,它定义了默认的 Django 测试行为。该类定义了进入点 run_tests()
,再加上对 run_tests()
所使用的其他方法的选择,以此来建立,执行和拆除测试套件。
class DiscoverRunner(pattern='test*.py', top_level=None, verbosity=1, interactive=True, failfast=False, keepdb=False, reverse=False, debug_mode=False, debug_sql=False, parallel=0, tags=None, exclude_tags=None, test_name_patterns=None, pdb=False, buffer=False, enable_faulthandler=True, timing=True, shuffle=False, logger=None, **kwargs)
DiscoverRunner
将在任何符合 pattern
的文件中搜索测试。
top_level
可以用来指定包含顶级 Python 模块的目录。通常 Django 会自动计算出这个目录,所以不需要指定这个选项。如果指定了这个选项,一般来说,它应该是包含你的 manage.py
文件的目录。
verbosity
决定将打印到控制台的通知和调试信息的数量;0 为无输出,1 为正常输出,2 为详细输出。
如果 interactive
是 True
,则测试套件在执行测试套件时,有权限向用户请求指令。这种行为的一个例子是要求允许删除一个现有的测试数据库。如果 interactive
为 False
,测试套件必须能够在没有任何人工干预的情况下运行。
如果 failfast
为 True
,测试套件将在检测到第一次测试失败后停止运行。
如果 keepdb
为 True
,测试套件将使用现有数据库,或在必要时创建一个数据库。如果 False
,将创建一个新的数据库,并提示用户删除现有的数据库。
如果 reverse
为 True
,则测试用例将以相反的顺序执行。 这对于调试未正确隔离并具有副作用的测试可能很有用。 使用此选项时会保留按测试类分组。 此选项可以与 --shuffle
结合使用,以反转特定随机种子的顺序。
debug_mode
指定 DEBUG
设置在运行测试之前应该设置成什么。
parallel
指定进程数。如果 parallel
大于 1,则测试套件会在 parallel
(平行)进程下运行。如果测试用例比配置的进程少,Django 将会相应地减少进程数量。每一个进程都有自己的数据库。该选择要求使用第三方包 tblib
来正确地显示回溯信息。
tags
用于指定一系列 测试标签。可以与 exclude_tags
结合使用。
exclude_tags
用于指定一系列 排除测试标签。可以与 tags
结合使用。
如果 debug_sql
为 True
,失败的测试用例会输出 SQL 查询记录到 django.db.backends logger
以及回溯。如果 verbosity
是 2,那么所有测试中的查询都会输出。
test_name_patterns
可以用来指定一套模式,通过名称过滤测试方法和类。
如果 pdb
为 True
,则每次测试错误或失败时都会产生一个调试器(pdb 或 ipdb)。
如果 buffer
为 True
,通过测试的输出将被丢弃。
如果 enable_faulthandler
是 True
,那么 faulthandler
将被启用。
如果 timing
是 True
,将显示测试时间,包括数据库设置和总运行时间。
如果 shuffle
是一个整数,则测试用例将在执行之前以随机顺序进行混洗,使用整数作为随机种子。 如果 shuffle
为 None
,则随机生成种子。 在这两种情况下,种子都会在运行测试之前被记录并设置为 self.shuffle_seed
。 此选项可用于帮助检测未正确隔离的测试。 使用此选项时会保留按测试类分组。
logger
可用于传递 Python Logger
对象。 如果提供,记录器将用于记录消息而不是打印到控制台。 记录器对象将尊重其记录级别而不是详细程度。
Django 可能会不时地通过添加新的参数来扩展测试运行器的功能。**kwargs
声明允许这种扩展。如果你将 DiscoverRunner
子类化,或者编写你自己的测试运行器,确保它接受 **kwargs
。
你的测试运行器也可以定义额外的命令行选项。创建或覆盖一个 add_arguments(cls, parser)
类方法,并通过在该方法中调用 parser.add_argument()
来添加自定义参数,这样 test
命令就可以使用这些参数。
属性
-
DiscoverRunner.test_suite
:用于构建测试套件的类。默认情况下,它被设置为 unittest.TestSuite
。如果你想实现不同的测试收集逻辑,可以重写这个类。 -
DiscoverRunner.test_runner
:这是低级测试运行器的类,用于执行各个测试和格式化结果。默认情况下,它被设置为 unittest.TextTestRunner
。尽管在命名习惯上有不幸的相似之处,但这与 DiscoverRunner
不是同一类型的类,后者涵盖了更广泛的职责。你可以覆盖这个属性来修改测试运行和报告的方式。 -
DiscoverRunner.test_loader
:这是一个加载测试的类,无论是从 TestCases 还是模块或其他方面加载测试,并将它们捆绑成测试套件供运行者执行。默认情况下,它被设置为 unittest.defaultTestLoader
。如果你的测试要以不寻常的方式加载,你可以重写这个属性。
方法
DiscoverRunner.run_tests(test_labels, **kwargs)
运行测试套件。
test_labels
允许你指定要运行的测试,并支持多种格式。
4.0 版后已移除:extra_tests
是一个额外的 TestCase
实例列表,用于添加到测试运行器执行的套件中。这些额外的测试是在 test_labels
中列出的模块中发现的测试之外运行的。
这个方法应该返回失败的测试次数。
classmethod DiscoverRunner.add_arguments(parser)
重写这个类方法来添加 test
管理命令接受的自定义参数。
DiscoverRunner.setup_test_environment(**kwargs)
通过调用 setup_test_environment()
和设置 DEBUG
为 self.debug_mode
(默认为 False
)来设置测试环境。
DiscoverRunner.build_suite(test_labels=None, **kwargs)
构建一个与提供的测试标签相匹配的测试套件。
test_labels
是描述要运行的测试的字符串列表。测试标签可以采取以下四种形式之一:
-
path.to.test_module.TestCase.test_method
——在测试用例中运行一个测试方法。 -
path.to.test_module.TestCase
——运行测试用例中的所有测试方法。 -
path.to.module
——搜索并运行命名的 Python 包或模块中的所有测试。 -
path/to/directory
——搜索并运行指定目录下的所有测试。
如果 test_labels
的值为 None
,测试运行器将在当前目录下所有文件中搜索名称符合 pattern
的测试。
4.0 版后已移除:extra_tests
是一个额外的 TestCase
实例列表,用于添加到测试运行器执行的套件中。这些额外的测试是在 test_labels
中列出的模块中发现的测试之外运行的。
返回一个准备运行的 TestSuite
实例。
DiscoverRunner.setup_databases(**kwargs)
通过调用 setup_databases()
创建测试数据库。
DiscoverRunner.run_checks(databases)
在测试的 databases
上运行 系统检查。
DiscoverRunner.run_suite(suite, **kwargs)
运行测试套件。
返回运行测试套件所产生的结果。
DiscoverRunner.get_test_runner_kwargs()
返回实例化 DiscoverRunner.test_runner
的关键字参数。
DiscoverRunner.teardown_databases(old_config, **kwargs)
通过调用 trapdown_databases()
来销毁测试数据库,恢复测试前的条件。
DiscoverRunner.teardown_test_environment(**kwargs)
恢复测试前的环境
DiscoverRunner.suite_result(suite, result, **kwargs)
计算并返回一个返回码,基于测试套件和测试套件返回的结果。
DiscoverRunner.log(msg, level=None)
如果设置了记录器,则以给定的整数记录级别记录消息(例如 logging.DEBUG
、logging.INFO
或 logging.WARNING
)。 否则,消息将打印到控制台,并考虑当前的详细程度。 例如,verbosity
为 0 时不打印消息,verbosity
至少为 1 时打印 INFO
及以上,至少为 2 时打印 DEBUG
。级别默认为 logging.INFO
。
测试工具集
django.test.utils
为了帮助创建自己的测试运行器,Django 在 django.test.utils
模块中提供了一些实用的方法。
setup_test_environment(debug=None)
执行全局性的测试前设置,如为模板渲染系统安装仪器,设置虚拟的电子邮件发件箱。
如果 debug
不是 None
,则 DEBUG 配置更新为其值。
teardown_test_environment()
进行全局性的测试后拆解,如从模板系统中删除仪器设备,恢复正常的邮件服务。
setup_databases(verbosity, interactive, *, time_keeper=None, keepdb=False, debug_sql=False, parallel=0, aliases=None, serialized_aliases=None, **kwargs)
创建测试数据库。
返回一个数据结构,该结构提供了足够的细节来撤销已做的更改。这些数据将在测试结束后提供给 teardown_databases()
函数。
aliases
参数确定应该为哪些 DATABASES
别名测试数据库设置。 如果未提供,则默认为所有 DATABASES
别名。
serialized_aliases
参数确定别名测试数据库的哪个子集应该对其状态进行序列化以允许使用 serialized_rollback
功能。 如果未提供,则默认为别名。
teardown_databases(old_config, parallel=0, keepdb=False)
销毁测试数据库,恢复测试前的条件。
old_config
是一个数据结构,定义了数据库配置中需要撤销的变化。它是 setup_databases()
方法的返回值。
django.db.connection.creation
数据库后台的创建模块还提供了一些在测试过程中有用的实用程序。
create_test_db(verbosity=1, autoclobber=False, serialize=True, keepdb=False)
创建一个新的测试数据库并对其运行 migrate
。
verbosity
与 run_tests()
中的行为相同。
autoclobber
描述了在发现与测试数据库同名的数据库时将发生的行为。
- 如果
autoclobber
为 False
,将要求用户批准销毁现有数据库。如果用户不同意,则调用 sys.exit
。 - 如果
autoclobber
为 True
,数据库将在不与用户协商的情况下被销毁。
serialize
决定 Django 是否在运行测试之前将数据库序列化为内存中的 JSON 字符串(如果没有事务,用于在测试之间恢复数据库状态)。如果你没有使用 serialized_rollback=True
的测试类,你可以将其设置为 False
以加快创建时间。
如果你使用的是默认的测试运行器,你可以通过 TEST
条目来控制。
keepdb
决定测试运行是否应使用现有数据库,还是创建一个新的数据库。如果 True
,则使用现有的数据库,如果不存在,则创建新的数据库。如果 False
,则创建一个新的数据库,并提示用户删除现有的数据库(如果存在)。
返回其创建的测试数据库的名称。
create_test_db()
的副作用是修改 DATABASES
中的 NAME
的值,使其与测试数据库的名称相匹配。
destroy_test_db(old_database_name, verbosity=1, keepdb=False)
销毁名称为 DATABASES
中 NAME
值的数据库,并将 NAME
设置为 old_database_name
值。
verbosity
参数和测试类 DiscoverRunner
的行为一样。
如果 keepdb
的参数为 True
,数据库连接会被关闭,但是数据库不会被销毁。