Django自带了一套测试套件, tests
代码库的目录。我们的政策是确保所有测试始终通过。
我们感谢您对测试套件的所有贡献!
Django测试都使用Django附带的测试基础设施来测试应用程序。见 编写和运行测试 关于如何编写新测试的解释。
第一, fork Django on GitHub .
第二,创建并激活虚拟环境。如果您不熟悉如何操作,请阅读我们的 contributing tutorial .
接下来,克隆您的fork,安装一些需求并运行测试:
$ git clone https://github.com/YourGitHubName/django.git django-repo
$ cd django-repo/tests
$ python -m pip install -e ..
$ python -m pip install -r requirements/py3.txt
$ ./runtests.py
...\> git clone https://github.com/YourGitHubName/django.git django-repo
...\> cd django-repo\tests
...\> py -m pip install -e ..
...\> py -m pip install -r requirements\py3.txt
...\> runtests.py
安装这些要求可能需要一些您的计算机尚未安装的操作系统包。您通常可以通过在Web上搜索错误消息的最后一行来确定要安装哪个包。如果需要,尝试将您的操作系统添加到搜索查询中。
如果在安装需求时遇到问题,可以跳过这一步。见 运行所有测试 有关安装可选测试依赖项的详细信息。如果没有安装可选的依赖项,则将跳过需要它的测试。
运行测试需要Django设置模块,该模块定义要使用的数据库。为了帮助您入门,Django提供并使用了一个使用SQLite数据库的示例设置模块。看到 使用另一个 settings 模块 了解如何使用不同的设置模块通过不同的数据库运行测试。
有问题吗?见 故障排除 一些常见问题。
tox
¶Tox 是用于在不同虚拟环境中运行测试的工具。Django包括一个基本的 tox.ini
这会自动执行我们的构建服务器对拉请求执行的一些检查。要运行单元测试和其他检查(如 import sorting vt.的. documentation spelling checker ,以及 code formatting ),安装并运行 tox
来自Django源代码树中任何位置的命令:
$ python -m pip install tox
$ tox
...\> py -m pip install tox
...\> tox
默认情况下, tox
运行带有捆绑的SQLite测试设置文件的测试套件, black
, blacken-docs
, flake8
, isort
和文档拼写检查器。除了本文档中其他地方提到的系统依赖项外,命令 python3
必须位于您的路径上,并链接到适当版本的Python。默认环境列表如下所示:
$ tox -l
py3
black
blacken-docs
flake8>=3.7.0
docs
isort>=5.1.0
...\> tox -l
py3
black
blacken-docs
flake8>=3.7.0
docs
isort>=5.1.0
除了默认环境之外, tox
支持为其他版本的Python和其他数据库后端运行单元测试。然而,由于Django的测试套件不捆绑除SQLite之外的数据库后端的设置文件,因此您必须 create and provide your own test settings 。例如,要使用PostgreSQL在Python3.10上运行测试:
$ tox -e py310-postgres -- --settings=my_postgres_settings
...\> tox -e py310-postgres -- --settings=my_postgres_settings
此命令设置一个Python3.10虚拟环境,安装Django的测试套件依赖项(包括用于PostgreSQL的依赖项),并调用 runtests.py
使用提供的参数(在本例中, --settings=my_postgres_settings
)。
本文档的其余部分显示了在 tox
但是,任何选项都传递给 runtests.py
也可以传递给 tox
通过在参数列表前加前缀 --
,如上所述。
Tox
也尊重 DJANGO_SETTINGS_MODULE
环境变量(如果设置)。例如,以下命令等同于上面的命令:
$ DJANGO_SETTINGS_MODULE=my_postgres_settings tox -e py310-postgres
Windows用户应该用途:
...\> set DJANGO_SETTINGS_MODULE=my_postgres_settings
...\> tox -e py310-postgres
Django包括一套 JavaScript unit tests 用于某些contrib应用程序中的功能。默认情况下,JavaScript测试不会使用 tox
因为它们需要 Node.js
需要安装,并且对于大多数补丁来说不是必需的。要使用运行JavaScript测试 tox
:
$ tox -e javascript
...\> tox -e javascript
此命令运行 npm install
确保测试需求是最新的,然后运行 npm test
.
django-docker-box
¶django-docker-box 允许您在所有支持的数据库和Python版本上运行Django的测试套件。看到 django-docker-box 项目页面,了解安装和使用说明。
settings
模块¶包含的设置模块 (tests/test_sqlite.py
)允许您使用SQLite运行测试套件。如果要使用不同的数据库运行测试,则需要定义您自己的设置文件。一些测试,例如用于 contrib.postgres
是特定于特定数据库后端的,如果使用不同的后端运行,将被跳过。特定数据库后端上的某些测试被跳过或预期会失败(请参见 DatabaseFeatures.django_test_skips
和 DatabaseFeatures.django_test_expected_failures
在每个后端上)。
要以不同设置运行测试,请确保该模块位于 PYTHONPATH
并通过模块 --settings
。
这个 DATABASES
任何测试设置模块中的设置都需要定义两个数据库:
A default
数据库。此数据库应使用要用于主测试的后端。
具有别名的数据库 other
. 这个 other
数据库用于测试查询是否可以定向到不同的数据库。此数据库应使用与 default
,它必须有一个不同的名称。
如果您使用的后端不是sqlite,则需要为每个数据库提供其他详细信息:
测试数据库通过预先准备获取名称 test_
价值 NAME
中定义的数据库的设置 DATABASES
. 测试完成后,这些测试数据库将被删除。
您还需要确保数据库使用UTF-8作为默认字符集。如果数据库服务器不使用utf-8作为默认字符集,则需要包含 CHARSET
在适用数据库的测试设置字典中。
Django的整个测试套件需要一段时间才能运行,并且如果您只是在Django中添加了一个您希望在不运行其他所有测试的情况下快速运行的测试,那么运行每个测试可能是多余的。通过将测试模块的名称附加到 runtests.py
在命令行上。
例如,如果您只想对类属关系和国际化运行测试,请输入:
$ ./runtests.py --settings=path.to.settings generic_relations i18n
...\> runtests.py --settings=path.to.settings generic_relations i18n
如何找出各个测试的名称?拜访 tests/
-每个目录名都有一个测试的名称。
如果您只想运行特定的测试类,则可以指定各个测试类的路径列表。例如,要运行 TranslationTests
的 i18n
模块,类型:
$ ./runtests.py --settings=path.to.settings i18n.tests.TranslationTests
...\> runtests.py --settings=path.to.settings i18n.tests.TranslationTests
除此之外,您还可以像这样指定单个测试方法:
$ ./runtests.py --settings=path.to.settings i18n.tests.TranslationTests.test_lazy_objects
...\> runtests.py --settings=path.to.settings i18n.tests.TranslationTests.test_lazy_objects
您可以从指定的顶级模块开始运行测试 --start-at
选项.例如:
$ ./runtests.py --start-at=wsgi
...\> runtests.py --start-at=wsgi
您还可以在指定的顶级模块之后运行测试, --start-after
选项.例如:
$ ./runtests.py --start-after=wsgi
...\> runtests.py --start-after=wsgi
请注意, --reverse
选项不影响 --start-at
或 --start-after
选项.此外,这些选项不能与测试标签一起使用。
有些测试需要硒和网络浏览器。要运行这些测试,您必须安装 selenium 打包并使用 --selenium=<BROWSERS>
选择。例如,如果您安装了Firefox和Google Chrome:
$ ./runtests.py --selenium=firefox,chrome
...\> runtests.py --selenium=firefox,chrome
见 selenium.webdriver 可用浏览器列表的包。
指定 --selenium
自动设置 --tags=selenium
只运行需要硒的测试。
某些浏览器(例如Chrome或Firefox)支持无头测试,这样可以更快、更稳定。添加 --headless
启用此模式的选项。
为了测试对管理用户界面的更改,可以使用 --screenshots
选项已启用。屏幕截图将保存到 tests/screenshots/
目录。
要定义在Selify测试期间何时应该截取屏幕截图,测试类必须使用 @django.test.selenium.screenshot_cases
具有支持的屏幕截图类型列表的修饰器 ("desktop_size"
, "mobile_size"
, "small_screen_size"
, "rtl"
, "dark"
,以及 "high_contrast"
)。然后,它可以调用 self.take_screenshot("unique-screenshot-name")
在所需的点生成屏幕截图。例如::
from django.test.selenium import SeleniumTestCase, screenshot_cases
from django.urls import reverse
class SeleniumTests(SeleniumTestCase):
@screenshot_cases(["desktop_size", "mobile_size", "rtl", "dark", "high_contrast"])
def test_login_button_centered(self):
self.selenium.get(self.live_server_url + reverse("admin:login"))
self.take_screenshot("login")
...
这会生成登录页面的多个屏幕截图-一个用于桌面屏幕,一个用于移动屏幕,一个用于桌面上从右到左语言,一个用于桌面上的黑暗模式,一个用于使用Chrome时桌面上的高对比度模式。
这个 --screenshots
选项和 @screenshot_cases
添加了装饰师。
如果要运行完整的测试套件,则需要安装一些依赖项:
argon2-cffi 19.2.0+
asgiref 3.7.0+(必填)
colorama 0.4.6+
docutils 0.19+
Jinja2 2.11+
Pillow 6.2.1+
pytz (必需)
redis 3.4+
selenium 4.8.0+
sqlparse 0.3.1+(必填)
tblib 1.5.0+
您可以在中找到这些依赖项 pip requirements files 内部 tests/requirements
Django源代码树的目录并按如下方式安装它们:
$ python -m pip install -r tests/requirements/py3.txt
...\> py -m pip install -r tests\requirements\py3.txt
如果在安装过程中遇到错误,您的系统可能缺少一个或多个Python包的依赖项。请参考失败包的文档或使用您遇到的错误消息在Web上搜索。
您也可以使用安装您选择的数据库适配器 oracle.txt
, mysql.txt
或 postgres.txt
.
如果您想测试Memcached或Redis缓存后端,您还需要定义 CACHES
设置分别指向您的Memcached或Redis实例。
要运行GeoDjango测试,您需要 set up a spatial database and install the Geospatial libraries 。
每个依赖项都是可选的。如果您丢失了其中的任何一个,则将跳过相关的测试。
要运行某些自动重新加载测试,您需要安装 Watchman 服务。
鼓励参与者在测试套件上运行覆盖范围,以确定需要额外测试的区域。覆盖工具的安装和使用在 testing code coverage .
要使用标准测试设置在Django测试套件上运行覆盖:
$ coverage run ./runtests.py --settings=test_sqlite
...\> coverage run runtests.py --settings=test_sqlite
运行Coverage后,通过运行以下命令合并所有Coverage统计信息:
$ coverage combine
...\> coverage combine
之后,通过运行以下命令生成html报告:
$ coverage html
...\> coverage html
当运行Django测试的覆盖范围时,包括 .coveragerc
设置文件定义 coverage_html
作为报告的输出目录,也排除了与结果无关的几个目录(测试代码或Django中包含的外部代码)。
Contrrib应用程序的测试可在 tests/ 目录,通常位于 <app_name>_tests
。例如,测试 contrib.auth
位于 tests/auth_tests 。
main
支部¶确保您拥有最新版本的 supported Python version ,因为早期版本中经常存在可能导致测试套件失败或挂起的错误。
在……上面 macOS (较高的Sierra和更新版本),您可能会看到记录此消息,在此之后测试挂起:
objc[42074]: +[__NSPlaceholderDate initialize] may have been in progress in
another thread when fork() was called.
要避免这种设置,请使用 OBJC_DISABLE_INITIALIZE_FORK_SAFETY
环境变量,例如:
$ OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES ./runtests.py
或添加 export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
到Shell的启动文件(例如 ~/.profile
)。
UnicodeEncodeError
¶如果 locales
未安装包,某些测试将失败 UnicodeEncodeError
.
您可以在基于Debian的系统上解决此问题,例如,通过运行以下步骤:
$ apt-get install locales
$ dpkg-reconfigure locales
您可以通过配置Shell的区域设置来解决macOS系统的这个问题:
$ export LANG="en_US.UTF-8"
$ export LC_ALL="en_US.UTF-8"
运行 locale
命令确认更改。或者,将这些导出命令添加到shell的启动文件(例如 ~/.bashrc
为了避免重打。
如果一个测试在单独运行时通过,但在整个套件中失败,那么我们有一些工具来帮助分析问题。
这个 --bisect
选择权 runtests.py
将运行失败的测试,同时将在每次迭代中与之一起运行的测试集减半,通常使识别可能与失败相关的少量测试成为可能。
例如,假设单独工作的失败测试是 ModelTest.test_eq
,然后使用:
$ ./runtests.py --bisect basic.tests.ModelTest.test_eq
...\> runtests.py --bisect basic.tests.ModelTest.test_eq
将尝试确定干扰给定测试的测试。首先,使用测试套件的前半部分运行测试。如果发生故障,测试套件的前半部分将分为两组,然后使用指定的测试运行每个组。如果测试套件的前半部分没有失败,则使用指定的测试运行测试套件的后半部分,并按照前面的描述适当地拆分。该过程将重复,直到将失败的测试集最小化。
这个 --pair
选项将给定测试与套件中的所有其他测试一起运行,让您检查另一个测试是否具有导致失败的副作用。所以:
$ ./runtests.py --pair basic.tests.ModelTest.test_eq
...\> runtests.py --pair basic.tests.ModelTest.test_eq
威尔对 test_eq
每个测试标签。
两者都有 --bisect
和 --pair
,如果您已经怀疑哪些情况可能导致失败,则可以限制测试进行交叉分析 specifying further test labels 在第一个之后:
$ ./runtests.py --pair basic.tests.ModelTest.test_eq queries transactions
...\> runtests.py --pair basic.tests.ModelTest.test_eq queries transactions
方法以随机或相反的顺序运行任何一组测试。 --shuffle
和 --reverse
选择。这有助于验证以不同的顺序执行测试不会导致任何问题:
$ ./runtests.py basic --shuffle
$ ./runtests.py basic --reverse
...\> runtests.py basic --shuffle
...\> runtests.py basic --reverse
如果您希望检查在失败的测试中运行的SQL,可以打开 SQL logging 使用 --debug-sql
选项.如果你将此与 --verbosity=2
,将输出所有SQL查询:
$ ./runtests.py basic --debug-sql
...\> runtests.py basic --debug-sql
默认情况下,测试并行运行,每个核心有一个进程。然而,当测试并行运行时,您只会看到任何测试失败的截断回溯。您可以使用调整此行为 --parallel
选项:
$ ./runtests.py basic --parallel=1
...\> runtests.py basic --parallel=1
您也可以使用 DJANGO_TEST_PROCESSES
为此目的的环境变量。
避免污染全球环境 apps
注册表并防止不必要的表创建,测试方法中定义的模型应绑定到临时 Apps
举个例子。为此,请使用 isolate_apps()
装饰师::
from django.db import models
from django.test import SimpleTestCase
from django.test.utils import isolate_apps
class TestModelDefinition(SimpleTestCase):
@isolate_apps("app_label")
def test_model_definition(self):
class TestModel(models.Model):
pass
...
设置 app_label
测试方法中定义的没有显式的模型 app_label
将自动为其测试类所在的应用程序分配标签。
为了确保在 isolate_apps()
实例安装正确,应通过目标 app_label
作为参数:
tests/app_label/tests.py
¶from django.db import models
from django.test import SimpleTestCase
from django.test.utils import isolate_apps
class TestModelDefinition(SimpleTestCase):
@isolate_apps("app_label", "other_app_label")
def test_model_definition(self):
# This model automatically receives app_label='app_label'
class TestModel(models.Model):
pass
class OtherAppModel(models.Model):
class Meta:
app_label = "other_app_label"
...
7月 22, 2024