Rez 软件包测试与 CI

定义 Rez 软件包测试,在隔离且已解析依赖项的环境中运行测试,并将明确的测试覆盖纳入 CI。

loonghao
2026年10月8日
0 收藏
73 下载

安装与下载

1 ClawHub CLI

从源直接安装技能的最快方式。

npx clawhub@latest install rez-test-ci

2 手动安装

将技能文件夹复制到以下位置之一

全局模式 ~/.openclaw/skills/
工作区 {'/skills/'}

优先级:工作区 › 全局 › 内置

3 提示词安装

将此提示词复制到 Openclaw 即可自动安装。

请帮我使用 Clawhub 安装 skill-rez-test-ci。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。

更倾向于下载?

获取包含原生技能文件的ZIP压缩包。

下载技能 (.zip)

基本信息

名称 Rez 软件包测试与 CI
Slug rez-test-ci
创建者 loonghao
创建时间 2026-10-08 05:41:50
更新时间 2026-10-08 05:41:50
收藏数 0
使用量 73
浏览量 30

安装指南

  1. ClawHub CLI 从源直接安装技能的最快方式。
    npx clawhub@latest install rez-test-ci
  2. 手动安装 将技能文件夹复制到以下位置之一
    全局模式
    ~/.openclaw/skills/
    工作区
    /skills/
    优先级:工作区 > 本地 > 内置
  3. 提示词安装 将此提示词复制到 OpenClaw 即可自动安装。
    请帮我使用 Clawhub 安装 rez-test-ci。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。
    更倾向于下载?
    获取包含原生技能文件的ZIP压缩包。
    下载技能 (.zip)

什么是

Rez 软件包测试与 CI 技能介绍如何在 package.py 中声明软件包测试,并使用 rez-test 执行测试。每项测试都会根据其 requires 获得独立的已解析环境,因此测试不只是一个命令:它还是一项可复现的环境与执行请求。
使用此技能了解测试选择、run_on 标签、变体、命令参数、标志和退出代码,然后围绕 Rez 3.4.0 构建可靠的 CI 工作流程。Openclaw Skills 帮助开发者避免测试被悄然跳过,方法是列出并明确指定流水线必须运行的测试。

应用场景

将单元测试、lint 或集成测试添加到 Rez 软件包定义中。
诊断为什么直接运行
rez-test
执行的测试少于
rez-test -l 列出的测试。
requires
字段添加测试专用依赖项。
将测试限制为选定的变体,或使用
run_on
标签标记仅用于发布的测试。
配置 CI,在运行测试前构建并安装软件包。
排查测试环境无法解析、缺少软件包、退出代码异常以及参数转发问题。
在依赖 CI 任务之前,使用 --dry-run 安全检查计划选择的测试。

工作原理

在软件包的 tests 字典中声明测试,形式可以是命令字符串、命令列表,或包含 command、requires、run_on 和 on_variants 等字段的字典。
在命令字符串中使用 {root} 引用软件包中的文件,无需依赖固定的安装路径。
构建并安装软件包,使其可通过已配置的 Rez 软件包路径访问;使用 rez-search
验证其可见性。
使用 rez-test -l 检查可用测试。直接运行时会选择带有 default 标签的测试,包括未明确设置 run_on 标签的测试;其他标签不会自动选择。 按名称运行特定测试。Rez 会根据每项测试的依赖项分别解析一个环境,然后在该环境中执行声明的命令。
检查结果摘要和进程退出代码。返回第一个失败测试的退出代码;无法解析环境时返回 -1,成功运行时返回 0。
在 CI 中明确列出必需的测试,避免添加非默认标签后覆盖率在不知情的情况下减少。

配置指南

声明测试
在 package.py 中添加 tests 字典。例如:
tests = {
"unit": "python -m unittest -s {root}/tests",
"integration": {
"command": "python -m pytest {root}/tests",
"requires": ["pytest"],
"run_on": ["pre_release"],
},
}
测试还可以指定 on_variants,以便在每个变体上运行,或只在符合请求的变体上运行。如果测试声明需要根据软件包变体进行调整,tests 属性可以是 @early() 或 @late() 函数。
安装并运行
python -m pip install "rez==3.4.0"
export REZ_PACKAGES_PATH=/path/to/packages
rez-build --install
rez-search toolcheck
rez-test toolcheck -l
rez-test toolcheck unit
rez-test toolcheck integration
对于 CI,请确保 Rez 可通过 PATH 使用,配置可访问的软件包仓库,并在测试前构建和安装软件包。优先明确指定测试名称,而不要依赖默认标签选择。
要将参数转发给一个具名测试,请加入 -- 分隔符:
rez-test toolcheck unit -- --verbose
使用 --dry-run 检查默认运行会选择哪些测试,而不实际执行测试。--inplace 用于活动的 Rez 上下文,不能与 --extra-packages、--paths 或 --no-local 组合使用。
Rez 软件包测试与 CI 数据架构与分类体系
测试声明结构
字段 用途
tests 将每个测试名称映射到命令、命令列表或配置字典的字典。
command 在该测试的环境中执行的 Shell 命令或命令列表。
requires 用于解析测试环境的其他软件包请求。
run_on 控制测试选择的标签或标签列表;省略标签时默认为 default。
on_variants 设置为 True 时在每个变体上运行,或使用请求配置选择匹配的变体。
{root} 在命令字符串中使用的引用,展开后指向软件包根目录,以便可移植地访问软件包文件。
运行时与 CI 输出
测试和软件包定义位于 package.py 中;此技能不定义单独生成的数据格式。
rez-test -l 会列出已声明的测试,包括非默认测试。 测试执行会生成摘要表,其中包含每项测试的状态、变体和描述。
没有测试失败时命令返回 0;失败时返回第一个失败测试的退出代码;测试环境无法解析时返回 -1。
没有测试的软件包会打印消息并以 0 退出;如果缺少测试应导致任务失败,CI 必须明确进行检查。

高级特性

基于标签的测试选择:
run_on
区分默认、预发布或其他测试组;请记住,直接运行只会选择
default
测试。
适配变体的声明:
on_variants
,或使用
@early()
@late()
根据软件包变体调整测试。
隔离测试依赖项:
在每项测试的
requires
中声明仅供测试使用的工具,而不要将它们加入软件包的常规依赖项。
可移植的软件包路径:
{root}
,使测试可以在不同安装位置找到软件包文件。
CI 覆盖率检查: -l 输出与 --dry-run 结果,并在流水线中明确写出必需的测试名称。
执行控制:
根据需要使用 -s --stop-on-fail 、 --extra-packages 、 --paths 、 --no-local 和可重复使用的详细程度标志。
参数转发:

将额外参数传递给一个具名测试;不带分隔符的参数可能会被
rez-test
接收。
感知上下文的就地运行:
仅在活动的
rez-env
内使用 --inplace ;常规的已解析测试环境是推荐的 CI 模式。


name: rez-test-ci description: "Declaring and running tests from a package definition — the tests attribute and its command / requires / run_on / on_variants fields, why a bare rez-test runs only tests tagged default, every rez-test flag, how the exit code is derived, and how to drive package tests from CI. Use when a package needs tests, when rez-test runs fewer tests than you declared, or when you are wiring rez package tests into a pipeline. Covers Rez 3.4.0."

Rez package tests and CI

One-sentence summary: tests live in the tests dict of package.py and run through rez-test, which resolves a separate environment per test from that test's own requires — so a test is a resolve, not just a command.

Skill scope: declaring, running and automating package tests. For the rest of the build/release/test loop and the other commands' flags see rez-cli; for the package.py attributes in general and @early/@late on tests see rez-package-definition; for the mistakes that make a package.py fail to load see rez-package-pitfalls; for driving tests from Python see rez-python-api.

Declaring tests

tests is a dict mapping a test name to either a command, a list of commands, or a dict:

name = "toolcheck"
version = "1.0.0"
tools = ["toolcheck"]

tests = {

# shorthand: a command string

"unit": "python -c "import sys; sys.exit(0)"",

# or a list of commands

"lint": ["python -m compileall -q python"],

# full form

"integration": {
"command": "python -m pytest {root}/tests",
"requires": ["pytest"],
"run_on": ["pre_release"],
"on_variants": {
"type": "requires",
"value": ["python-3"],
},
},
}

Field Meaning

command the command, or a list of them; run inside the test's own environment
requires extra request added to the test environment
run_on a tag or list of tags; a test with no tag is default
on_variants True to run on every variant, or {"type": "requires", "value": [...]} to run only on variants matching a request

tests may be an @early() or @late() function, which is how a package can declare different tests per variant.

Command strings automatically expand references such as {root}, so a test can reach files inside its own package without hard-coding a path:

tests = {
"unit": "python -m unittest -s {root}/tests",
}

The command otherwise runs as an ordinary shell command in the test environment. Use {root} in preference to an absolute path — a test that hard-codes a repository location breaks the moment the package is released somewhere else.

Running tests

rez-test toolcheck # every test tagged 'default'
rez-test toolcheck unit # one named test
rez-test toolcheck -l # list every test, including non-default ones
rez-test toolcheck --dry-run # show what would run, run nothing
rez-test toolcheck -s # stop at the first failure

A bare rez-test runs only default tests

This is the single most common surprise. Without a test name, rez-test selects tests whose run_on tags include default — and a test declares no run_on at all is default. Anything tagged otherwise, such as run_on: ["pre_release"], is skipped.

So given a package with unit, failing and a pre_release-tagged integration:

$ rez-test toolcheck -l
failing
integration
unit

$ rez-test toolcheck 1 succeeded, 1 failed, 0 skipped

integration is listed but never run. To run it, name it:

rez-test toolcheck integration

Output and exit code

Every run ends with a summary table:

Test results:

1 succeeded, 1 failed, 0 skipped

Test Status Variant Description


failing failed /packages/toolcheck/1.0.0 Test failed with exit code 3
unit success /packages/toolcheck/1.0.0 Test succeeded

The exit code is the exit code of the first test that failed, or 0 if none did. A test that could not run at all — its environment would not resolve — yields -1. That is all a CI job needs: a non-zero exit is a failure, and the exit code may be the test's own.

--dry-run reports each test as skipped with the description Dry run mode, and exits 0. Use it to check which tests would run before you trust a CI job's coverage.

Extra arguments after a single named test are passed through to that test's command, which is how you forward flags to the tool a test wraps:

rez-test toolcheck unit -- --verbose

The -- is required. Without it the arguments are consumed and the test command receives nothing at all — silently, with the test still passing. Forwarding a flag to the tool a test wraps therefore always needs the separator, and the flags behind it must not be rez-test flags you also meant to set.

You can only pass extra arguments to one named test; naming two is a parser error.

Flags

Flag Effect

-l, --list list the package's tests and exit --dry-run show what would run without running it -s, --stop-on-fail stop on the first failure --inplace run in the current environment; tests whose requirements are unmet are skipped --extra-packages PKG ... add requests to every test environment --paths PATHS override the package search path --nl, --no-local ignore local_packages_path -v, --verbose verbose, repeatable

--inplace is mutually exclusive with --extra-packages, --paths and --no-local:

rez test: error: Cannot use --inplace in combination with --extra-packages/--paths/--no-local

--inplace also needs an active rez context — outside one it fails on a missing current package, so it belongs inside a rez-env, not in a fresh CI shell.

A package with no tests is not an error. rez-test prints No tests found in to stderr and exits 0. If your CI must fail when a package declares no tests, check with -l and assert on the output yourself.

Wiring into CI

The pattern that works on every CI provider: make the runner rez-aware once, then run rez-test as an ordinary command. Rez only needs to be on PATH and the package repository reachable.

python -m pip install "rez==3.4.0"
export REZ_PACKAGES_PATH=/path/to/packages

rez-test toolcheck unit
rez-test toolcheck integration

Name the tests you want rather than relying on the default tag — an explicit list is self-documenting and cannot silently lose coverage when someone adds a run_on tag later.

A minimal GitHub Actions job:

jobs:
rez-tests:
runs-on: ubuntu-latest
steps:

  • uses: actions/checkout@v4
  • uses: actions/setup-python@v5 with:
python-version: "3.11"
  • name: Install rez run: python -m pip install "rez==3.4.0"
  • name: Build and install the package run: rez-build --install
  • name: Run package tests run: |
    rez-test toolcheck unit
    rez-test toolcheck integration

Build before you test. rez-test reads an installed package from the package path, so a package that has only been edited and not built is invisible to it. Verify visibility first when a CI job cannot find a package:

rez-search toolcheck

Making CI reflect what the package declares

Because a bare rez-test skips non-default tests, a job that runs rez-test
alone will happily report success while running a subset. Prefer enumerating tests, and gate the set in one place so it cannot drift:

rez-test toolcheck -l # what exists
rez-test toolcheck --dry-run # what a bare run would do

Compare the two when a tag is added. The gap between them is exactly the coverage a bare run would silently drop.

Troubleshooting

Symptom Cause

Fewer tests ran than -l lists a bare run only runs default-tagged tests; name them
No tests found in the package declares none, or rez-test is reading a different installed copy than you edited
Test cannot find the package's files the command runs in a fresh environment; paths must resolve there
Cannot use --inplace in combination with ... --inplace excludes --extra-packages / --paths / --no-local --inplace fails outside a context it needs an active rez context; wrap it in rez-env You can only pass extra arguments to a single, specified test extra args are allowed for exactly one named test
A test ignores the arguments I passed it the -- separator is missing, so they were swallowed and the test still passed
Exit code is an odd number like 3 that is the failing test's own exit code, passed through
CI cannot see the package it was not built and installed; check rez-search
A test's dependency is missing add it to the test's own requires, not the package's

Agent workflow

Confirm the package is installed and visible first: rez-search
.

List what exists with rez-test

-l, then check what a bare run would do with --dry-run. Run named tests rather than relying on the default tag, so coverage cannot drift silently.
Read the summary table and the exit code — non-zero is the first failing test's own code.
Tag slow or release-only tests with run_on deliberately, and enumerate them in CI so the tag never removes coverage by accident.
Reach for --inplace only inside an active rez-env; in CI prefer a normal resolved environment.
Rez 包排序器

Agent Billboard