添加和运行测试
高质量的测试套件对于确保代码库的正确性和健壮性至关重要。在这里,我们提供如何运行单元测试以及如何添加新测试的说明。
目录
添加新的单元测试
Python 包:pytest
将您的测试添加到以下目录中
tests/python-gpu/ (如果您正在测试 GPU 代码)
tests/test_distributed. (如果使用了分布式框架)
请参考PyTest 教程,学习如何为 Python 代码编写测试。
您可以按照本节中的说明尝试运行您的测试。
C++:Google Test
将您的测试添加到目录tests/cpp/下。请参考这个关于使用 Google Test 的优秀教程。
您可以按照本节中的说明尝试运行您的测试。注意:需要 Google Test 版本 1.8.1 或更高。
JVM 包:JUnit / scalatest
XGBoost 的 JVM 包(XGBoost4J / XGBoost4J-Spark)使用Maven 标准目录布局。具体来说,JVM 包的测试位于以下位置
要编写 Java 代码的测试,请参阅JUnit 5 教程。要编写 Scala 代码的测试,请参阅Scalatest 教程。
您可以按照本节中的说明尝试运行您的测试。
R 包:testthat
将您的测试添加到目录R-package/tests/testthat下。请参考这个关于 testthat 的优秀教程。
您可以按照本节中的说明尝试运行您的测试。
本地运行单元测试
R 包
运行
python ./ops/script/test_r_package.py --task=check
在项目根目录下。该命令会构建并检查 XGBoost r-package。或者,如果您只想运行测试,可以在安装 XGBoost 后使用以下命令
cd R-package/tests/
Rscript testthat.R
JVM 包
使用 Maven
mvn test
Python 包:pytest
要运行 Python 单元测试,首先安装pytest 包
pip3 install pytest
然后按照构建共享库中的说明编译 XGBoost。最后,在项目根目录调用 pytest
# Tell Python where to find XGBoost module
export PYTHONPATH=./python-package
pytest -v -s --fulltrace tests/python
此外,要测试 CUDA 代码,运行
# Tell Python where to find XGBoost module
export PYTHONPATH=./python-package
pytest -v -s --fulltrace tests/python-gpu
(对于此步骤,您应该已编译启用 CUDA 的 XGBoost。)
要使用分布式框架(如 Dask
和 PySpark
)进行测试
# Tell Python where to find XGBoost module
export PYTHONPATH=./python-package
pytest -v -s --fulltrace tests/test_distributed
C++:Google Test
要构建和运行 C++ 单元测试,请在运行 CMake 时启用测试
cmake -B build -S . -GNinja -DGOOGLE_TEST=ON -DUSE_DMLC_GTEST=ON -DUSE_CUDA=ON -DUSE_NCCL=ON
cmake --build build
cd ./build
./testxgboost
诸如 USE_CUDA
, USE_DMLC_GTEST
之类的标志是可选的。有关如何从源代码构建 XGBoost 的更多信息,请参阅从源代码构建。也可以使用 ctest 工具运行所有单元测试,该工具提供更高的灵活性。例如
ctest --verbose
如果您需要在 Windows 上使用 VS 调试器调试错误,可以在 test_main.cc 中附加 gtest 标志
::testing::GTEST_FLAG(filter) = "Suite.Test";
::testing::GTEST_FLAG(repeat) = 10;
Sanitizers:检测内存错误和数据竞争
默认情况下,sanitizers 已捆绑在 GCC 和 Clang/LLVM 中。可以使用 GCC >= 4.8 或 LLVM >= 3.1 启用 sanitizers,但某些发行版可能会单独打包 sanitizers。以下是支持的 sanitizers 及其相应的库名称列表
Address sanitizer: libasan
Undefined sanitizer: libubsan
Leak sanitizer: liblsan
Thread sanitizer: libtsan
Memory sanitizer 是 LLVM 独有的,因此 XGBoost 不支持。使用像 gcc-9 这样的最新编译器时,指定 sanitizer 标志后,编译器驱动程序应该能够自动链接运行时库。
如何使用 sanitizers 构建 XGBoost
通过指定 -DUSE_SANITIZER=ON,可以构建支持 sanitizer 的 XGBoost。默认情况下,当您打开 USE_SANITIZER 标志时,会使用 address sanitizer 和 leak sanitizer。您始终可以通过向 ENABLED_SANITIZERS 提供以分号分隔的 sanitizer 列表来更改默认设置。请注意,thread sanitizer 与其他两个 sanitizer 不兼容。
cmake -DUSE_SANITIZER=ON -DENABLED_SANITIZERS="address;undefined" /path/to/xgboost
默认情况下,CMake 会在常规系统路径中搜索 sanitizers,您也可以提供指定的 SANITIZER_PATH。
cmake -DUSE_SANITIZER=ON -DENABLED_SANITIZERS="address;undefined" \
-DSANITIZER_PATH=/path/to/sanitizers /path/to/xgboost
如何将 sanitizers 与 CUDA 支持一起使用
在 CUDA 上使用 address sanitizer (asan) 运行 XGBoost 会引发内存错误。要正确地将 asan 与 CUDA 一起使用,您需要通过 ASAN_OPTIONS 环境变量配置 asan
ASAN_OPTIONS=protect_shadow_gap=0 ${BUILD_DIR}/testxgboost
其他 sanitizer 运行时选项
默认情况下,undefined sanitizer 不会打印出回溯。您可以通过导出环境变量来启用它
UBSAN_OPTIONS=print_stacktrace=1 ${BUILD_DIR}/testxgboost
详细信息请参考sanitizers 的官方文档。