メインコンテンツへ

テスト

./gradlew test は直接叩けない

バックエンドのテスト実行は /backend-test-reports skill 経由でのみ行います。 ./gradlew test を直接実行するのは deny 設定されています。理由は単純で、テストは Gradle タスクが複数に分かれていて(後述)、どれをどう実行して結果をどう読むかを skill 側に集約しているためです。

# skill 経由(これだけが正しい実行経路)
.claude/skills/backend-test-reports/test.sh run --unit
.claude/skills/backend-test-reports/test.sh run --integration --module tag
.claude/skills/backend-test-reports/test.sh run --tests "*TagServiceTest"

# 直接叩くのは NG(deny される)
./gradlew test

Claude Code(AI エージェント)だけでなく、人間が手元で確認する場合もこの skill を使うのが安全です。テストタイプの指定・モジュール絞り込み・結果サマリ表示まで一貫して面倒を見てくれます。

unit / guard / integration の区分

backend/src/test/kotlin/com/astarworks/astarmanagement/ はパッケージ単位で大まかに unit/ integration/ architecture/ に分かれていますが、実行タスクの分割は @Tag だけでなくクラス名の suffix で決まります。

タスク対象特徴
unitTest@Tag("unit") のうち、以下の 7 suffix を除いたものモック依存の高速テスト。ヒープ 2g
guardTest@Tag("unit") のうち、以下の 7 suffixだけArchUnit ベースのアーキテクチャ検証。ヒープ 4g(ArchUnit の import cache が重い)
integrationTestIntegrationTestBase を継承したテスト実 DB (TestContainers) + 実 API 呼び出し

guardTest の 7 suffix: *ArchitectureTest *GuardTest *BoundaryTest *SnapshotTest *CoverageTest *ContractTest *ParityTest。実例:

architecture/ModuleBoundaryTest.kt              # *BoundaryTest
architecture/TenantScopedTableContractTest.kt    # *ContractTest
architecture/ErrorCodeCatalogI18nParityTest.kt   # *ParityTest
architecture/NasSyncBypassGuardTest.kt           # *GuardTest

⚠️ 自衛 クラス名が FooInvariantTest のように、意図はアーキテクチャ検証でもこの 7 suffix のどれにも当てはまらないと、guardTest ではなく unitTest に無言で分類されます。新しく ArchUnit / 不変条件系のテストを書くときは、7 suffix のどれかを名前に含めてください。

Integration テストの規約

  • 基底クラスは IntegrationTestBase@Transactional を integration テストに付けない — 付けると ArchUnit ガードが落ちます 番人: IntegrationTestTransactionArchitectureTest。実際の commit タイミングやトランザクション境界を検証するのが integration テストの役割なので、テスト自体をトランザクションで包んでしまうと意味が崩れます。
  • 自衛 integration テストから直接 SQL を書かない。ガードはありませんが、RepositoryImpl 経由でテストすることで実際のアプリケーションパスを検証できます。
  • RLS が絡むテストは IntegrationTestBasewithRls / withServiceRls / withNullRls / withRawRls ヘルパーを使ってテナント・ユーザーコンテキストを設定します。

スコープ限定実行が既定

フルスイート(test.sh run --all 相当)は最終検証と CI だけで実行します。 実装中・修正中は必ずスコープを絞ってください。

# 触っているモジュールだけ
.claude/skills/backend-test-reports/test.sh run --integration --module tag

# 特定クラス・特定メソッドだけ
.claude/skills/backend-test-reports/test.sh run --tests "*TagServiceTest.shouldCreateTag*"

理由は 2 つあります。1 つは単純にフィードバックが速いこと。もう 1 つは、main の baseline に既知の赤(後述)が一定数あり、フルスイートを回すたびにその既知の赤と自分の変更由来の赤を毎回仕分けるコストが発生するためです。

既知の baseline red(自分の変更が原因ではない)

main の時点で、unit テスト 27 件(6 クラス)の失敗と unitTest タスク自体のハング(想定所要時間 20 分)、integration テスト 14 件(8 クラス、RLS 分離系テストを含む)の失敗が既知として残っています。DefaultAiMemberProvisioningIntegrationTest はいわゆる test-first の赤(advisory lock がまだ実装されていない設計上のプレースホルダ)です。

自分の変更がこれらのクラスに触れていないのに赤が出ても、それは既存の baseline であって、あなたが直したり原因調査したりする対象ではありません。ただし「自分の変更がこの baseline を悪化させていないか」(新しい失敗が増えていないか)は確認してください。

PR ゲートと CI

CI 上のプルリクエストは prTest(10 分以内を目標にした高シグナルサブセット、@Tag("pr"))と integrationGuardTest(DB レベルの RLS/認可整合性ゲート)を実行します。フルの unitTest / guardTest / integrationTestmain への push・夜間・手動実行のタイミングで走ります。

Migration を追加するテストの注意

新しい Flyway migration を追加した状態で integration テストを走らせる場合は TESTCONTAINERS_REUSE_ENABLE=false を付けて実行してください(test.sh に環境変数として渡します)。既存の TestContainers を使い回すと、追加した migration が適用されていない古いスキーマに対してテストが走ってしまいます。