implement-conformance-testing-script
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseImplement Conformance Testing Script
实现Conformance测试脚本
This skill produces a single executable script that runs the conformance tests for a generated build folder, following a consistent, language-agnostic pattern.
The reference implementations are:
- assets/run_conformance_tests_java.sh — Java, install-inline variant.
- assets/run_conformance_tests_python.sh — Python, install-inline variant.
- assets/run_conformance_tests_<lang>.ps1 — Windows PowerShell equivalents.
Read both before writing anything — every script you produce must be a faithful translation of the same pattern into the target language's tooling and the user's shell environment.
本Skill生成一个可执行脚本,用于为生成的构建文件夹运行conformance测试,遵循一致的、与语言无关的模式。
参考实现如下:
- assets/run_conformance_tests_java.sh — Java,内置安装型变体。
- assets/run_conformance_tests_python.sh — Python,内置安装型变体。
- assets/run_conformance_tests_<lang>.ps1 — Windows PowerShell等效版本。
在编写任何内容之前,请先阅读上述所有脚本——你生成的每个脚本都必须将相同的模式忠实地转换为目标语言的工具链以及用户的Shell环境。
How conformance scripts differ from unit-test scripts
Conformance脚本与单元测试脚本的区别
A conformance script is structurally very close to a unit-test script (see the sibling skill ) but with two important differences:
implement-unit-testing-script- Two positional arguments instead of one. A conformance script takes both the build folder (source under test) and a separate conformance tests folder (the tests to execute against that build).
- Tests are loaded from outside the working folder. The build is staged into and the script
.tmp/<lang>_<arg>s into it, but the test command is pointed at the originalcd. Tests are never copied into the staging area.$current_dir/<conformance_tests_folder>
Everything else — toolchain check, build staging, dependency isolation, exit codes — is the same.
Conformance脚本在结构上与单元测试脚本非常相似(请查看姊妹Skill ),但有两个重要区别:
implement-unit-testing-script- 两个位置参数而非一个。Conformance脚本同时接收构建文件夹(被测源码)和一个独立的conformance测试文件夹(用于针对该构建执行的测试)。
- 测试从工作文件夹外部加载。构建被暂存到中,脚本
.tmp/<lang>_<arg>进入该文件夹,但测试命令指向原始的cd。测试永远不会被复制到暂存区域。$current_dir/<conformance_tests_folder>
其他所有内容——工具链检查、构建暂存、依赖隔离、退出码——都是相同的。
Variant decision: install-inline vs. activate-only
变体选择:内置安装型 vs 仅激活型
Before writing anything, decide which variant to emit. Both variants share toolchain check, arg validation, cwd capture, test execution, and exit-code handling — they differ only in the middle (steps 4–7 of the pattern below).
| Look for an existing | Emit |
|---|---|
| Activate-only variant. Verifies the prepared env, activates it, and runs tests. Does not stage the build or install deps — prepare already did. |
| Nothing — no prepare script | Install-inline variant. Stages the build, installs deps, and runs tests in one shot. |
在编写任何内容之前,请确定要生成的变体。两种变体共享工具链检查、参数验证、当前工作目录捕获、测试执行和退出码处理——它们仅在中间步骤(下文模式中的第4-7步)有所不同。
| 查找是否存在已有脚本 | 生成对应变体 |
|---|---|
项目 | 仅激活型变体。验证已准备好的环境,激活它并运行测试。不会暂存构建或安装依赖——prepare脚本已完成这些操作。 |
| 无——不存在prepare脚本 | 内置安装型变体。一次性完成构建暂存、依赖安装和测试运行。 |
Why this split exists
为何要拆分这两种变体
The conformance runner is invoked once per functional spec by the renderer. Each functional spec in a module has its own folder, and after the renderer finishes generating code for a new spec, it runs the conformance tests of every previous spec in the same module to detect regressions. For a module with N functional specs, this script is called on the order of N times per render — not once per render.
conformance_tests/<module>/<spec>/That per-spec invocation pattern is what makes the install step expensive. A naive runner that does / / / on every invocation pays the install cost N times per render. For anything beyond a toy project, that cost dominates wall-clock time.
pip installnpm cimvn install -DskipTestscargo buildThe two variants are a direct response to this:
- Install-inline is correct only when N is small (a few specs) or dependencies are cheap. It is self-contained: stage, install, run, repeat from scratch every invocation.
- Activate-only is the production answer. runs once per render and pays the install cost a single time, populating
prepare_environment_<lang>with the warmed environment. Each of the N conformance invocations then just attaches to that working folder and runs the tests — no install, no compile, just activate-and-go..tmp/<lang>_<arg>/
Why picking the right variant matters: if you emit the install-inline variant alongside an existing prepare script, prepare's work is wiped (by the script's ) or duplicated (by re-running install) on every run — defeating prepare's whole purpose. Conversely, emitting activate-only without a prepare script means the "verify prepared environment" check fails on every run because nothing has populated the working folder. See Anti-Patterns.
rm -rf .tmp/<lang>_$1Conformance运行器由渲染器针对每个功能规范调用一次。模块中的每个功能规范都有自己的文件夹,当渲染器完成新规范的代码生成后,它会运行同一模块中所有先前规范的conformance测试以检测回归问题。对于一个包含N个功能规范的模块,该脚本在每次渲染时会被调用大约N次——而非每次渲染调用一次。
conformance_tests/<module>/<spec>/这种按规范调用的模式使得安装步骤变得昂贵。如果在每次调用时都执行 / / / 的朴素运行器,每次渲染都会付出N次安装成本。对于非玩具项目,这一成本会占据大部分运行时间。
pip installnpm cimvn install -DskipTestscargo build两种变体正是针对这一问题的解决方案:
- 内置安装型仅在N较小(几个规范)或依赖安装成本较低时适用。它是自包含的:暂存、安装、运行,每次调用都从头重复。
- 仅激活型是生产环境的解决方案。在每次渲染时运行一次,只需付出一次安装成本,将预热后的环境填充到
prepare_environment_<lang>中。随后的N次conformance调用只需连接到该工作文件夹并运行测试——无需安装、无需编译,只需激活即可运行。.tmp/<lang>_<arg>/
选择正确变体的重要性:如果在已有prepare脚本的情况下生成内置安装型变体,prepare脚本的工作成果会在每次运行时被脚本的清除(或通过重新运行安装重复执行)——完全违背了prepare脚本的初衷。反之,如果在没有prepare脚本的情况下生成仅激活型变体,“验证已准备环境”检查会在每次运行时失败,因为没有任何内容填充工作文件夹。请查看反模式。
rm -rf .tmp/<lang>_$1Pick the Shell First
先选择Shell
Before writing anything, decide which shell flavor the script must target — it depends on the user's environment, not on the language:
- Bash () — macOS, Linux, WSL, CI runners on Linux. Default unless the user is on native Windows.
.sh - PowerShell () — native Windows / PowerShell-only environments.
.ps1
If you can't tell from the project (no obvious OS hints, no existing scripts), ask the user.
The same pattern applies to both. Only the syntax changes.
在编写任何内容之前,请确定脚本必须针对的Shell类型——这取决于用户的环境,而非编程语言:
- Bash() — macOS、Linux、WSL、Linux环境下的CI运行器。默认选择,除非用户使用原生Windows环境。
.sh - PowerShell() — 原生Windows / 仅PowerShell环境。
.ps1
如果无法从项目中判断(没有明显的操作系统提示,没有现有脚本),请询问用户。
两种Shell适用相同的模式,仅语法有所不同。
The Pattern
模式
Steps 1–3 and step 8 are identical in both variants. Steps 4–7 differ — pick the subsection below that matches the variant you decided on.
第1-3步和第8步在两种变体中完全相同。第4-7步有所不同——请选择与你确定的变体匹配的子章节。
Common steps (both variants)
通用步骤(两种变体)
- Toolchain check. Verify that the required language runtime / build tool (and the required version, if any) is installed. If not, print an error and exit with code .
69 - Argument validation. Require two positional arguments: and
<build_folder>. If either is missing, print usage and exit with code<conformance_tests_folder>.69 - Capture original cwd. Store in a variable (
pwd/current_dir) before changing directories — the test command in step 8 needs it to resolve the conformance tests folder.$PWD
- 工具链检查。验证所需的语言运行时/构建工具(以及任何所需的版本)已安装。如果未安装,打印错误信息并以代码退出。
69 - 参数验证。需要两个位置参数:和
<build_folder>。如果任一参数缺失,打印使用说明并以代码<conformance_tests_folder>退出。69 - 捕获原始工作目录。在更改目录之前,将存储到变量中(
pwd/current_dir)——第8步中的测试命令需要它来解析conformance测试文件夹。$PWD
Steps 4–7 — install-inline variant (no prepare script)
第4-7步——内置安装型变体(无prepare脚本)
- Working directory setup. Define a working folder at . Wipe it (
.tmp/<lang>_<arg1>/rm -rf) and recreate it. This folder — and only this folder — is where every subsequent write must land.Remove-Item -Recurse -Force - Copy the build. Recursively copy everything from (
<build_folder>) into the working folder. Do not copy the conformance tests — they stay where they are. After this step both$1(build folder) and$1(conformance tests folder) are treated as read-only for the rest of the script.$2 - Enter the working directory. /
cdintoSet-Location. If that fails, exit with code.tmp/<lang>_<arg1>. All remaining steps run from inside the working folder; they must never write back to69or$1.$2 - Install dependencies into an isolated environment inside . Set up a per-working-folder dependency location (a Python venv at
.tmp/<lang>_<arg1>, a local./.venv, a project-scoped Maven repo at./node_modules, etc.) and install/resolve all dependencies into it. Never install into the source build folder (./.m2), the conformance tests folder ($1), the user's global cache ($2, system-wide~/.m2,pip,~/.cargo, ...), or anywhere outside~/.npm. If the install command fails, propagate its exit code immediately and do not proceed to step 8. See Dependency isolation (install-inline)..tmp/<lang>_<arg1>
- 工作目录设置。定义工作文件夹为。清除该文件夹(
.tmp/<lang>_<arg1>/rm -rf)并重新创建。此后所有写入操作都必须仅在该文件夹中进行。Remove-Item -Recurse -Force - 复制构建内容。将(
<build_folder>)中的所有内容递归复制到工作文件夹中。不要复制conformance测试——它们保持原位。此步骤完成后,$1(构建文件夹)和$1(conformance测试文件夹)在脚本剩余部分中均被视为只读。$2 - 进入工作目录。使用/
cd进入Set-Location。如果失败,以代码.tmp/<lang>_<arg1>退出。剩余所有步骤均在工作文件夹内运行;绝不能写回69或$1。$2 - 在内的隔离环境中安装依赖。设置每个工作文件夹的依赖位置(Python的venv位于
.tmp/<lang>_<arg1>,本地./.venv,项目范围的Maven仓库位于./node_modules等)并将所有依赖安装/解析到其中。绝不能安装到源码构建文件夹(./.m2)、conformance测试文件夹($1)、用户的全局缓存($2、系统级~/.m2、pip、~/.cargo等)或~/.npm之外的任何位置。如果安装命令失败,立即传播其退出码,不要继续执行第8步。请查看依赖隔离(内置安装型)。.tmp/<lang>_<arg1>
Steps 4–7 — activate-only variant (prepare script exists)
第4-7步——仅激活型变体(存在prepare脚本)
-
Verify the prepared environment. Both:
- Check that the working folder exists.
.tmp/<lang>_<arg1> - Check that the language's isolation location inside it exists (e.g. for Python,
.venv/bin/activatefor Java,.m2/for Node,node_modules/for Go,.gocache/for Rust)..cargo/
If either check fails, print a helpful error () and exit"Error: prepared environment missing — did you run prepare_environment_<lang>.<sh|ps1> first?". Do not silently fall back to creating it inline — that would mask a real misconfiguration and turn this script into the install-inline variant in disguise. After this step both69and$1are treated as read-only for the rest of the script.$2 - Check that the working folder
-
Enter the working directory./
cdintoSet-Location. If that fails, exit.tmp/<lang>_<arg1>. All remaining steps run from inside the working folder; they must never write back to69or$1.$2 -
Activate the prepared dependency environment. Per-language:
- Python: (must succeed; exit
source .venv/bin/activateon failure).69 - Java: set so it can be passed as
MAVEN_LOCAL_REPO="$(pwd)/.m2"to-Dmaven.repo.local="$MAVEN_LOCAL_REPO"in step 8.mvn - Node.js / Go / Rust: nothing to activate explicitly — the test command in step 8 just needs to receive the same isolation flag/env var that prepare used (is found by default; pass
./node_modules/GOMODCACHE).CARGO_HOME
Activation is always relative to the working folder, never toor$1— prepare populated$2, and that is the only place to attach to..tmp/<lang>_<arg1>/... - Python:
-
(There is no step 7 in this variant — install was prepare's job. Skip straight to step 8.)
-
验证已准备环境。需同时检查:
- 工作文件夹是否存在。
.tmp/<lang>_<arg1> - 其中的语言隔离位置是否存在(例如Python的,Java的
.venv/bin/activate,Node的.m2/,Go的node_modules/,Rust的.gocache/)。.cargo/
如果任一检查失败,打印清晰的错误信息()并以"错误:已准备环境缺失——你是否先运行了prepare_environment_<lang>.<sh|ps1>?"退出。不要静默回退到内置创建环境——这会掩盖真实的配置错误,并将此脚本变相转换为内置安装型变体。此步骤完成后,69和$1在脚本剩余部分中均被视为只读。$2 - 工作文件夹
-
进入工作目录。使用/
cd进入Set-Location。如果失败,以.tmp/<lang>_<arg1>退出。剩余所有步骤均在工作文件夹内运行;绝不能写回69或$1。$2 -
激活已准备的依赖环境。针对不同语言:
- Python:(必须成功;失败则以
source .venv/bin/activate退出)。69 - Java:设置,以便在第8步中作为
MAVEN_LOCAL_REPO="$(pwd)/.m2"传递给-Dmaven.repo.local="$MAVEN_LOCAL_REPO"。mvn - Node.js / Go / Rust:无需显式激活——第8步中的测试命令只需接收与prepare脚本相同的隔离标志/环境变量(默认会找到;传递
./node_modules/GOMODCACHE)。CARGO_HOME
激活操作始终相对于工作文件夹,绝不能相对于或$1——prepare脚本已填充$2,这是唯一可连接的位置。.tmp/<lang>_<arg1>/... - Python:
-
(此变体无第7步——安装是prepare脚本的工作。直接跳至第8步。)
Common step 8 (both variants)
通用第8步(两种变体)
-
Run the conformance tests. Invoke the language's standard test command, pointed at(the original cwd from step 3 + the second arg). The script's final exit code is whatever the test command returns — except for the "no tests discovered" case below.
$current_dir/<conformance_tests_folder>The test command is read-only with respect to. It loads test files from there, but any artifacts the runner produces (caches, JUnit XML, coverage reports, compiled test classes, etc.) must land inside$current_dir/$2, not next to the test files. If your chosen runner defaults to writing output beside the tests, pass an explicit output-directory flag pointing inside the working folder (e.g..tmp/<lang>_<arg1>,pytest --basetemp=./.pytest_tmp, Mavenjest --cacheDirectory=./.jest_cacheundertarget/via.tmp).mvn -f "$current_dir/$2/pom.xml" -Dproject.build.directory="$(pwd)/target" test
-
运行conformance测试。调用语言的标准测试命令,指向(第3步中捕获的原始工作目录 + 第二个参数)。脚本的最终退出码即为测试命令的返回码——除了下文的“未发现测试用例”情况。
$current_dir/<conformance_tests_folder>测试命令相对于必须是只读的。它从该位置加载测试文件,但运行器生成的任何工件(缓存、JUnit XML、覆盖率报告、编译后的测试类等)必须存放在$current_dir/$2内,而非测试文件旁边。如果所选运行器默认将输出写入测试文件旁边,请传递显式的输出目录标志,指向工作文件夹内部(例如.tmp/<lang>_<arg1>,pytest --basetemp=./.pytest_tmp,通过jest --cacheDirectory=./.jest_cache将Maven的mvn -f "$current_dir/$2/pom.xml" -Dproject.build.directory="$(pwd)/target" test放在target/下)。.tmp
Read-only inputs — hard rule
只读输入——硬性规则
A conformance script has two read-only inputs: the source build folder () and the conformance tests folder (). Neither one may be written to under any circumstances. The script must never:
$1$2- install dependencies into or
$1(no$2insidepip install/$1, no$2inside them, nonpm installwriting into them, no Cargo build artifacts ending up under them),mvn install - write a virtualenv / /
node_modules/.m2/.gocachedirectory inside.cargoor$1,$2 - run the test command with its set to
cwdor$1(every test command runs from inside$2after the.tmp/<lang>_<arg1>in step 6 / activate-only step 5),cd - create logs, caches, build outputs, JUnit XML, coverage reports, compiled test classes, or temp files inside or
$1.$2
Why each input is read-only:
- (build folder) is shared with the renderer (
$1by default) and downstream tooling. Writing into it corrupts the renderer's view of "what was generated" and breaks subsequent renders. The whole point of staging intoplain_modules/...is so the source folder stays a clean, reproducible artifact of the render..tmp/ - (conformance tests folder) is the user's authored test source — typically checked into version control. Writing into it pollutes the working tree, churns git status, and (with frameworks that auto-discover) can make subsequent runs pick up generated files as if they were tests.
$2
If you find yourself about to issue any command whose is or , or whose target path starts with or , stop. Either move the operation into , or you're doing something the script must not do.
cwd$1$2$1/$2/.tmp/<lang>_<arg1>Conformance脚本有两个只读输入:源码构建文件夹()和conformance测试文件夹()。在任何情况下都不得写入这两个文件夹。脚本绝不能:
$1$2- 将依赖安装到或
$1中(不得在$2/$1内运行$2、pip install、npm install,不得让Cargo构建产物存放在它们下方),mvn install - 在或
$1内创建虚拟环境 /$2/node_modules/.m2/.gocache目录,.cargo - 在或
$1作为当前工作目录的情况下运行测试命令(所有测试命令均在第6步/仅激活型第5步的$2操作后,从cd内部运行),.tmp/<lang>_<arg1> - 在或
$1内创建日志、缓存、构建输出、JUnit XML、覆盖率报告、编译后的测试类或临时文件。$2
为何每个输入都是只读的:
- **(构建文件夹)**与渲染器(默认是
$1)和下游工具共享。写入其中会破坏渲染器对“生成内容”的认知,并影响后续渲染。将内容暂存到plain_modules/...的核心目的就是保持源码文件夹为渲染生成的干净、可复现的产物。.tmp/ - **(conformance测试文件夹)**是用户编写的测试源码——通常已纳入版本控制。写入其中会污染工作树,导致git状态频繁变动,并且(对于自动发现测试的框架)可能使后续运行将生成的文件当作测试用例。
$2
如果你发现自己要执行的命令的当前工作目录是或,或者目标路径以或开头,请停止。要么将操作移至内,要么你正在执行脚本不允许的操作。
$1$2$1/$2/.tmp/<lang>_<arg1>"No tests discovered" detection
“未发现测试用例”检测
The Python reference script grep's the test runner output for and exits if no tests ran. Replicate the equivalent check for the target language wherever that language's test runner silently passes when given an empty test set:
"Ran 0 tests in"1- Python :
unittest"Ran 0 tests in" - Node.js :
jest"No tests found" - Go :
go test/"no test files""no tests to run" - Rust :
cargo test"running 0 tests" - Java : usually fails loudly already; no extra check needed.
mvn test
A silently-passing zero-test run is the most dangerous failure mode of a conformance runner — always guard against it. This applies to both variants.
Python参考脚本会在测试运行器输出中搜索,如果没有测试运行则以退出。对于目标语言,请复制等效的检查逻辑,当该语言的测试运行器在给定空测试集时静默通过的情况:
"Ran 0 tests in"1- Python :
unittest"Ran 0 tests in" - Node.js :
jest"No tests found" - Go :
go test/"no test files""no tests to run" - Rust :
cargo test"running 0 tests" - Java :通常会直接报错;无需额外检查。
mvn test
静默通过的零测试运行是conformance运行器最危险的失败模式——始终要对此进行防范。此规则适用于两种变体。
Conventions
约定
Shared across both shell flavors and both variants:
- Exit codes:
- — unrecoverable invocation error: missing argument, missing toolchain, can't enter working folder, can't create venv (install-inline), or prepared environment missing/broken (activate-only). Matches the reference scripts'
69.UNRECOVERABLE_ERROR_EXIT_CODE - — "no tests discovered" guard tripped (see above).
1 - Any other non-zero code — propagated from the underlying test command.
- Working folder naming: where
.tmp/<lang>_<arg1>is a short identifier for the language (<lang>,java,python,node,go, ...). Use the first argument (the build folder) in the path, never the conformance tests folder. All dependency installs, build outputs, caches, test runner artifacts, and the test invocation itself live inside this folder. Nothing the script does should touchrustafter step 5 (install-inline) / step 4 (activate-only), or$1at any point.$2 - Logging: print short progress lines (,
"Preparing <lang> build subfolder: ...","Activating prepared virtual environment...") so failures are easy to triage. Wrap noisy "preparing" lines in a"Running <lang> conformance tests..."check if matching the Python reference.VERBOSE - Capture before
current_dir. This is the single most common bug in hand-written conformance scripts: forgetting that the conformance tests folder argument is relative to the invocation directory, not the working folder.cd
适用于两种Shell类型以及两种变体:
- 退出码:
- — 不可恢复的调用错误:缺失参数、缺失工具链、无法进入工作文件夹、无法创建venv(内置安装型),或已准备环境缺失/损坏(仅激活型)。与参考脚本的
69一致。UNRECOVERABLE_ERROR_EXIT_CODE - — 触发“未发现测试用例”防护(见上文)。
1 - 任何其他非零码 — 从底层测试命令传播而来。
- 工作文件夹命名:,其中
.tmp/<lang>_<arg1>是语言的短标识符(<lang>、java、python、node、go等)。使用第一个参数(构建文件夹)作为路径的一部分,绝不能使用conformance测试文件夹。所有依赖安装、构建输出、缓存、测试运行器工件和测试调用本身都存放在此文件夹内。脚本执行的任何操作在第5步(内置安装型)/第4步(仅激活型)后都不得触碰rust,或在任何时候触碰$1。$2 - 日志:打印简短的进度行(、
"准备<lang>构建子文件夹:..."、"激活已准备的虚拟环境..."),以便轻松排查故障。如果匹配Python参考脚本,可将嘈杂的“准备”行包装在"运行<lang> conformance测试..."检查中。VERBOSE - 在前捕获
cd。这是手写conformance脚本中最常见的错误:忘记conformance测试文件夹参数是相对于调用目录的,而非工作文件夹。current_dir
Dependency isolation (install-inline)
依赖隔离(内置安装型)
This section applies to install-inline scripts only. For activate-only scripts, the isolation location is set up by prepare; you just need to point the test command at it — see Activating a prepared environment.
The dependency environment must live inside so the test run can't be polluted by — or pollute — the user's global caches. Pick the most idiomatic isolation mechanism for the language:
$WORKING_FOLDER| Language | Isolation mechanism | Install command (run inside | Test command (point at |
|---|---|---|---|
| Python | | | |
| Node.js | local | | |
| Java | project-scoped Maven repo at | | |
| Go | module cache at | | |
| Rust | cargo home at | | |
Notes:
- Every path in the install command and test command is relative to . That's why the script
.tmp/<lang>_<arg1>s into the working folder in step 6 — from that point on,cd,./.venv,./node_modules, etc. all resolve under./.m2, never under.tmp/<lang>_<arg1>or$1.$2 - Always pass the isolation flag/env var to both the install command and the test command. They must agree on where deps live, otherwise the test command will silently fall back to the global cache or (worse) write into /
$1.$2 - Python is the only ecosystem where the venv is mandatory to satisfy "into a virtual environment" literally. The others use language-native equivalents that achieve the same isolation.
- Propagate the install exit code immediately. In Bash: . In PowerShell: check
<install cmd> || exit $?and$LASTEXITCODEif non-zero.exit $LASTEXITCODE - Time the dependency setup with (Bash) /
date +%s.%N(PowerShell) and printGet-Date. If this number is large, that's the signal to add a"Requirements setup completed in X.XX seconds"script (and switch this script to the activate-only variant).prepare_environment_<lang>
本节仅适用于内置安装型脚本。对于仅激活型脚本,隔离位置由prepare脚本设置;你只需将测试命令指向该位置即可——请查看激活已准备环境(仅激活型)。
依赖环境必须存放在**内部**,以确保测试运行不会被用户的全局缓存污染,也不会污染用户的全局缓存。为语言选择最符合惯例的隔离机制:
$WORKING_FOLDER| 语言 | 隔离机制 | 安装命令(在 | 测试命令(指向 |
|---|---|---|---|
| Python | | | |
| Node.js | 本地 | | |
| Java | 项目范围的Maven仓库位于 | | |
| Go | 模块缓存位于 | | |
| Rust | cargo home位于 | | |
注意事项:
- 安装命令和测试命令中的所有路径均相对于。这就是脚本在第6步中
.tmp/<lang>_<arg1>进入工作文件夹的原因——从那时起,cd、./.venv、./node_modules等都解析到./.m2下,绝不会解析到.tmp/<lang>_<arg1>或$1下。$2 - 始终将隔离标志/环境变量传递给安装命令和测试命令。它们必须就依赖的存放位置达成一致,否则测试命令会静默回退到全局缓存或(更糟)写入/
$1。$2 - Python是唯一强制要求使用venv的生态系统,以严格满足“进入虚拟环境”的要求。其他语言使用原生等效机制实现相同的隔离效果。
- 立即传播安装退出码。在Bash中:。在PowerShell中:检查
<install cmd> || exit $?,如果非零则$LASTEXITCODE。exit $LASTEXITCODE - 为依赖设置计时,使用(Bash)/
date +%s.%N(PowerShell)并打印Get-Date。如果此数值较大,则表明需要添加"依赖设置完成,耗时X.XX秒"脚本(并将此脚本切换为仅激活型变体)。prepare_environment_<lang>
Activating a prepared environment (activate-only)
激活已准备环境(仅激活型)
This section applies to activate-only scripts only. The isolation location was created by prepare; conformance just needs to attach to it and pass the right flags to the test command.
| Language | Verify exists in step 4 | Activate in step 6 | Test command in step 8 (point at |
|---|---|---|---|
| Python | | | |
| Node.js | | (nothing) | |
| Java | | | |
| Go | | | |
| Rust | | | |
Notes:
- Verify, don't recreate. If is missing, exit
.venvwith a clear "did you run prepare_environment first?" message — do not silently fall back to creating it inline. That would silently degrade a misconfigured project into the install-inline path and mask the real problem.69 - Match prepare's isolation paths exactly. If prepare puts the venv at and you look for it at
.venv, the verify step will always fail. Readvenvfor the canonical paths.implement-prepare-environment-script - Don't time anything in this variant. The slow phase is prepare; conformance just runs the tests. Adding a duration log here is misleading — it makes the script look like it's doing the install when it isn't.
本节仅适用于仅激活型脚本。隔离位置由prepare脚本创建;conformance脚本只需连接到该位置并向测试命令传递正确的标志即可。
| 语言 | 第4步中需验证存在的路径 | 第6步中的激活操作 | 第8步中的测试命令(指向 |
|---|---|---|---|
| Python | | | |
| Node.js | | (无操作) | |
| Java | | | |
| Go | | | |
| Rust | | | |
注意事项:
- 仅验证,不重新创建。如果缺失,以
.venv退出并显示清晰的“你是否先运行了prepare_environment?”信息——不要静默回退到内置创建环境。这会将配置错误的项目变相降级为内置安装型路径,并掩盖真实问题。69 - 与prepare脚本的隔离路径完全匹配。如果prepare脚本将venv放在,而你在
.venv中查找,验证步骤将始终失败。请阅读venv以获取标准路径。implement-prepare-environment-script - 此变体无需计时。耗时阶段是prepare脚本的工作;conformance脚本仅运行测试。在此处添加时长日志会产生误导——它会让脚本看起来在执行安装操作,但实际上并没有。
Bash specifics
Bash特定事项
- Shebang: .
#!/bin/bash - File naming: , placed in
run_conformance_tests_<lang>.sh(skill reference) orassets/(target project).test_scripts/ - Arguments: = build folder,
$1= conformance tests folder.$2 - Make it executable: the produced script.
chmod +x - failure check: the reference scripts use the
cd+cd ... 2>/dev/nullpattern. Keep it.[ $? -ne 0 ]
- Shebang:。
#!/bin/bash - 文件命名:,放置在
run_conformance_tests_<lang>.sh(Skill参考)或assets/(目标项目)中。test_scripts/ - 参数:= 构建文件夹,
$1= conformance测试文件夹。$2 - 设置可执行权限:为生成的脚本执行。
chmod +x - 失败检查:参考脚本使用
cd+cd ... 2>/dev/null模式。请保持此模式。[ $? -ne 0 ]
PowerShell specifics
PowerShell特定事项
- No shebang. Use a block at the top instead.
param([Parameter(Mandatory=$true)][string]$BuildFolder, [Parameter(Mandatory=$true)][string]$ConformanceTestsFolder) - File naming: .
run_conformance_tests_<lang>.ps1 - Exit codes: use etc. (PowerShell honors them just like Bash).
exit 69 - Toolchain check: prefer and, where a specific version is needed, parse the tool's
Get-Command <tool> -ErrorAction SilentlyContinueoutput.--version - Filesystem: use ,
Test-Path,Remove-Item -Recurse -Force,New-Item -ItemType Directory,Copy-Item -Recurse. Quote paths to handle spaces.Set-Location - Capture original cwd: before any
$currentDir = (Get-Location).Pathcall.Set-Location - No step needed. If execution policy is likely to block the script, mention
chmodto the user — don't bake it into the script.Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
- 无Shebang。在顶部使用块替代。
param([Parameter(Mandatory=$true)][string]$BuildFolder, [Parameter(Mandatory=$true)][string]$ConformanceTestsFolder) - 文件命名:。
run_conformance_tests_<lang>.ps1 - 退出码:使用等(PowerShell与Bash一样会遵守这些退出码)。
exit 69 - 工具链检查:优先使用,当需要特定版本时,解析工具的
Get-Command <tool> -ErrorAction SilentlyContinue输出。--version - 文件系统操作:使用、
Test-Path、Remove-Item -Recurse -Force、New-Item -ItemType Directory、Copy-Item -Recurse。为路径添加引号以处理空格。Set-Location - 捕获原始工作目录:,必须在任何
$currentDir = (Get-Location).Path调用之前执行。Set-Location - 无需步骤。如果执行策略可能阻止脚本运行,请告知用户执行
chmod——不要将此步骤写入脚本。Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
Workflow
工作流程
- Decide the variant. Look in the project for /
prepare_environment_<lang>.sh(check.ps1, then anytest_scripts/key inprepare-environment-script:). If present → emit activate-only. If absent → emit install-inline. See Variant decision.config.yaml - Confirm the target language, shell flavor (Bash or PowerShell), and dependency manifest (,
pom.xml/requirements.txt,pyproject.toml,package.json,go.mod, ...). Ask if any is unclear.Cargo.toml - Read assets/run_conformance_tests_java.sh and assets/run_conformance_tests_python.sh to refresh the exact structure. Both are install-inline references — for activate-only, follow steps 4–7 of the activate-only variant and the Activating a prepared environment table.
- Translate each step into the equivalent commands for the target language and shell. The toolchain check, dependency install/activate, and test invocation are the language-specific parts; the rest is mechanical translation between Bash and PowerShell syntax.
- Pick the right per-language row:
- Install-inline: Dependency isolation (install-inline) table — use the same flag/env var in steps 7 and 8.
- Activate-only: Activating a prepared environment table — use the matching verify, activate, and test-command columns in steps 4, 6, and 8.
- Add the language-appropriate "no tests discovered" guard from No tests discovered detection.
- Save the new script. For Bash, it.
chmod +x - For activate-only scripts only: smoke-test by running . If the conformance script errors with "prepared environment missing" right after a successful prepare, the two scripts disagree on either the working-folder path or the isolation location — fix that before declaring done.
prepare_environment_<lang>.<sh|ps1> <build> && run_conformance_tests_<lang>.<sh|ps1> <build> <tests>
- 确定变体。在项目中查找/
prepare_environment_<lang>.sh(先检查.ps1,再检查test_scripts/中的config.yaml键)。如果存在 → 生成仅激活型。如果不存在 → 生成内置安装型。请查看变体选择。prepare-environment-script: - 确认目标语言、Shell类型(Bash或PowerShell)和依赖清单(、
pom.xml/requirements.txt、pyproject.toml、package.json、go.mod等)。如有任何不清楚的地方,请询问用户。Cargo.toml - 阅读assets/run_conformance_tests_java.sh和assets/run_conformance_tests_python.sh以刷新对精确结构的认知。两者都是内置安装型参考——对于仅激活型,请遵循仅激活型变体的第4-7步和激活已准备环境表格。
- 将每个步骤转换为目标语言以及Shell的等效命令。工具链检查、依赖安装/激活和测试调用是语言特定部分;其余部分是Bash与PowerShell语法之间的机械转换。
- 选择正确的语言对应行:
- 内置安装型:依赖隔离(内置安装型)表格——在第7步和第8步中使用相同的标志/环境变量。
- 仅激活型:激活已准备环境表格——在第4、6、8步中使用匹配的验证、激活和测试命令列。
- 添加未发现测试用例检测中适合该语言的防护逻辑。
- 保存新脚本。对于Bash脚本,执行。
chmod +x - 仅针对仅激活型脚本:通过运行进行冒烟测试。如果在成功运行prepare脚本后,conformance脚本报错“已准备环境缺失”,则两个脚本在工作文件夹路径或隔离位置上存在不一致——在完成前修复此问题。
prepare_environment_<lang>.<sh|ps1> <build> && run_conformance_tests_<lang>.<sh|ps1> <build> <tests>
Anti-Patterns
反模式
- (Hard mistake) Don't install into, build into, or otherwise write to the source build folder () or the conformance tests folder (
$1). Both arguments are read-only input. Every install, cache, build artifact, log, JUnit XML, coverage report, compiled test class, and temp file must land in$2. This includes never running.tmp/<lang>_<arg1>,pip install,npm install, ormvn installwithcargo buildor$1as their$2or target; never letting a venv /cwd/node_modules/.m2/.gocachedirectory appear inside.cargoor$1; and never running the test command from inside either folder. The whole point of staging into$2is so the build folder remains a clean artifact of the render and the conformance tests folder remains a clean tree under the user's version control — writing to either one corrupts those guarantees..tmp/ - Don't emit the install-inline variant when a script already exists. The conformance script's
prepare_environment_<lang>will wipe everything prepare did, and the inline install will redo it from scratch on every run. Always run the Variant decision check first.rm -rf .tmp/<lang>_$1 - Don't emit the activate-only variant when no prepare script exists. The "verify prepared environment" check will fail on every run because nothing has populated the working folder.
- Don't silently fall back from activate-only to install-inline when the prepared environment is missing. Exit with a clear error so the misconfiguration is visible. Silent fallback hides the real bug and produces inconsistent behavior between runs.
69 - Don't copy the conformance tests folder into . Only the build folder is staged (and only in install-inline). The test folder is read in place from
.tmp/.$current_dir/$2 - Don't compute the test path after . Capture
cdfirst; otherwisecurrent_dirwill be resolved relative to the working folder and silently miss the tests.$2 - Don't skip the "no tests discovered" check. A conformance suite that finds zero tests and exits is the worst possible failure mode — it looks like success in CI.
0 - Don't skip the toolchain check, even when "everyone has it installed" — exit code is what the calling system relies on to detect a missing runtime.
69 - Don't reuse the source folder in place (install-inline). Always copy into first; the renderer relies on this isolation.
.tmp/<lang>_<arg1> - Don't change the exit-code contract. Other parts of the system branch on and
69specifically — and these codes must be identical between the Bash and PowerShell variants.1 - Don't write a cross-shell hybrid (e.g. a that detects PowerShell, or vice versa). Ship one script per shell, named with the appropriate extension.
.sh - Don't install dependencies into the user's global location (, system-wide
~/.m2,pip, etc.) in the install-inline variant. Always isolate inside~/.cargoso concurrent runs and other projects can't interfere.$WORKING_FOLDER - Don't run the test command without first verifying the install / activation succeeded. A failed install (or missing prepared env) followed by a "test" run produces misleading errors that look like test failures.
- (严重错误)不要安装到、构建到或写入源码构建文件夹()或conformance测试文件夹(
$1)。这两个参数都是只读输入。所有安装、缓存、构建产物、日志、JUnit XML、覆盖率报告、编译后的测试类和临时文件都必须存放在$2中。这包括绝不能在.tmp/<lang>_<arg1>或$1作为当前工作目录或目标的情况下运行$2、pip install、npm install或mvn install;绝不能让虚拟环境 /cargo build/node_modules/.m2/.gocache目录出现在.cargo或$1内;绝不能在任一文件夹内运行测试命令。将内容暂存到$2的核心目的是保持构建文件夹为渲染生成的干净产物,保持conformance测试文件夹为用户版本控制下的干净树——写入任一文件夹都会破坏这些保证。.tmp/ - 当脚本已存在时,不要生成内置安装型变体。conformance脚本的
prepare_environment_<lang>会清除prepare脚本完成的所有工作,而内置安装会在每次运行时从头重做。请始终先执行变体选择检查。rm -rf .tmp/<lang>_$1 - 当不存在prepare脚本时,不要生成仅激活型变体。“验证已准备环境”检查会在每次运行时失败,因为没有任何内容填充工作文件夹。
- 当已准备环境缺失时,不要从仅激活型静默回退到内置安装型。以退出并显示清晰的错误信息,以便暴露配置错误。静默回退会掩盖真实的bug,并导致运行之间的行为不一致。
69 - 不要将conformance测试文件夹复制到中。仅暂存构建文件夹(且仅在内置安装型中)。测试文件夹从
.tmp/原位读取。$current_dir/$2 - 不要在后计算测试路径。先捕获
cd;否则current_dir会相对于工作文件夹解析,导致静默找不到测试用例。$2 - 不要跳过“未发现测试用例”检查。一个找到零测试用例并以退出的conformance套件是最糟糕的失败模式——在CI中看起来像是成功。
0 - 不要跳过工具链检查,即使“每个人都已安装”——退出码是调用系统检测缺失运行时的依据。
69 - 不要原地复用源码文件夹(内置安装型)。始终先复制到;渲染器依赖此隔离机制。
.tmp/<lang>_<arg1> - 不要更改退出码约定。系统的其他部分会专门针对和
69进行分支处理——这些代码在Bash和PowerShell变体中必须完全相同。1 - 不要编写跨Shell混合脚本(例如检测PowerShell的脚本,反之亦然)。为每个Shell单独提供一个脚本,使用适当的扩展名命名。
.sh - 在内置安装型变体中,不要将依赖安装到用户的全局位置(、系统级
~/.m2、pip等)。始终在~/.cargo内隔离,以便并发运行和其他项目不会相互干扰。$WORKING_FOLDER - 不要在未验证安装/激活成功的情况下运行测试命令。安装失败(或缺失已准备环境)后运行“测试”会产生误导性错误,看起来像是测试失败。