Communitygithub.com

lguidolin/graphql-contract-testing

GraphQLクエリ/ミューテーションをUIとテストで共有する際や、ルート/スキーマのコントラクトテストやスモークテストを構築する際に使用します。症状:テストへのクエリのコピペ、クエリテキストをアサートするテスト、UIビルドを壊さないスキーマ変更、RLS/パーミッションのズレ。キーワード:graphql-codegen、typed document、コントラクトテスト、ルートスモークテスト。

graphql-contract-testing とは?

このスキルは、GraphQLベースのアプリケーションにおいて、UIとバックエンド間の契約(コントラクト)を強制するテスト手法を提供します。graphql-codegenを用いて型安全なドキュメントを一元管理し、UIとテストが同じアーティファクトをインポートすることで、両方向のズレ(DB→UIのスキーマ変更、UI→DBの権限変更)をコンパイル時または実行時に検出します。また、ルート単位のスモークテストを定義し、URLの追加や削除にテスト変更を強制することで、UIの基本的な動作を保証します。PostGraphileとシード済みテストDB、RLSロールマトリックスを組み合わせたランタイムテストにより、実際の権限コンテキストでのデータアクセス結果を検証します。この手法は、従来のクエリ文字列そのものをチェックするアンチパターン(変更検出器)を排除し、真の契約(データ形状とアクセス権限)の変化のみをキャッチすることを目的としています。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/lguidolin/agent-skills/tree/main/skills/graphql-contract-testing

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

GraphQL コントラクトテスト

概要

レイヤー間の継ぎ目に位置し、一方が他方の同意なしに動いたときに壊れるテスト — 境界に適用された「テスト・アズ・ア・コントロール」。基本ルール:契約(コンシューマーが依存するデータ形状とアクセスセマンティクス)をアサートし、クエリ文字列自体は決してアサートしない。 見た目のクエリ編集で壊れるテストは変更検出アンチパターンであり、保証された形状や権限が動いたときに壊れるテストがコントロールである。

§1 — GraphQL クエリ契約

  • すべての操作は、既知の場所に型付きドキュメントとして一度だけ作成され、エクスポートされてインポートされる。 UIはそれをインポートし、テストはまったく同じアーティファクトをインポートする — 決して再入力したコピーではない。テストにクエリをコピペすると契約が静かに破壊される(UIクエリを編集してもテストが壊れなくなる)。DRYが耐荷重になる。
  • 構造上、双方向に壊れる:
    • DB → UI のズレ:コンパイル時に。 graphql-codegen がライブスキーマからTypeScript型を生成する。使用中のフィールドをリネームまたは削除すると、tsc がすべての使用箇所 および 共有ドキュメントで失敗する — ユーザーが空白のパネルを見る前にビルドが壊れる。これがライブスキーマに対するコード生成が必須である理由である。
    • UI → DB / パーミッションのズレ:実行時に。 共有ドキュメントが、実際の呼び出しパスを通じてシード済みテストDBに対して、ロールコンテキスト下で実行され、返された形状とアクセス結果(クエリテキストではない)をアサートする。
  • コントラクトテストとRLSロールマトリックスは同じハーネスである。 一つのドキュメントをPostGraphileを通じてロールA(データを期待)およびロールB(拒否/空を期待)として実行する。一つのメカニズムが3つのことを証明する:クエリがまだスキーマに一致する、UIの前提がまだ有効である、RLSがまだ境界を強制している。

実例 — 実際のバグがどのように捕捉されるか

  • DB→UI: マイグレーションで equipment.is_active が削除される。Codegenが新しいスキーマから再生成し、生成された型からフィールドが失われる。tsc が共有ドキュメントとそれを使用するすべてのコンポーネントで失敗する — マージ前にビルドで捕捉される。 テストは「クエリテキスト == X」をアサートしない。
  • UI→DB: 開発者がUIクエリを拡大して cancellation_reason を取得しようとする(RLSは昇格ロールにのみ公開)。一般メンバーとして実行されるランタイムテストがメンバー可視形状をアサートし、null/拒否を得て失敗する — 「これを公開する意図があったのか?」を強制する。

§2 — ルートコントラクトとスモークテスト

  • ルートは単一ソースから列挙される。 各ルートにはスモークテストがある:エラーなくレンダリングされる + 最小限の必須要素セット(見出し、ランドマーク、主要なコントロール — 詳細なインタラクションは不要)を表示する。
  • ルートの追加/削除は対応するテスト変更を強制する — 新しいURLはスモークテストなしでは不完全であり、削除されたURLはそのテストを削除する。URLが黙って出現したり消失したりすることは決してない。
  • 明示的に詳細なUI/インタラクションテストではない — 意図的で範囲を限定。問題は「このURLは機能し、エッセンシャルをレンダリングするか」であり、それ以上ではない。

強制手段: コンパイル時には graphql-codegen + tsc をCIで(ブロッキング)実行。ランタイムのコントラクトテスト + ルートスモークテストはシード済みDBに対してCIで実行。

完全な根拠:憲法第15条、engineering-constitution/references/engineering-constitution.md にバンドル。

Individual skills in this repo

This repo contains 18 individual skills — each has its own dedicated page.

lguidolin/change-hygiene-and-code-craft

Use when writing or refactoring code, structuring a commit or PR, or deciding whether to abstract duplication. Symptoms — mixing reorg with logic changes, a PR doing several things at once, a file growing large, the second copy of similar code, or unsure whether to DRY something up.

lguidolin/cloud-delivery-aks

Use when deploying to Kubernetes or Azure Kubernetes Service (AKS), configuring cloud secrets, setting up progressive rollout/canary, per-PR ephemeral environments, or k8s health probes. Keywords — Kubernetes, AKS, Key Vault, Argo Rollouts, Flagger, canary, blue-green, liveness, readiness, PodDisruptionBudget, HPA, rollback, GHCR.

lguidolin/commit-history-rewrite

Use when an existing repository has messy commit history that needs to conform to conventional commits before adopting release-please, or when intermediate WIP/fixup/merge commits need to be cleaned up.

lguidolin/conventional-commits-and-releases

Use when committing, writing a commit message, opening a PR that will be squash-merged, or configuring automated versioning/changelogs. Keywords — conventional commits, release-please, semver, feat/fix/chore, breaking change, changelog.

lguidolin/defense-in-depth-security

Use when handling untrusted input, secrets, authentication/authorization, or dependencies — or threat-modeling a new surface. Keywords — STRIDE, threat model, least privilege, secrets management, supply chain, dependency scanning, input validation, audit log, defense in depth.

lguidolin/designing-before-building

Use when starting a feature, fixing a non-trivial bug, or about to write implementation code — before any code exists. Symptoms you need this: "this is simple, I'll just code it", reaching for the editor before a design is approved, or an idea that hasn't been turned into a spec and plan.

lguidolin/engineering-constitution

Use when starting work in a project that follows the engineering constitution, orienting to its rules, or deciding which engineering practice applies to a task — spec writing, commits, testing, security, deploys, database, or UI work.

lguidolin/init-repo-CI

Use when setting up a new repository with conventional commits, release-please, and CI automation, or when retrofitting an existing repository that lacks automated versioning and PR validation workflows.

lguidolin/interface-craft-and-accessibility

Use when building or styling UI — components, layouts, forms, design tokens — or making accessibility decisions. Keywords — a11y, WCAG, keyboard navigation, focus state, contrast, design system, minimalist UI, component reuse, ARIA, semantic HTML.

lguidolin/merge-gates-and-automation

Use when setting up or changing CI, pre-push hooks, or a task runner, or deciding what must pass before merge. Symptoms — tempted to put authoritative checks only in a local hook, skip CI, bypass with --no-verify, or unsure what gates a merge vs. runs locally.

lguidolin/observability-and-slos

Use when adding logging, metrics, tracing, health checks, SLOs, or alerting — or when building a service surface that needs to be operable and debuggable. Keywords — structured logs, OpenTelemetry, correlation id, RED metrics, liveness, readiness, SLI, SLO, error budget, alerting.

lguidolin/performance-and-scale

Use when working on hot paths, list endpoints, pagination, data-access in loops, or public interfaces/schemas. Symptoms — unbounded queries, N+1 access, no latency budget, optimizing without measuring, or changing an interface many consumers depend on. Keywords — pagination, N+1, Hyrum's Law, performance budget, bundle size.

lguidolin/postgres-postgraphile-rls-and-sql

Use when writing PostgreSQL, PostGraphile config, Row-Level Security policies, SQL schema files, or working on the Browser→App→PostGraphile→Postgres data path. Keywords — RLS, SECURITY DEFINER, search_path, pgSettings, grants, roles, GraphQL depth limit, query cost, statement_timeout, SQL file organization.

lguidolin/recording-decisions

Use when a design or architecture decision has been made and needs to be captured — writing a decision record or ADR, updating a decision index, noting a deferred idea, or superseding a past decision. Keywords — ADR, decision record, rationale, rejected alternatives, dependency index.

lguidolin/resilience-and-deploy-safety

Use when planning a deploy, designing a rollback, or responding to an incident or writing a postmortem. Keywords — deploy safety, rollback, immutable artifact, progressive delivery, canary, blast radius, incident response, blameless postmortem, error budget.

lguidolin/ship-it

Use when the user wants to ship work — push, PR, archive decision records, merge, and clean up. Handles the full lifecycle from committing final changes through post-merge cleanup including converting specs/plans to compact decision records.

lguidolin/tests-as-a-control

Use when writing or modifying tests, when a test breaks during a refactor, or when testing permission/role rules. Symptoms — tempted to edit a test to make it pass, testing only the happy path, a deny-test that started passing, flaky tests, or unsure what to assert.

lguidolin/zero-downtime-migrations

Use when changing a database schema where data must survive the change — adding/removing/renaming columns, constraints, indexes, or backfilling. Symptoms — a destructive migration bundled with a code deploy, a NOT NULL column with a backfill, a table-locking UPDATE, or a rename. Keywords — expand/contract, parallel change, backfill, NOT VALID, CREATE INDEX CONCURRENTLY, graphile-migrate.

関連スキル