Chainlink CRE 冒烟测试实战指南:本地环境搭建、套件分桶与 CI 维护
2026/9/16 17:10:22 网站建设 项目流程

Chainlink CRE 冒烟测试实战指南:本地环境搭建、套件分桶与 CI 维护

【免费下载链接】chainlinknode of the decentralized oracle network, bridging on and off-chain computation项目地址: https://gitcode.com/GitHub_Trending/ch/chainlink

CRE(Chainlink Runtime Environment)是 Chainlink 节点核心代码库(当前仓库)中承载链下计算、工作流编排与跨链能力的一套运行时体系。本指南围绕仓库中system-tests/tests/smoke/cre的 CRE 冒烟测试套件展开,说明如何基于 Local CRE 环境运行这些测试、理解其环境引导机制、掌握分桶(bucket)选择与并行执行规则,并在 CI 中正确维护和扩展套件。读完本文,你将能够复现官方推荐的本地测试流程、按拓扑与场景精确挑选测试入口,并遵循仓库约定新增一条可被 CI 自动发现的冒烟测试。

CRE 冒烟测试的定位:包级规则与适用边界

system-tests/tests/smoke/cre/README.md首先给出了一条贯穿整套测试的“经验法则”(Rule of Thumb):

Happy-path(正常路径)与 sanity checks(健全性检查)属于smoke;边缘场景与负向条件属于regression

这条规则的完整展开见 docs/local-cre/system-tests/index.md:smoke 测试覆盖正常路径与健全性检查行为,而边界情况、负向条件应放在system-tests/tests/regression/cre包中。该边界也在 cre_suite_test.go 的包注释中被代码化:

//////////// SMOKE TESTS ///////////// // target happy path and sanity checks // all other tests (e.g. edge cases, negative conditions) // should go to a `regression` package /////////////////////////////////////

从源码结构看,冒烟测试目录 system-tests/tests/smoke/cre 下按链族与能力维度组织了大量场景:EVM 读写、Solana 读写与日志触发、Aptos、Stellar、Vault、HTTP Action、分片(sharding)等,每个子目录通常带独立go.modmain.go,形成可独立编译运行的分包。这与"套件可发现、可复用、可跨拓扑运行"的设计目标一致。

快速开始:五分钟拉起本地冒烟套件

仓库 README 给出了最小化的快速启动流程,这也是本地验证 CRE 冒烟套件的最短路径:

cd core/scripts/cre/environment go run . env setup go run . env start --with-chip-ingress-stack go test ./system-tests/tests/smoke/cre -timeout 20m -run '^Test_CRE_'

命令拆解如下:

  1. go run . env setup:初始化 Local CRE 环境(下载依赖镜像、生成配置文件等准备步骤);
  2. go run . env start:启动本地 CRE 环境。--with-chip-ingress-stack会额外拉起 Chip Ingress 观测栈(--with-beholder为已废弃的等价旧参数);
  3. go test:以^Test_CRE_前缀正则选中全部 CRE 冒烟测试,并给出20m的整体超时预算。

关于--with-chip-ingress-stack的端口冲突警告

docs/local-cre/system-tests/running-tests.md 特别强调:默认冒烟流程不要开启--with-chip-ingress-stack。原因在于,多数 CRE 冒烟测试会在默认 gRPC 端口50051上启动 ChIP 测试接收端(test sink),而 Chip Ingress 栈同样占用该端口;两者同时使用默认端口时,测试接收端会启动失败。--with-beholder已废弃,其行为与--with-chip-ingress-stack相同。

仅在以下情况才需要开启 Chip Ingress 栈:

  • 你正在运行与 Chip Ingress 栈强相关的专项覆盖(如CronChipIngressStack场景);
  • 调试时需要借助该栈观测;
  • 你通过--grpc-port将 Chip Ingress 改到别的端口,把默认50051留给测试接收端。

因此,官方推荐的常规本地流程是(见 running-tests.md):

cd core/scripts/cre/environment go run . env setup go run . env start go test ./system-tests/tests/smoke/cre -timeout 20m -run '^Test_CRE_'

cre_suite_test.go 的头部注释也记录了同样的执行路径:先在core/scripts/cre/environment下执行go run . env restart --with-chip-ingress-stack(标注 deprecated),再在冒烟包内执行go test -timeout 15m -run "^Test_CRE_"

测试如何自动引导本地 CRE:CTF_CONFIGS 的切换机制

使用这套套件时,你可以手动先启动 Local CRE 再跑测试,也可以让测试助手替你引导环境。其底层实现位于 system-tests/tests/test-helpers/before_suite.go,核心机制分三步(与 index.md 的描述一一对应):

  1. CTF_CONFIGS为空,助手将其设置为请求的拓扑配置setConfigurationIfMissingCTF_CONFIGS为空时写入EnvironmentConfigPath,并设置默认私钥(before_suite.go#L333-L342);
  2. 若 Local CRE 状态文件不存在,助手自动执行go run . env startcreateEnvironmentIfNotExists检查状态文件,缺失时拼装env start命令并执行(before_suite.go#L344-L360);
  3. 环境创建完成后,CTF_CONFIGS被切换为本地 CRE 状态文件,使测试消费已部署的环境而非原始拓扑 TOML(before_suite.go#L320-L331)。
func createEnvironment(t *testing.T, testConfig *ttypes.TestConfig, flags ...string) { // 1. 未设置 CTF_CONFIGS 时写入拓扑配置路径 setConfigurationIfMissing(testConfig.EnvironmentConfigPath) // 2. 状态文件不存在则自动 env start createEnvironmentIfNotExists(...) // 3. 切换 CTF_CONFIGS 到 Local CRE 状态文件 os.Setenv("CTF_CONFIGS", envconfig.MustLocalCREStateFileAbsPath(...)) }

这就是"手动启动"与"助手自举"两种方式都能跑通的原因。此外,共享环境通过sync.Once保证每个(配置路径 + flags)组合只创建一次环境,同一拓扑下的多个测试复用同一套已部署合约与节点(before_suite.go#L116-L152),这正是下文"架构模式"中"每拓扑创建一次环境"的实现基础。

本地运行细节:超时、调试与 VS Code 配置

超时预算

运行时长与镜像来源强相关(running-tests.md):

  • 镜像从源码构建时,预留约20 分钟
  • 使用预构建镜像时,运行时间显著缩短。

调试单个分桶

缩小范围、保留完整拓扑与工作流设置的单测调试模式:

CTF_LOG_LEVEL=debug \ go test ./system-tests/tests/smoke/cre -timeout 20m -run '^Test_CRE_V2_Suite_Bucket_A$'

CTF_LOG_LEVEL=debug会输出更详细的框架日志,便于定位环境搭建阶段的失败。

VS Code 调试启动配置

文档同时给出了可直接使用的 VS Code launch 配置(mode: test):

{ "name": "Launch CRE V2 Bucket A", "type": "go", "request": "launch", "mode": "test", "program": "${workspaceFolder}/system-tests/tests/smoke/cre", "args": ["-test.run", "^Test_CRE_V2_Suite_Bucket_A$"] }

环境变量速查表

冒烟套件主要依赖以下环境变量(来源:running-tests.md 及对应源码):

环境变量作用源码依据
CTF_CONFIGS启动前指向拓扑 TOML;启动后指向生成的 Local CRE 状态文件,本地运行由助手自动切换before_suite.go
TOPOLOGY_NAME用于测试名、bucket 标签与日志输出,使结果与所测拓扑绑定cre_suite_test.go
CTF_LOG_LEVEL=debug输出更详细的框架日志
CTF_JD_IMAGE固定 Job Distributor 镜像,避免默认本地镜像选择running-tests.md
CTF_CHAINLINK_IMAGE固定 Chainlink 节点镜像dons.go

其中CTF_CHAINLINK_IMAGE的消费点可以精确定位:system-tests/lib/cre/environment/dons.go 中的ensureGithubTokenForPrivatePlugins会先检查该变量——若通过环境变量提供了镜像,则无需本地 Docker 构建;否则当节点规格Image为空(需要构建)时,会要求GITHUB_TOKEN存在,缺失时尝试通过gh auth token获取,以便从私有仓库安装插件。

并行执行:默认关闭、按场景放行

并行执行是显式开启的(running-tests.md):

CRE_TEST_PARALLEL_ENABLED=1

但该开关只是"允许并行",并不会盲目并行化所有用例。在 cre_suite_test.go 中,每个场景独立判断是否调用t.Parallel()

  • 部分场景(如 ProofOfReserve、HTTP Trigger Action、Consensus 等)在parallelEnabled为真时立即并行;
  • 部分场景保持串行,因为它们依赖不可共享的基础设施(例如 cre_suite_test.go 中共享同一分片配置的 Sharding 系列测试,显式标注了//nolint:paralleltest)。

这与 docs/local-cre/system-tests/ci-and-suite-maintenance.md 中"该标志只授权并行,每个测试仍需自行判断是否安全调用t.Parallel()"的说明一致。

拓扑选择:默认拓扑与显式覆盖

默认本地流程使用的拓扑为:

core/scripts/cre/environment/configs/workflow-gateway-capabilities-don.toml

对应源码中的默认配置:GetDefaultTestConfig即指向该文件(before_suite.go#L291-L295)。仅在你有意覆盖时(分片、纯网关、特定链族等覆盖)才需要改写CTF_CONFIGS。仓库 configs 目录 中已内置多套可选拓扑:

  • workflow-gateway-don.tomlworkflow-gateway-don-aptos.tomlworkflow-gateway-don-stellar.toml:不同链族/网关布局;
  • workflow-gateway-sharded-don.tomlworkflow-gateway-sharded-manual.tomlworkflow-gateway-sharded-ringocr-overrides.toml:分片及手动分配、OCR 覆盖;
  • workflow-gateway-capabilities-multi-gateway-don.toml:多网关路由;
  • workflow-gateway-capabilities-don-vault-stall-purge.toml...-vault-workflow-don-binding-enabled.toml:Vault 相关专项拓扑。

分桶测试选择:从超大入口到运行时均衡

较大的 CRE 冒烟套件被拆分为按运行时均衡的多个 bucket,而不是一个超大的测试入口(running-tests.md)。旧版 V2 套件分为三个入口:

  • Test_CRE_V2_Suite_Bucket_A
  • Test_CRE_V2_Suite_Bucket_B
  • Test_CRE_V2_Suite_Bucket_C

其场景分配定义在 system-tests/tests/smoke/cre/config/bucketing.go:

  • suite-bucket-aProofOfReserveHTTPTriggerActionDONTimeConsensus
  • suite-bucket-bVaultDON
  • suite-bucket-cCronChipIngressStackHTTPActionCRUDHTTPActionMultiGateway(后者除非TOPOLOGY_NAME包含multi-gateway否则跳过)

分桶注册表还带有完整性校验:ValidateSuiteBucketRegistry会检查每个场景是否恰好被分配到一个 bucket、是否存在重复分配或未分配场景(bucketing.go#L100-L126)。runSuiteBucket在启动时即调用该校验(cre_suite_test.go#L48-L55),防止分桶配置漂移。注释中还给出了再平衡的建议:在 CI 跑一次,依据各用例执行时间重新分配,保持 bucket 运行时均衡。

多网关 HTTP Action 路由

使用多网关拓扑并运行对应测试:

TOPOLOGY_NAME=workflow-gateway-capabilities-multi-gateway \ go test ./system-tests/tests/smoke/cre -timeout 20m -run '^Test_CRE_V2_HTTP_Action_Multi_Gateway$'

注意TOPOLOGY_NAME需包含multi-gateway,否则该场景会直接跳过(cre_suite_test.go#L154-L164)。

EVM 读套件

EVM 读场景使用独立的 bucket 注册表,位于 system-tests/tests/smoke/cre/evm/evmread/config/bucketing.go,入口为:

  • Test_CRE_V2_EVM_Read_HeavyCalls
  • Test_CRE_V2_EVM_Read_StateQueries
  • Test_CRE_V2_EVM_Read_TxArtifacts

何时使用分桶入口

  • 本地反馈循环更短;
  • CI 运行时长更稳定;
  • 套件增长时能以可控方式再平衡各场景的运行时。

测试中的工作流:优先使用共享助手

冒烟测试通常不应自行实现工作流编译、产物拷贝与注册逻辑,而应复用共享助手(docs/local-cre/system-tests/workflows-in-tests.md):

t_helpers.CompileAndDeployWorkflow(...)

该助手负责:

  • 默认将工作流产物拷贝到工作流 DON;
  • 按需支持额外的产物拷贝目标(WithArtifactCopyDONTypes(...));
  • 创建工作流产物;
  • 从已部署环境解析工作流注册表;
  • 以当前注册表版本注册工作流。

工作流编译规则(源码级)

共享编译器位于 system-tests/lib/cre/workflow/compile.go,其执行规则与文档描述一致:

  • 工作流名称必须不少于 10 个字符(compile.go#L37-L39);
  • Go 工作流:构建前先执行go mod tidy(compile.go#L115-L119),并以CGO_ENABLED=0GOOS=wasip1GOARCH=wasm交叉编译为 WASM(compile.go#L121-L127);
  • TypeScript 工作流:通过bun cre-compile编译(compile.go#L95-L110);
  • 语言由文件扩展名自动识别:.ts/.tsx走 TS,.go走 Go(compile.go#L83-L93);
  • 最终产物为 Brotli 压缩 + base64 编码,输出为.br.b64文件(compile.go#L137-L174)。

配置、密钥与 YAML 工作流

工作流配置文件是可选的、与具体被测工作流相关。共享工作流包提供密钥支持,会为注册准备针对当前 DON 与能力注册表的加密密钥。该领域还涵盖工作流密钥处理、YAML/DSL 工作流、直接的 JD(Job Distributor)任务提案流程——这些模式只留给确实需要底层控制的测试,标准冒烟路径仍应优先使用CompileAndDeployWorkflow

环境助手二选一:Per-Test Keys 还是共享 Root Signer

编写测试时,比工作流编译更重要的选择是使用哪个环境助手(workflows-in-tests.md)。

场景一:SetupTestEnvironmentWithPerTestKeys(...)(工作流平面,可并行)

适用于可能并行执行、或执行独立链上写入的工作流平面测试。该路径(实现见 before_suite.go#L177-L248):

  • 为测试生成全新的已注资密钥对(注资额为perTestEVMFundingAmountWei = 1 ETH);
  • 将 EVM 客户端与部署者密钥切换为该测试专属签名者(通过 seth 新建 per-test 客户端、替换 CLDF deployer key);
  • 需要时在 v2 工作流注册表上授权该签名者(authorizePerTestWorkflowSignerIfNeeded调用UpdateAllowedSigners,且对根签名者 nonce 加锁保护);
  • 从而避免并行测试之间的 nonce 冲突与共享密钥耦合。

场景二:SetupTestEnvironmentWithConfig(...)(控制平面,共享根签名者)

适用于管理员/控制平面或所有权敏感测试,必须使用共享 root signer。这是以下流程的更安全选择:

  • V1 注册表测试;
  • 分片与所有权管理操作(如ShardConfig的 ownership-admin);
  • 有意以环境所有者身份执行的测试。

经验法则:v2 工作流执行测试默认用SetupTestEnvironmentWithPerTestKeys;仅当测试需要共享所有者权限、或有意避开 per-test 签名者隔离时才用SetupTestEnvironmentWithConfig。二者的差异同样体现在 before_suite.go 的注释与setupTestEnvironmentWithConfigMode实现中。

价格数据源:TrueUSD 与 Fake 的实现差异

Proof-of-Reserve 相关测试使用共享的PriceProvider抽象,包含两种实现(workflows-in-tests.md):

  • TrueUSDPriceProvider:使用真实 TrueUSD 储备端点,主要校验价格是否变为非零;
  • FakePriceProvider:启动一次共享的 fake HTTP 服务,为每条 feed 生成有界序列的测试价格,强制校验 auth 头,并同时追踪期望价格与实际价格以便严格断言。

Fake 实现的源码位于 system-tests/tests/smoke/cre/por_price_provider.go:通过sync.Once保证 fake 数据提供者只启动一次(避免端口冲突),响应体模拟 TrueUSD 的accountName/totalTrust/ripcord/updatedAt字段,并通过Authorization头校验请求合法性(未授权返回 401)。

使用建议:本地与可重复的冒烟覆盖用 fake provider;仅当场景有意验证与真实数据的集成路径时,才使用 live provider。

CI 与套件维护:自动发现与拓扑矩阵

自动发现机制

ci-and-suite-maintenance.md 描述的高层 CI 流程为:

  • CI 自动发现system-tests/tests/smoke/cre下的测试;
  • 构建"拓扑 × 测试入口"矩阵;
  • 每个测试以适配该拓扑的配置运行。

这意味着新增 CRE 冒烟测试无需手工登记到专属列表

命名与放置约定

  • 测试放在system-tests/tests/smoke/cre包中;
  • 函数名以Test_CRE_前缀开头;
  • 遵循现有包内的 setup 与助手使用模式。

架构模式:每拓扑建一次环境

套件采用"分离"模式(ci-and-suite-maintenance.md):

  • 每个拓扑只创建一次环境;
  • 多个测试复用该环境;
  • 已部署合约与节点在拓扑运行内共享。

这比每个测试都重建 Local CRE 更便宜、更快——其实现即上文提到的sync.Once共享环境缓存(before_suite.go#L116-L152)。

CI 中的受支持拓扑与逐测试覆盖

默认情况下,CRE 工作流对workflow-gateway-capabilities拓扑运行测试。部分测试必须用显式的逐测试覆盖替换默认拓扑集合,当前示例(在.github/workflows/cre-system-tests.yaml中配置):

  • Test_CRE_Aptos_Suiteworkflow-gateway-aptos
  • Test_CRE_Solana_Suiteworkflow
  • Test_CRE_Shardingworkflow-gateway-sharded

关键约束:若新测试只适用于非默认拓扑,仅添加测试代码是不够的,还必须在工作流矩阵中显式添加覆盖,让 CI 以匹配的topologyconfigs组合运行它。尽量保持测试拓扑无关;仅当工作流确实依赖不同链族或拓扑布局时才使用逐测试拓扑覆盖。

新增一条冒烟测试的七步流程

按照 ci-and-suite-maintenance.md 的清单:

  1. 将测试放入 smoke 包;
  2. 遵循现有命名约定(Test_CRE_前缀);
  3. 优先使用共享助手(CompileAndDeployWorkflow、环境助手等);
  4. 决定它属于现有 bucket 还是需要新入口;
  5. 若需要非默认拓扑,添加显式的工作流矩阵覆盖;
  6. 验证其在预期的拓扑矩阵下正常工作;
  7. 保持外部依赖显式化。

故障排查清单

测试逻辑启动前失败(running-tests.md)

  1. 确认CTF_CONFIGS值正确;
  2. 确认 Local CRE 状态文件有效;
  3. 确认所需镜像存在;
  4. 重跑go run . env setup
  5. 开启 debug 日志重跑(CTF_LOG_LEVEL=debug)。

CI 未发现测试(ci-and-suite-maintenance.md)

  1. 确认函数名以Test_开头;
  2. 确认文件位于 smoke 包内;
  3. 确认包可编译;
  4. 确认测试不依赖 CI 中不存在的本地专属假设。

推荐的本地工作流

综合 index.md 的建议,日常本地验证按以下顺序进行:

  1. 拉起 Local CRE(go run . env setup+go run . env start);
  2. 确认目标拓扑(默认workflow-gateway-capabilities-don.toml,特殊场景按需覆盖);
  3. 运行相关冒烟测试(全量^Test_CRE_,或精确到分桶/单场景);
  4. 仅在场景确实需要额外信号时,才使用 Chip Ingress 栈或观测能力(并避开默认50051端口冲突)。

以上内容均基于当前仓库内文档与源码验证:文档骨架来自 system-tests/tests/smoke/cre/README.md 及其链接的 docs/local-cre 长文档,实现细节对照了 cre_suite_test.go、bucketing.go、before_suite.go、compile.go 与 dons.go 等源码文件,读者可沿这些路径继续深入探索。

【免费下载链接】chainlinknode of the decentralized oracle network, bridging on and off-chain computation项目地址: https://gitcode.com/GitHub_Trending/ch/chainlink

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询