关于 setup-sdk-testing
用于配置和运行 Speakeasy 生成的 SDK 测试,适合验证生成的客户端是否符合 API 规范或实际 API。涵盖自动生成的契约测试、自定义 Arazzo 工作流和集成测试。
主要功能
- 01根据 OpenAPI 规范生成契约测试
- 02使用 Arazzo 定义多步骤测试
- 03通过 Speakeasy CLI 运行测试
- 04配置实时 API 集成测试
- 05在 GitHub Actions 中运行契约测试
适用场景
- 01检查 SDK 请求和响应处理是否符合规范
- 02测试多步骤 API 工作流
- 03针对测试 API 验证 SDK 行为
- 04SDK 重新生成后运行回归测试
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ speakeasy-api/ sdk-generation-skills --skill setup-sdk-testing安装后在 Claude Code 中输入/setup-sdk-testing确认已加载。
附带文件content/arazzo-reference.md
详细介绍
setup-sdk-testing
使用契约测试、自定义 Arazzo 工作流或针对实时 API 的集成测试,为 Speakeasy 生成的 SDK 配置并运行测试。
内容指南
| 主题 | 指南 |
|---|---|
| Arazzo 参考 | content/arazzo-reference.md |
Arazzo 参考提供了工作流、步骤、成功标准、环境变量和链接操作的完整语法。
适用场景
- 为生成的 SDK 配置自动化测试
- 通过
gen.yaml启用契约测试生成 - 使用 Arazzo 编写自定义多步骤 API 工作流测试
- 配置针对实时 API 的集成测试
- 调试
ResponseValidationError或测试失败 - 用户提到:“测试 SDK”“契约测试”“Arazzo 测试”“speakeasy test”“模拟服务器”“测试生成”
输入
| 输入 | 必需 | 说明 |
|---|---|---|
gen.yaml | 是 | 生成配置;在此处启用契约测试 |
| OpenAPI 规范 | 是 | 生成 SDK 所依据的 API 规范 |
| 目标语言 | 是 | typescript、python、go 或 java(支持契约测试) |
.speakeasy/tests.arazzo.yaml | 否 | 自定义 Arazzo 测试定义 |
| 实时 API 凭据 | 否 | 仅集成测试需要 |
输出
| 输出 | 位置 |
|---|---|
| 生成的契约测试 | SDK 输出目录中的 tests/ 目录 |
| 模拟服务器配置 | 与契约测试一起自动生成 |
| Arazzo 测试结果 | speakeasy test 的终端输出 |
| CI 工作流 | .github/workflows/(如果配置了集成测试) |
前提条件
- 已安装并完成身份验证的 Speakeasy CLI(
speakeasy auth login) - 可正常运行的 SDK 生成配置(
gen.yaml+ OpenAPI 规范) - 对于集成测试:将 API 凭据设为环境变量
决策框架
根据需求选择合适的测试方法:
| 需求 | 方法 | 工作量 |
|---|---|---|
| 验证 SDK 类型和方法是否符合 API 契约 | 契约测试 | 低(自动生成) |
| 测试多步骤 API 工作流(创建后再验证) | 自定义 Arazzo 测试 | 中 |
| 使用真实数据针对实时 API 进行验证 | 集成测试 | 高 |
| 在每次重新生成 SDK 时捕获回归问题 | 契约测试 + CI | 低 |
| 端到端测试身份验证流程 | 集成测试 | 高 |
| 验证具有数据依赖关系的链式操作 | 自定义 Arazzo 测试 | 中 |
从契约测试开始。 它会自动生成,并能捕获最常见的问题。添加自定义 Arazzo 测试以覆盖工作流;只有在需要验证实时 API 时才添加集成测试。
命令
启用契约测试
添加到 gen.yaml:
generation:
tests:
generateTests: true
然后重新生成 SDK:
speakeasy run --output console
运行测试
# Run all Arazzo-defined tests (contract + custom)
speakeasy test
# Run tests for a specific target
speakeasy test --target my-typescript-sdk
# Run with verbose output for debugging
speakeasy test --verbose
通过 CI 运行
启用测试生成后,契约测试会在 Speakeasy GitHub Actions 工作流中自动运行。契约测试无需额外配置 CI。
示例
1. 契约测试(快速开始)
在 gen.yaml 中启用测试生成:
generation:
tests:
generateTests: true
重新生成 SDK:
speakeasy run --output console
运行生成的测试:
speakeasy test
CLI 会根据 OpenAPI 规范生成测试,创建一个返回符合规范响应的模拟服务器,并验证 SDK 是否能正确处理请求和响应。
2. 自定义 Arazzo 测试
创建或编辑 .speakeasy/tests.arazzo.yaml:
arazzo: 1.0.0
info:
title: Custom SDK Tests
version: 1.0.0
sourceDescriptions:
- name: my-api
type: openapi
url: ./openapi.yaml
workflows:
- workflowId: create-and-verify-resource
steps:
- stepId: create-resource
operationId: createResource
requestBody:
payload:
name: "test-resource"
type: "example"
successCriteria:
- condition: $statusCode == 201
outputs:
resourceId: $response.body#/id
- stepId: get-resource
operationId: getResource
parameters:
- name: id
in: path
value: $steps.create-resource.outputs.resourceId
successCriteria:
- condition: $statusCode == 200
- condition: $response.body#/name == "test-resource"
- workflowId: list-and-filter
steps:
- stepId: list-resources
operationId: listResources
parameters:
- name: limit
in: query
value: 10
successCriteria:
- condition: $statusCode == 200
运行自定义测试:
speakeasy test
在 Arazzo 测试中使用环境变量
通过环境变量引用敏感值:
steps:
- stepId: authenticated-request
operationId: getProtectedResource
parameters:
- name: Authorization
in: header
value: Bearer $env.API_TOKEN
successCriteria:
- condition: $statusCode == 200
禁用特定测试
使用 overlay 禁用某个生成的测试,而不删除它:
overlay: 1.0.0
info:
title: Disable flaky test
actions:
- target: $["workflows"][?(@.workflowId=="flaky-test")]
update:
x-speakeasy-test:
disabled: true
3. 集成测试
对于实时 API 测试,请使用 SDK 工厂模式:
TypeScript 示例:
import { SDK } from "./src";
function createTestClient(): SDK {
return new SDK({
apiKey: process.env.TEST_API_KEY,
serverURL: process.env.TEST_API_URL ?? "https://api.example.com",
});
}
describe("Integration Tests", () => {
const client = createTestClient();
it("should list resources", async () => {
const result = await client.resources.list({ limit: 5 });
expect(result.statusCode).toBe(200);
expect(result.data).toBeDefined();
});
it("should create and delete resource", async () => {
// Create
const created = await client.resources.create({ name: "integration-test" });
expect(created.statusCode).toBe(201);
// Cleanup
const deleted = await client.resources.delete({ id: created.data.id });
expect(deleted.statusCode).toBe(204);
});
});
Python 示例:
import os
import pytest
from my_sdk import SDK
@pytest.fixture
def client():
return SDK(
api_key=os.environ["TEST_API_KEY"],
server_url=os.environ.get("TEST_API_URL", "https://api.example.com"),
)
def test_list_resources(client):
result = client.resources.list(limit=5)
assert result.status_code == 200
assert result.data is not None
@pytest.mark.cleanup
def test_create_and_delete(client):
created = client.resources.create(name="integration-test")
assert created.status_code == 201
try:
fetched = client.resources.get(id=created.data.id)
assert fetched.data.name == "integration-test"
finally:
client.resources.delete(id=created.data.id)
用于集成测试的 GitHub Actions CI:
name: Integration Tests
on:
schedule:
- cron: "0 6 * * 1-5"
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: speakeasy-api/sdk-generation-action@v15
with:
speakeasy_version: latest
- run: speakeasy test
env:
SPEAKEASY_API_KEY: ${{ secrets.SPEAKEASY_API_KEY }}
- name: Run integration tests
run: npm test -- --grep "integration"
env:
TEST_API_KEY: ${{ secrets.TEST_API_KEY }}
TEST_API_URL: ${{ secrets.TEST_API_URL }}
不要做的事
- 不要跳过契约测试,直接进行集成测试——契约测试无需额外成本,而且能发现大多数问题
- 不要在 Arazzo 测试文件中硬编码 API 密钥或机密信息——请使用
$env.VARIABLE_NAME语法 - 不要直接修改自动生成的测试文件——重新生成时这些文件会被覆盖;请改用自定义 Arazzo 测试
- 不要在未调查原因前禁用失败的契约测试——
ResponseValidationError通常意味着规范与 API 不一致 - 不要在生产环境中运行包含破坏性操作的集成测试——务必使用测试/预发布环境
- 不要假设所有语言都支持契约测试——目前支持的语言有:TypeScript、Python、Go、Java
故障排除
契约测试中的 ResponseValidationError
SDK 响应与 OpenAPI 规范不匹配。常见原因:
- 规范已过时:根据最新的 API 规范重新生成
- 缺少必填字段:检查规范中的
required数组是否与实际 API 响应一致 - 类型不匹配:检查架构定义中的
type和format字段
# Regenerate with latest spec and re-run tests
speakeasy run --output console && speakeasy test --verbose
测试在本地通过,但在 CI 中失败
- 检查是否已在 CI 密钥中设置所有环境变量
- 确认 CI 运行器可以通过网络访问模拟服务端口
- 确保本地与 CI 中的 Speakeasy CLI 版本一致
找不到 speakeasy test 命令
更新 Speakeasy CLI:
speakeasy update
模拟服务无法启动
- 检查默认模拟服务端口是否存在冲突
- 确保 OpenAPI 规范有效:
speakeasy lint openapi -s spec.yaml - 确认
generateTests: true已在gen.yaml中设置,且 SDK 已重新生成
自定义 Arazzo 测试未运行
- 确认文件位于
.speakeasy/tests.arazzo.yaml - 检查
operationId值是否与 OpenAPI 规范中的值完全一致 - 验证 YAML 语法——缩进错误是最常见的原因
集成测试间歇性失败
- 为依赖网络的测试添加重试逻辑
- 使用包含时间戳的唯一资源名称,避免冲突
- 确保测试失败时也会执行清理(使用
finally或afterEach)