studio-design/gesso

GitHub: studio-design/gesso

面向 PHP 的框架无关 OpenAPI 契约测试库,提供细粒度端点覆盖率追踪、请求响应验证、漂移检测与多框架适配。

Stars: 5 | Forks: 0

Gesso logo

# Gesso **/ˈdʒɛs.so/** —— 发音为 “JESS-so” Gesso 是在画布上绘画前涂抹的底料——一层稳定、易于附着的基础,完成的作品在此之上构建。Gesso 将同样的理念引入到 API 中,为 PHP 中的 OpenAPI 契约测试提供可靠的基础。 [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/studio-design/gesso/actions/workflows/ci.yml) [![最新版本](https://poser.pugx.org/studio-design/gesso/v)](https://packagist.org/packages/studio-design/gesso) [![总下载量](https://poser.pugx.org/studio-design/gesso/downloads)](https://packagist.org/packages/studio-design/gesso) [![PHP 版本要求](https://poser.pugx.org/studio-design/gesso/require/php)](https://packagist.org/packages/studio-design/gesso) [![许可证](https://poser.pugx.org/studio-design/gesso/license)](https://packagist.org/packages/studio-design/gesso) Gesso 为 PHPUnit 提供了与框架无关的 OpenAPI 3.0/3.1/3.2 契约测试,**支持 endpoint 覆盖率追踪**。 在测试期间,根据你的 OpenAPI 规范验证 API 响应,并获取显示已测试 endpoint 的覆盖率报告。 Gesso 2 以 `studio-design/gesso` 发布,并在 `Studio\Gesso\` 下声明其公共 PHP API。从 `studio-design/openapi-contract-testing` v1.10 升级时,请遵循[分阶段 v2 迁移指南](docs/migration/v2.md)。 **[搜索文档](https://studio-design.github.io/gesso/)** · [核心快速入门](https://studio-design.github.io/gesso/quickstarts/core) · [Laravel](https://studio-design.github.io/gesso/quickstarts/laravel) · [Symfony](https://studio-design.github.io/gesso/quickstarts/symfony) · [Pest](https://studio-design.github.io/gesso/quickstarts/pest) ## 功能 - **支持 OpenAPI 3.0、3.1 和 3.2** —— 明确的版本检测,包括 3.2 的 `QUERY`、自定义 `additionalOperations`、表单 `querystring`、`discriminator.defaultMapping` 以及可观察流的限制 - **响应和请求验证** —— 通过 opis/json-schema 实现感知方言的 JSON Schema:为 OpenAPI 3.0 提供 Draft 07 兼容性,并为 OpenAPI 3.1/3.2 提供原生的 2020-12 语义;支持 `application/json` 及任何 `+json` 内容类型 - **Endpoint 覆盖率追踪** —— 独有的 PHPUnit 扩展,以 `(method, path, status, content-type)` 的粒度报告哪些规范 endpoint 已被测试覆盖 - **Laravel 路由/规范一致性** —— `openapi:routes` 可找出缺少路由的已记录操作和缺少 OpenAPI 操作的已注册路由,支持过滤器、稳定的 JSON 输出和独立的 CI 门禁 - **基于 schema 的请求 fuzzing** —— 有效的边界、组合分支、带有明确预期状态类的定向负面测试用例、确定性的重放/缩减、全局规范过滤、生命周期/auth 钩子以及明确的跳过原因 - **Enum 漂移检测** —— 在 PHP backed enum 及其 `enum:` 规范数组之间进行静态比较,支持 PHPUnit 扩展的自动发现 - **Schema 描述不足检测** —— 可选的严格模式,标记实现总是返回但规范标记为可选的响应字段,捕获单纯的一致性检查无法发现的规范缺口。有关当前范围和限制,请参见 [`docs/strict-required.md`](docs/strict-required.md)。 - **按状态码跳过** —— 可配置的正则表达式状态码列表,不验证这些状态码的主体(默认:所有 `5xx`);可通过 `skipResponseCode()` 针对特定请求设置 - **PSR-7、Laravel、Symfony 和 Pest 适配器** —— 一流的 PSR-7 请求/响应/交换验证,为 Laravel 提供 auto-assert / auto-validate-request 集成,为 Symfony 提供 HttpFoundation 断言,以及 Pest 期望 - **支持并行运行器** —— 为 paratest / `pest --parallel` 协调 sidecar+合并工作流 - **多格式报告** —— Markdown / JUnit XML / JSON / HTML 输出,支持一键 GitHub Step Summary - **零运行时开销** —— 仅用于测试套件 ## 为什么选择这个库? 根据您所需的工作流程进行选择,而不是仅基于单一的“是/否”功能数量: - 当您需要 `(method, path, status, content-type)` 粒度的响应级覆盖率、多种 CI 报告格式、OpenAPI 3.1/3.2 JSON Schema 语义、基于 schema 的探索,或在与框架无关的核心以及 Laravel、Symfony 和 Pest 适配器之间进行漂移检测时,请选择**此库**。 - 对于 Laravel 12 应用,当生成的测试 stub、JSON 断言失败或远程/私有 GitHub 规范来源比响应级覆盖率的粒度和更广泛的框架支持更重要时,请选择 **[Spectator][spectator]**。 - 当您想要一个低级别的 PSR-7 验证器或 PSR-15 中间件,并打算自行构建测试/报告集成时,请选择 **[league/openapi-psr7-validator][league]**。 - 当您想要一个小型的 HttpFoundation 到 PSR-7 的验证桥接时,请选择 **[osteel/openapi-httpfoundation-testing][osteel]**;或者当主要需求是在 Laravel HTTP 测试周围进行自动验证时,请选择 **[laravel-openapi-validator][kirschbaum]**。 ### 功能对比(检查日期 2026-07-10) | 功能 | **此库** | [Spectator v3.0.2][spectator] | [league/psr7 v0.24][league] | [osteel v0.14][osteel] | [kirschbaum v2.0.2][kirschbaum] | | --- | --- | --- | --- | --- | --- | | 明确支持的 OpenAPI 版本 | [3.0, 3.1, 3.2](docs/supported-features.md) | 未说明版本范围 | [3.0.x][league-readme] | [3+;委托给 League v0.22][osteel-composer] | [委托给 League v0.14–0.24][kirschbaum-composer] | | 请求 + 响应验证 | ✅ | [✅ Laravel][spectator] | [✅ PSR-7][league-readme] | [✅ HttpFoundation / PSR-7][osteel-readme] | [✅ Laravel HTTP tests][kirschbaum-readme] | | 覆盖率粒度 | [`method, path, status, content-type`](docs/coverage.md) | [`method, path` operation][spectator-coverage-source] | — | — | — | | 覆盖率输出 | [Markdown, JUnit XML, JSON, HTML, GitHub Step Summary](docs/coverage.md) | [Text, JSON][spectator-coverage] | — | — | — | | 并行覆盖率合并 | [Sidecar + merge CLI](docs/parallel.md) | 未记录 | — | — | — | | 路由/规范一致性 | [`openapi:routes`](docs/laravel-route-parity.md) 支持 text/JSON 和 CI 门禁 | [`spectator:routes`][spectator-cli] | — | — | — | | CLI 诊断 / 脚手架 | [`doctor`](docs/doctor.md), [`openapi:routes`](docs/laravel-route-parity.md), 覆盖率合并;无脚手架 | [`validate`, `coverage`, `routes`, `stubs`][spectator-cli] | — | — | — | | 结构化验证失败 | 文本消息;计划支持 JSON ([#282](https://github.com/studio-design/gesso/issues/282)) | [JSON `{errors: [...]}`][spectator-errors] | [PHP exception hierarchy][league-errors] | [Wrapper exception][osteel-readme] | [PHPUnit failure text][kirschbaum-failure-source] | | 基于 schema 的探索 | [确定性 endpoint + 全局规范生成](docs/fuzzing.md) | — | — | — | — | | 漂移 / 描述不足检查 | [Enum drift](docs/enum-drift.md), [strict required](docs/strict-required.md) | — | — | — | — | | 一流集成 | [PSR-7](docs/psr7.md), [Laravel, Symfony, Pest](docs/setup.md) | [Laravel][spectator] | [PSR-7, PSR-15 middleware][league-middleware] | [HttpFoundation, PSR-7][osteel-readme] | [Laravel auto-validation][kirschbaum-readme] | | 声明的运行时最低要求 | PHP 8.3 核心;[Testbench 9–11](composer.json) ([Laravel 11–12][testbench-compat]; [Laravel 13 / PHP 8.3][testbench-11-composer]) | [PHP 8.3, Laravel 12][spectator-composer] | [PHP 7.2][league-composer] | [PHP 8.0, HttpFoundation 5–8][osteel-composer] | [PHP 8.0, Illuminate 10–13][kirschbaum-composer] | **图例**:✅ 支持 · — 未记录有等效功能。“未记录”与“不支持”有本质区别。 **方法论**:这是一次文档/来源审计,不是基准测试。声明仅限于链接的、标签固定的公开文档以及在 2026-07-10 检查的 Composer 约束。此库的声明描述了位于 [`8c6416d` 的 `main` 分支](https://github.com/studio-design/gesso/commit/8c6416dcd7edf179010f5f1cdc71a1e146a5c403);竞争对手的版本显示在表头中。当过去三个月或有新版本发布时,至少每季度使用[发布检查清单](docs/versioning.md#release-checklist)重新检查此矩阵。 ## 要求 - PHP 8.3+ - PHPUnit 12 或 13 - PSR-18 HTTP 客户端 + PSR-17 请求工厂(例如 Guzzle, Symfony HttpClient)——仅在解析 HTTP(S) `$ref` 时需要 ## 安装 ``` composer require --dev "studio-design/gesso:^2.0" ``` ## 快速开始 选择与您的技术栈相匹配且经过 CI 测试的五分钟路径: | 技术栈 | 通过的示例 | 展示内容 | | --- | --- | --- | | 与框架无关的 PHPUnit | [`examples/core`](examples/core) | 直接响应验证和覆盖率 | | Laravel | [`examples/laravel`](examples/laravel) | 显式断言、`auto_assert` 和请求验证 | | Symfony | [`examples/symfony`](examples/symfony) | HttpFoundation 请求/响应断言 | | Pest | [`examples/pest`](examples/pest) | Laravel 响应和请求期望 | | PSR-7 | [`examples/psr7`](examples/psr7) | 请求/响应交换验证 | 所有路径均从相同的开发依赖开始: ``` composer require --dev "studio-design/gesso:^2.0" ``` 下面的示例使用 PSR-7 请求和响应。可搜索的文档包含完整的[核心](https://studio-design.github.io/gesso/quickstarts/core)、[Laravel](https://studio-design.github.io/gesso/quickstarts/laravel)、[Symfony](https://studio-design.github.io/gesso/quickstarts/symfony) 和 [Pest](https://studio-design.github.io/gesso/quickstarts/pest) 快速入门指南。 ### 1. 提供您的 OpenAPI 规范 将加载器指向您的规范的入口文件。内部和本地文件系统的 `$ref` 会自动解析——无需预先打包: ``` openapi/ ├── root.yaml # paths reference ./schemas/*.yaml └── schemas/ ├── pet.yaml └── error.json ``` ### 2. 注册 PHPUnit 扩展 在运行第一个测试之前,验证该包是否可以加载并执行契约: ``` vendor/bin/gesso doctor \ --spec=openapi/root.yaml \ --strip-prefix=/api \ --phpunit-snippet ``` 该命令会解析本地引用,检查 OpenAPI/JSON Schema 方言,报告不受支持的执行功能,计算发现的操作和响应,并对不兼容的规范返回非零退出码。在 CI 中使用 `--format=json`。有关多规范、HTTP 引用、输出类别和退出码的信息,请参见 [doctor 命令参考](docs/doctor.md)。 然后注册输出的配置: ``` ``` ### 3. 验证 PSR-7 交换 当您的应用程序或 HTTP 客户端已经返回 PSR-7 消息时,通过一个独立于框架的调用来验证双方并记录覆盖率: ``` use Studio\Gesso\Psr7\OpenApiPsr7Validator; $validator = new OpenApiPsr7Validator('front'); $result = $validator->validateExchange($request, $response); $this->assertTrue($result->isValid(), $result->errorMessage()); ``` 适配器接受任何 `psr/http-message` 实现;不会将具体的 PSR-7 包添加到生产依赖中。PHPUnit 断言 trait、仅响应的操作寻址、PSR-15 测试方案和流保证在 [PSR-7 指南](docs/psr7.md) 中有所涵盖。 ### Laravel 适配器 ``` php artisan vendor:publish --tag=gesso ``` 在已发布的 `config/gesso.php` 中设置 `default_spec`,然后引入该 trait: ``` use Studio\Gesso\Laravel\ValidatesOpenApiSchema; class GetPetsTest extends TestCase { use ValidatesOpenApiSchema; public function test_list_pets(): void { $response = $this->get('/api/v1/pets'); $response->assertOk(); $this->assertResponseMatchesOpenApiSchema($response); } } ``` 在运行测试之前,将 Laravel 注册的路由与规范进行比较: ``` php artisan openapi:routes --fail-on-undocumented --fail-on-unimplemented ``` 要自动验证每个响应,请设置 `'auto_assert' => true` 并删除显式的 assert 调用。若要同时捕获请求端的漂移,请设置 `'auto_validate_request' => true`。有关完整配置和退出机制的参考,参见 [`docs/setup.md`](docs/setup.md)。 ## 文档 | 主题 | 参考 | |---|---| | PSR-7 请求 / 响应 / 交换验证和 PSR-15 测试方案 | [`docs/psr7.md`](docs/psr7.md) | | 完整设置,Laravel / Symfony / 与框架无关的适配器,auto-assert,退出属性,请求验证,HTTP `$ref` | [`docs/setup.md`](docs/setup.md) | | 测试前兼容性诊断 (`gesso doctor`) | [`docs/doctor.md`](docs/doctor.md) | | Laravel 路由/规范一致性 (`openapi:routes`) | [`docs/laravel-route-parity.md`](docs/laravel-route-parity.md) | | Pest 插件:`expect()->toMatchOpenApiResponseSchema()` 及相关方法 | [`docs/pest-plugin.md`](docs/pest-plugin.md) | | 基于 schema 的请求 fuzzing | [`docs/fuzzing.md`](docs/fuzzing.md) | | Enum 漂移检测 | [`docs/enum-drift.md`](docs/enum-drift.md) | | Schema 描述不足检测 (`strict_required`) | [`docs/strict-required.md`](docs/strict-required.md) | | 覆盖率报告模式和阈值门禁 | [`docs/coverage.md`](docs/coverage.md) | | HTML 覆盖率输出 | [`docs/coverage-html-output.md`](docs/coverage-html-output.md) | | JSON 覆盖率输出 schema | [`docs/coverage-json-schema.md`](docs/coverage-json-schema.md) | | 并行测试运行器 (paratest / Pest `--parallel`) | [`docs/parallel.md`](docs/parallel.md) | | CI 集成(GitHub Actions、PR 评论、输出格式、部分运行处理) | [`docs/ci.md`](docs/ci.md) | | API 参考 (`OpenApiResponseValidator`, `OpenApiSpecLoader`, `OpenApiCoverageTracker`) | [`docs/api-reference.md`](docs/api-reference.md) | | 支持的功能、已知限制、警告通道 | [`docs/supported-features.md`](docs/supported-features.md) | | 版本控制策略与支持矩阵 | [`docs/versioning.md`](docs/versioning.md) | ## 开发 ``` composer install # 运行测试 vendor/bin/phpunit # 静态分析 vendor/bin/phpstan analyse # 代码风格 vendor/bin/php-cs-fixer fix vendor/bin/php-cs-fixer fix --dry-run --diff # Check only ``` ## 许可证 MIT 许可证。详情请参见 [LICENSE](LICENSE)。
标签:API测试, ffuf, Laravel, OpenAPI, OpenVAS, PHP, PHPUnit, Symfony, 契约测试