测试 Conan 包

在之前的教程的所有部分中,我们都使用了test_package。它在构建我们的包之后,在 conan create 命令的末尾自动调用,以验证包是否创建正确。让我们在本节中更详细地解释一下test_package

请先克隆源代码以重新创建此项目。您可以在 GitHub 上的examples2 仓库中找到它们。

$ git clone https://github.com/conan-io/examples2.git
$ cd examples2/tutorial/creating_packages/testing_packages

关于test_package的一些重要说明

  • test_package 文件夹与单元或集成测试不同。这些测试是“包”测试,用于验证包是否正确创建,以及包使用者是否能够链接到它并重用它。

  • 它本身就是一个小的 Conan 项目,包含自己的conanfile.py 和源代码,包括构建脚本。它依赖于正在创建的包,并构建并执行一个需要包中库的小应用程序。

  • 它不属于该包。它只存在于源代码仓库中,而不存在于包中。

  • test_package 文件夹是默认文件夹,但可以通过命令行参数 --test-folder 或配方属性 test_package_folder 定义不同的文件夹。

我们的 hello/1.0 Conan 包的test_package 文件夹包含以下内容

test_package
 ├── CMakeLists.txt
 ├── conanfile.py
 └── src
     └── example.cpp

让我们看一下test_package 中包含的不同文件。首先,example.cpp 只是一个如何使用我们正在打包的libhello 库的最小示例

test_package/src/example.cpp
#include "hello.h"

int main() {
    hello();
}

然后是CMakeLists.txt 文件,用于告诉 CMake 如何构建示例

test_package/CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(PackageTest CXX)

find_package(hello CONFIG REQUIRED)

add_executable(example src/example.cpp)
target_link_libraries(example hello::hello)

最后,是用于test_package 的配方,它使用hello/1.0 Conan 包

test_package/conanfile.py
import os

from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout
from conan.tools.build import can_run


class helloTestConan(ConanFile):
    settings = "os", "compiler", "build_type", "arch"
    generators = "CMakeDeps", "CMakeToolchain"

    def requirements(self):
        self.requires(self.tested_reference_str)

    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()

    def layout(self):
        cmake_layout(self)

    def test(self):
        if can_run(self):
            cmd = os.path.join(self.cpp.build.bindir, "example")
            self.run(cmd, env="conanrun")

让我们过一下最相关的部分

  • 我们在 requirements() 方法中添加依赖项,但在此情况下,我们使用 Conan 传递给 test_package 的 tested_reference_str 属性。这是一个方便的属性,可以避免在 test_package 中硬编码包名称,以便我们可以为同一 Conan 包的多个版本重用相同的 test_package。在我们的例子中,这个变量将取 hello/1.0 值。

  • 我们定义一个 test() 方法。此方法仅在test_package 配方中调用。它在调用 build() 后立即执行,旨在运行一些可执行文件或测试二进制文件,以证明包已正确创建。关于我们的 test() 方法的内容,有几点说明

    • 我们使用 conan.tools.build.cross_building 工具来检查我们是否可以在当前平台上运行构建的可执行文件。该工具将返回 tools.build.cross_building:can_run 配置的值(如果已设置)。否则,它将返回我们是否正在交叉构建。对于您的架构可以运行多个目标的情况,这是一个有用的功能。例如,Mac M1 机器可以运行 armv8x86_64

    • 我们使用 Conan 放入运行环境中的环境信息,运行在 self.cpp.build.bindir 文件夹中生成的可执行文件示例。然后 Conan 将调用一个启动器,其中包含运行时环境信息,以及运行编译的可执行文件和应用程序所需的任何信息。

现在我们已经过了一遍代码的重要部分,让我们尝试我们的test_package。虽然我们已经了解到,当我们调用 conan create 时会调用test_package,但如果您已经在 Conan 缓存中创建了 hello/1.0 包,也可以只创建test_package。这是使用 conan test 命令完成的

$ conan test test_package hello/1.0

...

-------- test_package: Computing necessary packages --------
Requirements
    fmt/8.1.1#cd132b054cf999f31bd2fd2424053ddc:ff7a496f48fca9a88dc478962881e015f4a5b98f#1d9bb4c015de50bcb4a338c07229b3bc - Cache
    hello/1.0#25e0b5c00ae41ef9fbfbbb1e5ac86e1e:fd7c4113dad406f7d8211b3470c16627b54ff3af#4ff3fd65a1d37b52436bf62ea6eaac04 - Cache
Test requirements
    gtest/1.17.0#d136b3379fdb29bdfe31404b916b29e1:656efb9d626073d4ffa0dda2cc8178bc408b1bee#ee8cbd2bf32d1c89e553bdd9d5606127 - Skip

...

[ 50%] Building CXX object CMakeFiles/example.dir/src/example.cpp.o
[100%] Linking CXX executable example
[100%] Built target example

-------- Testing the package: Running test() --------
hello/1.0 (test package): Running test()
hello/1.0 (test package): RUN: ./example
hello/1.0: Hello World Release! (with color!)

如您在输出中所见,我们的test_package 构建成功,测试hello/1.0 Conan 包可以毫无问题地被使用。