运行测试#
Bokeh 是一个大型的多语言项目,依赖于复杂且全面的测试和测试工具,以帮助确保一致性并防止回归。
本章描述了如何在 本地开发环境 和 Bokeh 在 GitHub 上的持续集成 (CI) 系统 中运行各种测试。
本地测试#
几乎所有的Bokeh测试都可以在本地运行。然而,有些测试在本地系统上设置和正确运行可能会比较复杂。因此,当你在Bokeh的GitHub仓库上创建一个Pull Request时,所有测试都将在Bokeh的CI中运行。你不需要在本地设置和运行所有测试。
遵循以下一般准则来决定在本地运行哪些测试:
- Whenever you change anything in Bokeh’s codebase
运行Bokeh的代码库测试
- When you edit Bokeh’s Python code
运行Bokeh的Python单元测试
- When your work involves UI elements
运行Bokeh的Python集成测试
- When your change anything related to BokehJS
运行Bokeh的JavaScript测试
作为参考,本节概述了所有可用的测试以及如何在大多数系统上本地运行它们。通常,只运行与您正在处理的内容相关的特定测试是最有意义的。有关如何选择和取消选择特定Python测试的说明,请参见选择特定测试。有关如何选择和取消选择特定BokehJS测试的说明,请参见选择特定BokehJS测试。
检查基本要求#
在尝试本地运行Bokeh测试之前,请确保您已成功完成本贡献指南中设置开发环境部分的所有步骤。
通过运行 pip install bokeh_sampledata
来检查 Bokeh 的示例数据 是否已安装并更新到最新版本。如果您无法在系统上安装示例数据,您可以选择 禁用这些特定测试。
一些测试还需要在您的系统上安装Selenium和相应的web driver。虽然可以使用其他web驱动程序进行某些测试,但推荐的设置是使用Selenium与ChromeDriver和Chrome。有关安装说明和更多信息,请参阅附加依赖项。如果您的系统上没有安装Selenium,您可以选择禁用这些特定测试。
在某些Unix平台上,您可能还需要增加“最大打开文件描述符的数量”。一些测试在测试服务器时会打开许多文件,因此这个数字应该至少为1024。
ulimit -n 1024
运行代码库测试#
最基本的测试集是Bokeh的代码库测试。这包括使用Ruff检查Python代码,使用ESLint检查JavaScript代码,以及各种其他测试,如未使用的导入和多余的空格。
您对Bokeh的Python或JavaScript代码库所做的任何编辑都应通过此测试。
从仓库的顶层运行此命令:
pytest tests/codebase
运行Python测试#
Bokeh 包含了许多专注于 Bokeh 的 Python 代码的测试。 这些测试使用 pytest,并位于 tests 文件夹中。
每当您使用Bokeh的Python代码时,您应该运行Bokeh的 代码库和 Python单元测试。如果 您的工作还包括对用户界面元素的更改,您还应该运行 Bokeh的Python集成测试。
这些是一些命令行参数,对于pytest
来说,在处理基于Bokeh的pytest测试时了解这些参数会很有帮助:
-k
: 提供一个搜索字符串以筛选特定测试。参见 选择特定测试。-m
: 根据标记选择或取消选择特定测试。参见 选择特定测试。-n
: 将测试分布在多个CPU或核心上。提供一个数字来定义要使用的核心数量。设置为auto
以使用所有可用的核心。例如:pytest -n 4 tests/codebase
。参见pytest-xdist。-v
: 以更详细的输出运行测试。--driver
: 为基于Selenium的测试使用特定的网页驱动 ("chrome"
,"firefox"
, 或"safari"
). 例如:pytest --driver="firefox" tests/unit/
.--no-js
: 跳过任何JavaScript代码,仅测试Python代码。
查看 pytest 文档 获取更多选项。
- Unit tests
要运行Bokeh的Python单元测试,请在仓库的顶层使用以下命令:
pytest -m "not selenium" tests/unit
注意
此命令将排除需要Selenium的单元测试。因为 Selenium可能难以设置,而且一些单元测试需要 geckodriver和ChromeDriver在您的系统上可用, 使用
-m "not selenium"
是本地运行单元测试的推荐方式。一旦您创建拉取请求,Bokeh的CI将运行所有测试,包括 基于Selenium的单元测试。如果您的系统上同时有Selenium、geckodriver和 ChromeDriver可用,您可以使用pytest tests/unit
运行所有单元测试。
- Code coverage (Python unit tests)
要为Python单元测试创建覆盖率报告,请使用
pytest
并带上命令行选项--cov=bokeh
:pytest --cov=bokeh
Bokeh的Python单元测试覆盖率应达到约90%。覆盖率报告仅与Python单元测试相关。对于其他Python测试或BokehJS的任何JavaScript代码,没有覆盖率报告。
您还可以选择在运行特定的Python单元测试子集时添加
--cov=bokeh
。这会在测试结果中添加一个覆盖率报告。例如:pytest --cov=bokeh --cov-report=html -m "not selenium" tests/unit/bokeh/test_objects.py
另请参阅
覆盖率报告使用pytest插件pytest-cov。更多信息,请参阅pytest-cov的文档。
- Cross integration tests
有一些Python到JS接口测试,在Bokeh的一侧运行Python代码示例(测试用例),生成带有序列化文档的JSON输出。然后该JSON存储在仓库中的
tests/baselines/cross
下。添加新测试用例时,运行:pytest tests/test_cross.py
然后提交任何新的基线并重新运行测试。测试运行器只考虑已提交的基线。
每个测试用例在BokehJS中必须有一个对应的集成测试,位于
bokehjs/test/integration/cross.ts
下。这些测试等同于典型的BokehJS集成测试。然而,建议对于不需要检查输出视觉方面的测试,跳过图像差异比较。请注意,跳过图像捕获并不会禁用*.blf
文件的生成。请注意,交叉测试用例必须精心设计,以确保BokehJS能够运行它们并产生一致且可重复的输出,特别是在捕获图像时。与其他类型的测试一样,允许使用随机数据,因为测试运行器会为Python和numpy的随机数生成器设定种子。遵循BokehJS的指南来创建健壮的集成测试。
- Run all available tests
你可以通过从顶级目录运行以下命令来运行所有可用的测试(Python 和 JavaScript 单元测试、示例和集成测试):
pytest
- Select specific tests
要测试Bokeh包的一个子集,请将路径传递给
pytest
:pytest tests/unit/bokeh/models/
同样地,你可以通过将特定文件传递给
pytest
来运行特定的测试:pytest tests/unit/bokeh/models/test_grids.py
另一种选择或取消选择特定测试的方法是使用标记。 目前,Bokeh的测试使用以下两个标记:
sampledata
: 一个需要下载bokeh.sampledata
的测试selenium
: 一个需要selenium的测试
有关设置自定义标记的更多信息,请参阅 使用自定义标记 在 pytest 文档 中。要了解更多 关于 pytest 选择特定测试的各种选项,请参阅 指定要运行的测试。
另请参阅
有关添加和更新Python测试的信息,请参阅 编写Python测试。
运行JavaScript测试#
大多数基于JavaScript的BokehJS测试使用了一个自定义的测试框架。该框架需要Google Chrome或Chromium。您需要在系统上安装这些浏览器的最新版本,以便在本地运行这些测试。
运行所有BokehJS测试#
你可以使用 pytest
来运行所有可用的 BokehJS 测试:
pytest tests/test_bokehjs.py
这是运行所有BokehJS测试的快捷方式。你可以直接从源代码检出中的bokehjs子目录使用node make
运行相同的测试集:
node make test
这将运行代码库、默认值、单元和集成测试套件的组合。
选择特定的BokehJS测试#
您还可以选择单独运行这些测试套件,使用
node make test:suite_name
在源代码检出目录的 bokehjs 子目录中:
node make test:codebase
: 代码库测试检查文件大小限制node make test:defaults
: 测试检查Bokeh的Python模型中的默认值是否与Bokeh的JavaScript模型中的默认值匹配node make test:unit
: BokehJS的单元测试node make test:integration
: 视觉集成测试,将本地生成的图表与一组基线文件进行比较
你可以通过运行node make test:lib
来合并最后两个测试套件。
此外,您可以使用搜索字符串来选择单个测试或测试组。使用-k
参数提供您的搜索字符串。搜索字符串区分大小写。BokehJS测试框架尝试将您的搜索字符串与测试中describe()
和it()
函数中定义的字符串进行匹配。例如:
$ node make test:integration -k "Legend"
这将仅运行包含字符串“Legend”的集成测试。
注意
BokehJS 单元测试和集成测试需要最新版本的 Chrome 或 Chromium。BokehJS 测试框架会自动启动浏览器,并使用正确的设置以产生一致的测试结果。
使用开发工具服务器进行测试#
除了从命令行运行BokehJS测试外,您还可以使用BokehJS开发工具服务器。此系统要求您的系统上安装有Chrome网络浏览器。使用BokehJS开发工具服务器来运行测试并查看视觉测试的输出。
首先,从bokehjs子目录启动devtools服务器,使用以下命令:
$ node test/devtools server
listening on 127.0.0.1:5777
您现在可以使用devtools服务器进行以下操作:
- Inspecting visual test results
运行集成测试后,您可以使用开发工具服务器将本地结果与基线图像进行比较。在Chrome网络浏览器中打开显示的服务器URL(通常为
127.0.0.1:5777
)并附加/integration/report
。这将打开一个比较视图,显示任何本地渲染的图表与基线文件不同的测试。例如:- Initiate test runs
你也可以使用开发工具服务器来启动测试运行。你有两种选择:
- Run tests from a JavaScript console
在您的网页浏览器中打开以下三个端点之一:
/unit
/defaults
/integration
这将加载BokehJS和测试。要运行测试,请在Chrome的JavaScript控制台中输入
Tests.run_all()
。这允许你在运行代码之前设置断点。你还可以传递一个搜索字符串、字符串列表或正则表达式作为函数的query
参数,以仅运行特定的测试。例如:Tests.run_all(query=/[Ll]egend/);
- Use endpoint to run tests
通过使用浏览器访问以下任一端点来启动测试运行:
/unit/run
/defaults/run
/integration/run
要仅运行或查看特定测试,请在URL后附加?k=some%20text
。这将通过关键字过滤测试。
要仅运行或查看特定平台的测试,请在URL后附加platform=linux
、platform=macos
或platform=windows
。
有关添加和更新BokehJS测试的信息,请参阅 编写JavaScript测试(BokehJS)。
注意
在大多数情况下,使用常规的Chrome图形用户界面在本地运行测试的结果与在Bokeh的CI中使用无头版本的Chrome运行测试的结果是相同的。然而,在极少数情况下,无头Chrome和图形用户界面Chrome会产生不同的结果。在这种情况下,你不能使用图形用户界面——相反,你需要直接在无头浏览器中调试BokehJS的代码。更多信息请参见在无头Chrome中调试。
运行示例测试#
除了Bokeh的Python和JavaScript重点测试外,Bokeh还使用了一套示例测试。这套测试运行Bokeh仓库中的一部分示例,以检查每个示例是否能够构建而不产生错误。运行这些测试还会生成一个报告,其中包含这些图表的截图。
示例测试使用了一个主题测试框架,包括Chrome的自定义配置。因此,建议不要在本地运行这些测试。相反,一旦您创建了一个拉取请求,Bokeh的CI就会运行所有示例测试。
要在本地运行示例测试,首先需要在后台启动一个定制的无头版本的Chrome。这个无头浏览器需要从bokehjs
文件夹启动。请从您的源代码检出目录的顶层使用以下命令:
cd bokehjs
node make test:run:headless
这将启动一个无头Chrome工具。接下来,打开第二个终端并从您的源代码检出目录的顶层运行测试:
pytest tests/test_examples.py
运行测试时,pytest 还会生成一份报告,其中包含每个示例的视觉输出截图。这些截图可以在 examples-report.html
中找到。该文件位于您运行测试的同一目录中:

注意
示例测试不会分析生成的截图,因此不会基于视觉输出失败。您需要手动检查测试报告。
此外,示例测试会在同一目录下生成一个名为examples.log
的日志文件。
持续集成 (CI)#
每次你在Bokeh的GitHub仓库上启动一个Pull Request或向现有的Pull Request分支添加新的提交时,Bokeh的持续集成(CI)将在你的分支上运行所有可用的测试。
您可以在此URL查看所有当前和之前的CI运行列表: bokeh/bokeh
环境文件#
Bokeh的CI在Linux、macOS和Windows上运行测试。它还使用不同版本的Python运行测试。各种测试环境在conda文件夹中的各自YAML文件中定义。如果您添加或更改依赖项,您需要更新这些文件。
礼仪#
CI服务为开源项目提供有限的免费构建工作者。请在推送到GitHub之前将您的提交分组为有意义的工作块,而不是单独推送每个提交。这将帮助您体谅其他需要访问这些有限资源的人。