hybrid-cloud-test-gen について
Sentry のハイブリッドクラウド向けテストを作成するスキルです。RPC、API ゲートウェイ、outbox、silo デコレーター付きエンドポイントを扱う開発者向けに、分類別の手順とテスト制約を示します。
主な機能
- 01RPC、ゲートウェイ、outbox、エンドポイントのテスト
- 02ソースと既存テストの確認手順
- 03silo モードとテスト基底クラスの指針
- 04ファクトリーと pytest アサーションの規則
- 05テスト検証チェックリスト
活用シーン
- 01クロス silo RPC サービスのテスト追加
- 02API ゲートウェイの転送動作の検証
- 03outbox メッセージと silo 間の作用確認
- 04silo デコレーター付きエンドポイントのテスト
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ getsentry/ sentry --skill hybrid-cloud-test-genインストール後、Claude Code で/hybrid-cloud-test-genを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/api-gateway-tests.mdendpoint-silo-tests.mdoutbox-tests.mdrpc-service-tests.md詳細
ハイブリッドクラウドテストの生成
このスキルは、Sentry のハイブリッドクラウドアーキテクチャ向けのテストを生成します。RPC サービス、API ゲートウェイのプロキシ、アウトボックスパターン、エンドポイントのサイロデコレーターを対象とします。
重要な制約
常にファクトリメソッド(
self.create_user()、self.create_organization())を使用してください —Model.objects.create()は決して使用しないでください。
ファクトリメソッドの呼び出しを
assume_test_silo_modeやassume_test_silo_mode_ofでラップしないでください。ファクトリはサイロを認識しており、サイロモードを内部で処理します。サイロモードのコンテキストマネージャーは、直接の ORM クエリ(Model.objects.get/filter/count/exists/delete)にのみ使用してください。
常に
pytestスタイルのアサーション(assert x == y)を使用してください —self.assertEqual()は決して使用しないでください。
そのモジュール用のファイルが存在しない場合を除き、常に新しいテストファイルを作成するのではなく、既存のテストファイルにテストを追加してください。
クロスサイロの ORM アクセスについて: 単一のモデルにアクセスする場合は
assume_test_silo_mode_of(Model)を使用してください(サイロを自動検出します)。ブロックが複数のモデルまたはモデル以外の操作を対象とする場合はassume_test_silo_mode(SiloMode.X)を使用してください。
outbox_runner()を使用するテストを含め、ほとんどのテストにはTestCaseを使用してください。実際にコミットされたトランザクションを必要とするテスト(スレッディング、並行処理、マルチプロセスシナリオ)の場合にのみTransactionTestCaseを使用してください。
RPC モデルを扱うテストファイルでは
from __future__ import annotationsを決して使用しないでください。
ステップ 1: テストカテゴリの特定
ユーザーのリクエストに基づいて、生成する HC テストのカテゴリを判断します:
| シグナル | カテゴリ | 移動先 |
|---|---|---|
| RPC サービス、サービスのメソッド、シリアライゼーションのラウンドトリップ、ディスパッチ | RPC サービステスト | ステップ 3 |
| API ゲートウェイ、プロキシ、ミドルウェア、転送 | API ゲートウェイテスト | ステップ 4 |
| アウトボックス、クロスサイロメッセージ、ControlOutbox、CellOutbox、アウトボックスのドレイン | アウトボックスパターンテスト | ステップ 5 |
| サイロデコレーター付き API エンドポイント、エンドポイントテスト、権限チェック | エンドポイントサイロテスト | ステップ 6 |
シグナルが曖昧な場合は、どのカテゴリかをユーザーに確認してください。
ステップ 2: コンテキストの収集
テストを生成する前に:
-
テスト対象のソースモジュールを読み込みます。
@cell_silo_endpoint、@control_silo_endpoint、local_mode = SiloMode.X、または@cell_silo_model/@control_silo_modelデコレーターを確認して、そのサイロモードを判断します。 -
ミラーパスの規則を使用して既存のテストファイルを見つけます:
src/sentry/foo/bar.py→tests/sentry/foo/test_bar.pysrc/sentry/foo/services/bar/service.py→tests/sentry/foo/services/test_bar.pysrc/sentry/foo/services/bar/impl.py→tests/sentry/foo/services/test_bar.py
-
既存のテストファイルを読み込み、すでにテストされている内容、使用されている基底クラス、確立されているパターンを把握します。
-
ソースのメソッドシグネチャを読み込み、パラメーター、戻り値の型、および関係する RPC モデルを把握します。
ステップ 3: RPC サービステストの生成
完全なテンプレートとパターンについては references/rpc-service-tests.md を読み込んでください。
RPC サービステストは以下をカバーする必要があります:
- サイロ互換性:
@all_silo_testにより、サービスがすべてのサイロモードで動作することを保証します - シリアライゼーションのラウンドトリップ:
dispatch_to_local_serviceにより、引数と戻り値がシリアライゼーションを経ても保持されることを検証します - フィールドの正確性: RPC モデルと ORM オブジェクトのフィールドごとの比較
- エラーハンドリング: not-found の戻り値、無効化されたメソッド、リモート例外のラップ
- クロスサイロの影響: 伝播のチェックのための
outbox_runner()+assume_test_silo_mode
クイックリファレンス — デコレーターと基底クラス
| シナリオ | デコレーター | 基底クラス |
|---|---|---|
| 標準的な RPC サービス | @all_silo_test | TestCase |
| 名前付きセルを使用する RPC | @all_silo_test(cells=create_test_cells("us")) | TestCase |
| メンバーマッピングのアサーションを含む RPC | @all_silo_test | TestCase, HybridCloudTestMixin |
ステップ 4: API ゲートウェイテストを生成する
完全なテンプレートとパターンについては、references/api-gateway-tests.md を読み込んでください。
API ゲートウェイテストは、コントロールシロのエンドポイントへのリクエストが適切なセルに正しくプロキシされることを検証します。これらは以下をカバーする必要があります:
- プロキシのパススルー: 正しいパラメーター、ヘッダー、ボディで転送されるリクエスト
- クエリパラメーターの転送: 複数値のパラメーターが保持される
- エラーのプロキシ: 上流のエラーが正しく転送される
- ストリーミングレスポンス: プロキシされたレスポンスボディを読み取るための
close_streaming_response()
クイックリファレンス — デコレーターと基底クラス
| シナリオ | デコレーター | 基底クラス |
|---|---|---|
| 標準的なゲートウェイテスト | @control_silo_test(cells=[ApiGatewayTestCase.CELL], include_monolith_run=True) | ApiGatewayTestCase |
ステップ 5: アウトボックスパターンテストを生成する
完全なテンプレートとパターンについては、references/outbox-tests.md を読み込んでください。
アウトボックステストは、シロ間のメッセージが作成され、排出され、期待される副作用を生み出すことを検証します。これらは以下をカバーする必要があります:
- アウトボックスの作成:
outbox_context(flush=False)を使用して正しいアウトボックスレコードを検証する - アウトボックスの処理:
outbox_runner()が保留中のメッセージを排出する - シロ間の副作用: レプリカ/マッピングの状態を確認するための
assume_test_silo_mode_of(Model) - 冪等性: 同じシャードを2回排出しても重複が発生しない
クイックリファレンス — デコレーターと基底クラス
| シナリオ | デコレーター | 基底クラス |
|---|---|---|
| コントロールアウトボックステスト | @control_silo_test | TestCase |
| セルアウトボックステスト | @cell_silo_test | TestCase |
| スレッディング/並行処理を伴うアウトボックス | (なし) | TransactionTestCase |
ステップ 6: エンドポイントシロテストを生成する
完全なテンプレートとパターンについては、references/endpoint-silo-tests.md を読み込んでください。
エンドポイントシロテストは、API エンドポイントが宣言されたシロモードの下で正しく動作することを検証します。これらは以下をカバーする必要があります:
- 正しいシロデコレーター: エンドポイント → テストデコレーターを一致させる
- シロ間のデータセットアップ: ファクトリメソッドを使用してデータを作成する(シロラッパーは不要)
- 権限チェック: 不正なアクセスに対する 401/403 を検証する
- レスポンスの正確性: レスポンスボディが期待されるデータと一致することを検証する
クイックリファレンス — デコレラクターマッピング
| エンドポイントデコレーター | テストデコレーター |
|---|---|
@cell_silo_endpoint | @cell_silo_test |
@control_silo_endpoint | @control_silo_test |
@control_silo_endpoint (with proxy) | @control_silo_test(cells=create_test_cells("us")) |
| No decorator (monolith-only) | @no_silo_test |
ステップ 7: 検証
生成されたテストを提示する前に、このチェックリストに照らして検証してください:
- テストクラスに正しい silo デコレーターがある
- 単一モデルの ORM アクセスには
assume_test_silo_mode_of(Model)、複数モデル/非モデルの ORM ブロックにはassume_test_silo_mode(SiloMode.X)を使用している - ファクトリメソッド(
self.create_*)がassume_test_silo_modeでラップされていない - ファクトリメソッドを使用している —
Model.objects.create()は決して使用しない -
pytestスタイルのアサーションのみを使用している(assert x == y) - 正しい基底クラスを使用している(ほとんどのテストでは
TestCase、スレッド/並行処理の場合のみTransactionTestCase) - インポートが正確かつ最小限である
- テストファイルが正しいミラーパスにある
- テストメソッドに説明的な名前が付いている(
test_<action>_<scenario>) - 実行コマンド:
pytest -svv --reuse-db tests/sentry/path/to/test_file.py
主要なインポート クイックリファレンス
# Silo decorators
from sentry.testutils.silo import (
all_silo_test,
control_silo_test,
cell_silo_test,
no_silo_test,
assume_test_silo_mode,
assume_test_silo_mode_of,
create_test_cells,
)
# Base classes
from sentry.testutils.cases import TestCase, TransactionTestCase, APITestCase
# Cross-silo utilities
from sentry.testutils.outbox import outbox_runner
from sentry.testutils.hybrid_cloud import HybridCloudTestMixin
from sentry.silo.base import SiloMode
# RPC testing
from sentry.hybridcloud.rpc.service import dispatch_to_local_service
# API gateway testing
from sentry.testutils.helpers.apigateway import ApiGatewayTestCase, verify_request_params
# Outbox models
from sentry.hybridcloud.models.outbox import ControlOutbox, CellOutbox, outbox_context
from sentry.hybridcloud.outbox.category import OutboxCategory, OutboxScope
コンテキストマネージャー クイックリファレンス
# Use ONLY for direct ORM queries — never for factory calls
assume_test_silo_mode(SiloMode.CONTROL) # Switch to control silo for ORM access
assume_test_silo_mode(SiloMode.CELL) # Switch to cell silo for ORM access
assume_test_silo_mode_of(ModelClass) # Switch to silo matching model's silo mode
outbox_runner() # Drain all pending outboxes on exit
outbox_context(flush=False) # Create outboxes without flushing
override_cells(cells) # Override active cell config
override_settings(SILO_MODE=SiloMode.X) # Override Django settings
override_options({"key": value}) # Override Sentry options