测试 🧪#
在本节中,我们将概述 Arrow 中单元测试所需的步骤。
我们在 Python 中使用 pytest 进行单元测试。有关所需软件包的更多信息,请参阅 Python 单元测试部分。
结构
PyArrow 中的测试布局遵循 pytest
将测试作为应用程序代码的一部分 的结构。
pyarrow/
__init__.py
csv.py
dataset.py
...
tests/
__init__.py
test_csv.py
test_dataset.py
...
Parquet 的测试位于单独的文件夹 pyarrow/tests/parquet/
中。
运行测试
要运行特定的单元测试,请在 arrow/python
文件夹的终端中使用以下命令
$ pytest pyarrow/tests/test_file.py -k test_your_unit_test
运行一个文件中的所有测试
$ pytest pyarrow/tests/test_file.py
运行所有测试
$ pytest pyarrow
您还可以使用 python -m pytest [...]
运行测试,这几乎等同于直接使用 pytest [...]
,不同之处在于通过 python 调用还会将当前目录添加到 sys.path
中,并且在某些情况下,如果 pytest [...]
导致 ImportError,则可能会有所帮助。
重新编译 PyArrow 或 Arrow C++
如果测试开始失败,请尝试重新编译 PyArrow 或 Arrow C++。请参阅 PyArrow 选项卡下 构建其他 Arrow 库 部分中的注释。
Fixtures
在 PyArrow 测试文件中,可以定义辅助函数和 Fixtures。也使用了其他 pytest 装饰器,例如 @parametrize
或 @skipif
。
例如
_alltypes_example
在test_pandas
中提供了一个包含 100 行所有数据类型的数据框。_check_pandas_roundtrip
在test_pandas
中断言从Pandas
通过pa.Table
或pa.RecordBatch
返回Pandas
的往返是否产生相同的结果。large_buffer
fixture 在test_serialization.py
中向函数test_primitive_serialization(large_buffer)
提供固定大小的 PyArrow 缓冲区。
因此,最好浏览一下您计划添加测试的文件,看看是否有任何已定义的函数或 fixture 对您有所帮助。
有关 pytest
的更多常规信息,请访问 完整的 pytest 文档
我们在 R 中使用 testthat 进行单元测试。更具体地说,我们使用 testthat 的第三版。在极少数情况下,我们可能需要 testthat 第二版的功能,这可以通过 testthat::local_edition(2)
来指示。
结构
预期 testthat 文件夹结构
tests
├── testthat # test files live here
└── testthat.R # runs tests when R CMD check runs (e.g. with devtools::check())
这是使用 testthat
在 R 中进行测试的基本结构。像 testthat.R
这样的文件预计不会经常更改。对于 arrow
R 包,testthat.R
还定义了如何在控制台中显示/报告各种测试的结果。
通常,R/
子文件夹中的大多数文件在 tests/testthat
中都有对应的测试文件
运行测试
要在本地运行包中的所有测试,请在 R 控制台中调用
devtools::test()
或者,您可以在 shell 中使用
$ make test
`R CMD check --run-tests arrow`
`devtools::test_file("tests/testthat/test-example.R")`
devtools::test_active_file()
所有测试也会作为我们持续集成 (CI) 流水线的一部分运行。
Arrow R 开发者指南也有一节 关于运行测试的内容。
良好实践
通常,任何对源代码的更改都需要 accompanied by 单元测试。所有测试都应在合并拉取请求之前通过。
添加功能 -> 添加单元测试
修改功能 -> 更新单元测试
解决错误 -> 在解决错误之前添加单元测试,这有助于证明错误及其修复
性能改进应反映在基准测试中(基准测试也是测试)
例外情况可能是完全由单元测试覆盖的重构功能
一个好的经验法则是:如果新功能是面向用户或 API 的更改,您几乎肯定需要更改测试——如果不需要更改测试,则可能意味着测试不正确!如果新功能是重构并且 API 没有更改,则可能不需要更改测试。
测试助手
为了补充 testthat
的功能,arrow
R 包定义了一系列特定的实用函数(称为助手),例如
期望 - 这些函数以
expect_
开头,用于比较对象例如,
expect_…_roundtrip()
函数接受一个输入,将其转换为某种其他格式(例如 arrow、altrep),然后再转换回来,确认值相同。x <- c(1, 2, 3, NA_real_) expect_altrep_roundtrip(x, min, na.rm = TRUE)
skip_
- 跳过单元测试 - 将它们视为可接受的失败。我们可能希望跳过单元测试的情况skip_if_r_version()
- 这是一个特定的arrow
跳过。例如,我们使用它在 R 版本为 3.5.0 及以下时跳过单元测试(skip_if_r_version("3.5.0")
)。当我们测试的功能依赖于 R 3.5.0 版本之后引入的功能(例如在 R 3.5.0 中引入的向量的替代表示形式 Altrep,但在后续版本中进行了重大补充)时,您可能会看到它被使用。作为我们 CI 工作流程的一部分,我们针对不同版本的 R 进行测试,这就是此功能的用武之地。skip_if_not_available()
- 另一个特定的 {arrow} 跳过。Arrow (libarrow) 有许多可选功能,可以在构建时打开或关闭。如果单元测试依赖于 such a 功能,并且此功能不可用(即在构建 libarrow 时未选择),则会跳过该测试,而不是进行失败的测试。skip_if_offline()
- 不会运行需要互联网连接的测试skip_on_os()
- 适用于特定操作系统的单元测试
重要提示:一旦满足
skip_()
语句的条件,同一个test_that()
测试块中的其他代码行将不会被执行。如果skip
在test_that()
代码块之外,它将跳过文件的其余部分。
有关 R 中单元测试的更多常规信息