rc-testing について
rc-testing は、RevenueCat のテスト手順を整える Android 開発者向けスキルです。Test Store による購入結果の検証に加え、BillingService、mockk、GitHub Actions を使った単体テストと CI を扱います。
主な機能
- 01Test Store で購入結果をテスト
- 02BillingService で Purchases をラップ
- 03mockk で ViewModel の単体テスト
- 04デバッグ版とリリース版で別のキーを設定
- 05GitHub Actions の単体テストを設定
活用シーン
- 01購入成功・失敗・キャンセル時の画面を検証
- 02Paywall ViewModel の課金処理を分離してテスト
- 03プッシュごとに単体テストを実行
- 04Google Play Sandbox で更新と決済の一連の流れを確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ revenuecat/ ai-toolkit --skill rc-testingインストール後、Claude Code で/rc-testingを入力して読み込まれたか確認します。
詳細
Android で RevenueCat をテストする
このスキルを使って、RevenueCat Android 統合の高速なテストループを構築します。ほとんどの作業では Test Store が Google Play Sandbox の代わりとなり、BillingService インターフェースによって Purchases をモック可能にし、小規模な GitHub Actions ジョブでプッシュのたびにユニットテストを実行します。
ソース全文:revenuecat.com の章全文を参照してください。
フェーズ 1:調査
変更を加える前に、すでに何があるかを確認します。各項目について、該当するファイル、または「なし」と回答してください。
| 確認項目 | 確認場所 | 確認したい内容 |
|---|---|---|
| テスト API キーは設定されていますか? | app/build.gradle.kts、local.properties、環境変数 | デバッグ時に BuildConfig.RC_API_KEY に割り当てられた test_... の値 |
| リリースキーは分けられていますか? | build.gradle.kts のリリースブロック | goog_... キーであり、test_... ではないこと |
| Purchases はラップされていますか? | app/src/main/java/**/*Billing*.kt | Purchases.sharedInstance を隠すインターフェース |
| CI はありますか? | .github/workflows/*.yml | ./gradlew testDebugUnitTest を実行するジョブ |
| シークレットは接続されていますか? | GitHub リポジトリの設定、ワークフローの env: | secrets から参照される RC_TEST_STORE_KEY |
| テストライブラリはありますか? | app/build.gradle.kts の依存関係 | io.mockk:mockk と kotlinx-coroutines-test |
これらが何もない場合は、フェーズ 3 で最初から構築します。一部がある場合は、不足しているものだけを補います。
フェーズ 2:計画
シナリオごとにテスト方法を選びます。デフォルトは Test Store です。Test Store では再現できないストアの動作が必要な場合に限り、Google Play Sandbox に切り替えます。
| シナリオ | 使用するもの |
|---|---|
| 成功、失敗、キャンセルの各パス | Test Store |
| ViewModel のユニットテスト | BillingService に対する mockk |
| プッシュのたびに実行する CI | Test Store + ユニットテスト |
| サブスクリプションの更新サイクル | Google Play Sandbox |
| 保留中の購入(保護者の承認) | Google Play Sandbox |
| エンドツーエンドの決済全体 | Google Play Sandbox |
コーディングを始める前に、計画を短いチェックリストとして tasks/todo.md に記述します。アプリでサブスクリプションを提供する場合は、Test Store で日々の反復をまかなえる場合でも、リリース前チェックリストに Sandbox での確認を 1 回含めてください。
フェーズ 3:実行
ステップ 1:テスト API キーを生成する
RevenueCat ダッシュボードでアプリを開き、アプリとプロバイダーに移動して、Test Store を作成を選択します。test_... キーをコピーします。コミットしないでください。local.properties または CI シークレットに保存します。
ステップ 2:デバッグビルドでキーを設定する
// build.gradle.kts
android {
buildTypes {
debug {
buildConfigField("String", "RC_API_KEY", "\"test_YOUR_KEY\"")
}
release {
buildConfigField("String", "RC_API_KEY", "\"goog_YOUR_KEY\"")
}
}
}
CI では、キーが git に入らないよう、環境変数から読み取ります。
// build.gradle.kts
val testKey = System.getenv("RC_TEST_STORE_KEY") ?: "test_placeholder"
buildConfigField("String", "RC_API_KEY", "\"$testKey\"")
ステップ 3:ビルド設定のキーで Purchases を構成する
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) Purchases.logLevel = LogLevel.DEBUG
Purchases.configure(
PurchasesConfiguration.Builder(this, BuildConfig.RC_API_KEY).build()
)
}
}
ステップ 4:Test Store のダイアログを表示する
デバッグモードでアプリを実行し、ペイウォールから awaitPurchase() を呼び出します。「成功」「失敗」「キャンセル」のオプションが表示されたダイアログが現れます。各選択肢は本番と同じように処理されます。「成功」では有効なエンタイトルメントを含む PurchaseResult が返され、「失敗」では支払いエラーを伴う PurchasesTransactionException がスローされ、「キャンセル」では userCancelled = true を伴う例外がスローされます。エラー処理のすべての分岐を確認して、UI の状態を検証してください。
ステップ 5:Purchases を BillingService でラップする
Purchases シングルトンはモックできません。薄いインターフェースを使うと、テストでフェイクを注入でき、ViewModel を SDK の型から切り離せます。
interface BillingService {
suspend fun getOfferings(): Offerings
suspend fun purchase(activity: Activity, pkg: Package): CustomerInfo
suspend fun getCustomerInfo(): CustomerInfo
}
class RevenueCatBillingService : BillingService {
override suspend fun getOfferings() =
Purchases.sharedInstance.awaitOfferings()
override suspend fun purchase(activity: Activity, pkg: Package): CustomerInfo =
Purchases.sharedInstance.awaitPurchase(
PurchaseParams.Builder(activity, pkg).build()
).customerInfo
override suspend fun getCustomerInfo() =
Purchases.sharedInstance.awaitCustomerInfo()
}
ステップ 6:mockk のユニットテストを書く
class PaywallViewModelTest {
private val billing = mockk<BillingService>()
private val viewModel = PaywallViewModel(billing)
@Test
fun `purchase success grants access`() = runTest {
val info = mockk<CustomerInfo> {
every { entitlements["pro_access"]?.isActive } returns true
}
coEvery { billing.purchase(any(), any()) } returns info
viewModel.purchase(mockActivity, mockPackage)
assertTrue(viewModel.state.value is PaywallState.Success)
}
}
各分岐につきテストを 1 つ追加します。成功ではアクセスを許可し、失敗ではエラーを表示し、キャンセルではアイドル状態を維持します。
ステップ 7:最小限の GitHub Actions ジョブを追加する
# .github/workflows/test.yml
name: test
on: [push, pull_request]
jobs:
unit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- name: Run tests
env:
RC_TEST_STORE_KEY: ${{ secrets.RC_TEST_STORE_KEY }}
run: ./gradlew testDebugUnitTest
test_... キーを RC_TEST_STORE_KEY リポジトリシークレットとして保存します。このジョブは、デバイスや Google アカウントがなくても実行できます。
検証
購入ごとに RevenueCat ダッシュボードを開き、顧客に移動してユーザーを選び、購入、エンタイトルメント、CustomerInfo JSON を確認します。イベントタブには、テスト購入で発生した Webhook が表示されます。
出荷前チェックリスト
-
Purchases.logLevel = LogLevel.DEBUGがBuildConfig.DEBUGによって制御されている - リリースビルドでは
test_キーではなく、goog_キーを使用している -
test_キーをコミットしていない(環境変数またはlocal.propertiesを使用) - Test Store ダイアログを使って、成功、失敗、キャンセルの各フローをテスト済み
- Google Play Sandbox で少なくとも 1 つのエンドツーエンドフローを検証済み
- Webhook エンドポイントがサンドボックスでの購入イベントを受信する