はじめに
これまで Kiro を使ってWebアプリを作る体験記事を何本か書いてきましたが、動作確認の方法はずっと同じです。Amplify Sandbox や Amplify Hosting にデプロイして、画面を開いて、手動でポチポチ触る。結果確認、バグ発見、修正依頼、またデプロイかけて数分待って…。時間はかかるけど、まぁそういうもんだと受け入れていました。
今回取り上げる AWS Blocks は、2026年6月にパブリックプレビューになったばかりの新しいサービスですが、この AWS Blocks の売りのひとつに「AWS アカウント不要でローカル完結のテスト実行」というものがあります。npm run test:e2e だけで結合テストがローカルで数秒で回せるとのこと。
本記事では、サンプルプログラムの実装を通じて確認した AWS Blocks のローカル E2E テストの仕組みと、Amplify 統合時のテスト戦略を整理してみます。
一方で、実はこれまでコーディングエージェントの実施するテストの内容についてあまり気にしてこなかったので、「Kiro が裏でどんなテストを回していたのか」についても合わせて掘り下げていこうと思います。
Blocks 導入でコーディングエージェント時代のテストはどう変わるか
筆者はプログラマではないので、テストコードを自分で書くことはありません。動作確認は Amplify Sandbox や Hosting にデプロイして画面をポチポチ操作するだけです。手動テストでは「さっき確認した部分が、別の修正で壊れていないか」を毎回網羅的に確認できるわけではないので、ここが Blocks 導入による自動テストの拡充に期待しているところです。
今回検証に用いた Blocks プロジェクトでは、Steering にて明示的に「テストが全パスしたらタスク完了」と指示したので、Kiro がタスクを実装するたびに npm run test:e2e を自分で実行し、失敗すれば修正して再テスト、通るまでループを回していました。この E2E テストがプログラム品質を支える主力となります。
では、そのテストはどういう仕組みで動いているのか。ここから技術的な中身に入ります。
テストの段階を整理する
これまでは特に意識してきませんでしたが、「テスト」と一口に言ってもいろいろあると思うので、段階的に整理しておきます。※網羅的ではないかもしれません
| 段階 | テストの種類 | 何を確認するか | いつ実行するか |
|---|---|---|---|
| 1 | 型チェック(tsc) | コードの型が合っているか | コード変更のたび(即時) |
| 2 | ユニットテスト / PBT | 関数単体のロジックが正しいか | コード変更のたび(数秒) |
| 3 | E2E テスト(結合テスト) | API → DB → レスポンスの一連の流れが正しいか | タスク実装後(数秒〜数十秒) |
| 4 | ブラウザテスト(Playwright 等) | 画面表示・操作が正しいか | 機能実装後(数十秒) |
| 5 | 手動テスト | 人間の目で見て違和感がないか | デプロイ後(数分〜) |
下に行くほど「確認できる範囲が広い」が「時間がかかる」というトレードオフです。
従来の自分のやり方は、段階1(Kiro が型チェック)→ 段階5(自分が手動確認)の2段構えだけでした。段階2〜4はスキップしていた形です。
今回 Blocks のおかげで段階3(E2E テスト) が AWS アカウント不要で回せるようになり、Kiro がこのテストパートも担ってくれるようになります。型チェックと手動テストの間に、もう一枚テストの層が挟まった のが今回の本質です。
従来の AWS ローカルテスト事情
前述の段階3(E2E テスト)を AWS バックエンドに対してローカルで実現しようとすると、以下のような手段を取ることが多いようです。
| 手段 | 追加で必要なもの | 主な制約 |
|---|---|---|
| LocalStack | Docker、設定ファイル | AWS中心の実績ある開発基盤だが、有料版でないとカバレッジ不完全 |
| SAM Local | Docker、SAM CLI | Lambda + API Gateway のみ。DB 連携は別途 |
| serverless-offline | Serverless Framework | フレームワーク依存。サービス連携はモック手書き |
いずれも「本番コードとは別のレイヤー」を追加で用意する必要があり、手間がかかります。
なお、Amplify でのアプリ開発時には npx ampx sandbox で実環境にデプロイしてテストする方法もありますが、これは段階5(手動テスト)の環境として使うのが実態です。デプロイに数分かかるため、Kiro がタスクごとに回す段階3のテストには向きません。
Blocks だとなぜ追加ツールなしでテストが書けるのか
Conditional Exports による環境切り替え
Blocks は Node.js の Conditional Exports を使い、同じ import が環境ごとに異なる実装に解決されます。package.json の exports フィールドを用いて切り替えます。
import { api } from 'aws-blocks';
// ローカル: インメモリ / PGlite 実装がロード
// Lambda: AWS SDK を使う実装がロード
テストコードも本番コードも 同じ import、同じ API 呼び出し です。テスト用のモックやスタブを別途書く必要がありません。
ローカルで何が動くか
| Block | ローカル実装 | 本番サービス |
|---|---|---|
| KVStore | インメモリ → .bb-data/ に永続化 |
DynamoDB |
| DistributedDatabase | PGlite | Aurora DSQL |
| Database | PGlite | Aurora Serverless v2 |
| AsyncJob | setTimeout(インプロセス) | SQS + Lambda |
| CronJob | 手動トリガー API | EventBridge + Lambda |
| AuthBasic | ローカル認証(cookie) | DynamoDB + JWT |
注目すべきは DistributedDatabase / Database のローカル実装が PGlite であること。SQL クエリがそのままローカルで実行されるので、SQL 構文エラーやクエリロジックのミスもテストで検出できます。
PGlite とは?
PostgreSQL を WebAssembly にコンパイルしたもので、Node.js プロセス内でそのまま動きます。Docker も外部プロセスも不要で、npm install するだけで使える圧倒的に軽量な組み込み型の PostgreSQL です。
LocalStack との比較
| 観点 | LocalStack | Blocks ローカル |
|---|---|---|
| Docker | 必須 | 不要 |
| 起動時間 | 数十秒(コンテナ) | 約1秒 |
| テストコード | エンドポイント切り替え等の設定が必要 | 本番コードと同一 |
| DB | DynamoDB Local (Docker) | PGlite (インプロセス) |
| カバレッジ | 120+ サービス(有料版) | Blocks が提供する Block のみ |
| メンテナンス | バージョン追従が必要 |
npm update のみ |
LocalStack と比べると、LocalStackは「AWS 全体のエミュレーション」、Blocks は「バックエンドを丸ごとローカルで起動」となっており、アプローチが根本的に異なります。LocalStack のカバー範囲は優秀です。
【実例紹介】在庫管理システムの E2E テスト
実際に AWS Blocks × Amplify Gen 2 でサンプルとして構築した資材在庫管理システムで、ローカル E2E テストを試してみました。
システム概要
機能一覧
| 機能 | 使用 Block |
|---|---|
| 資材マスタ CRUD | DistributedDatabase (SQL) |
| 倉庫マスタ CRUD | DistributedDatabase (SQL) |
| 入出庫記録(在庫不足チェック、OCC リトライ) | DistributedDatabase (トランザクション) |
| 在庫照会(集計クエリ) | DistributedDatabase (SQL) |
| 低在庫アラート | CronJob (EventBridge) |
| CSV 一括インポート | AsyncJob (SQS) |
| ユーザーメモ・設定 | Amplify Data (AppSync + DynamoDB) + Cognito 認証 |
業務アプリとしてはよくある構成ですが、SQL トランザクション、非同期処理、定期実行が絡むため、従来はローカルでの結合テストが非常に面倒だった領域です。
ユーザーメモ・設定は Amplify の機能を使っているため、E2Eテストの対象にはなりません。
AWS アーキテクチャ図
画面イメージ
特に指示せず完全おまかせで作りました。画面イメージとしてはこんな感じです。
E2E テストの全体像
E2E テストの構成やテストコードの作成も今回は全て Kiro のお任せにしており、結果的に全40項目となりました。各テストが何を検証しているか、カテゴリごとに整理します。
| カテゴリ | テスト数 | 検証している内容 | 検証の勘所 |
|---|---|---|---|
| 資材マスタ CRUD | 8 | 作成、一覧取得、ソート順、SKU ユニーク制約、バリデーション(空文字・不正文字・範囲外) |
UNIQUE 制約がSQL レベルで効くか |
| 資材 更新・削除 | 5 | 名前変更、存在しないIDへの操作、バリデーション、削除後の消失確認 | 更新時に他フィールドが壊れないか |
| 倉庫マスタ CRUD | 9 | 作成、一覧、ソート、更新、削除、存在チェック、バリデーション | 参照整合性(在庫がある倉庫の削除拒否等) |
| 入出庫トランザクション | 6 | 入庫記録、在庫不足時の出庫拒否、出庫後の残数確認、数量バリデーション、存在チェック |
SUM 集計 + トランザクション内の整合性 |
| 在庫照会 | 5 | 集計結果の正確性、倉庫/資材フィルタ、空結果、サマリー(複数倉庫の合算) |
GROUP BY + JOIN の集計SQL |
| アラート(CronJob) | 4 | 低在庫検知、確認(acknowledge)、冪等性(2回実行で重複しない)、存在しないアラート | 定期バッチの冪等性 |
| CSV インポート(AsyncJob) | 4 | 正常行+異常行の混在処理、サイズ制限、行数制限、在庫不足行のエラー記録 | 非同期ジョブの完了待ち + 行レベルエラー |
このように表でまとめてみると、普段の業務で受入試験時に気にしたいポイントが含まれていることがわかります。倉庫マスタ CRUDの参照整合性などはしっかりと抑えておきたい観点です。
各テストは api.createMaterial(...) のように 本番と同じ型付き API クライアント を使って実行されます。モックへの差し替えやエンドポイント切り替えの設定は一切ありません。
テストコードの構造
テストファイルは test/e2e.test.ts に配置し、npm run test:e2e で実行します。これは Blocks が公式に想定している標準構成で、AGENTS.md にもこのパスとコマンドが記載されています。Blocks 公式リポジトリのテストアプリでも同じ構成が採用されており、Kiro が自然とこのパターンに従ってテストコードを生成してくれます。
import { test } from 'node:test';
import assert from 'node:assert';
import { isServerRunning } from '@aws-blocks/blocks/utils';
import type { api as ApiType } from 'aws-blocks';
let api: typeof ApiType;
test.before(async () => {
// サーバーが未起動なら自動で起動
if (!await isServerRunning()) {
spawn('npm', ['run', 'dev:server'], { detached: true });
await setTimeout(2000);
}
// api を dynamic import(conditional exports が解決される)
const mod = await import('aws-blocks');
api = mod.api;
});
ポイント:
-
node:test(Node.js 標準のテストランナー)を使用。外部テストフレームワーク不要 -
import('aws-blocks')で API クライアントを取得。モック設定なし - サーバーが起動していなければ自動起動する仕組み
テストの実例
以下は、Kiro がスペック開発の中で自動生成したテストコードからの抜粋です。プロジェクトの機能要件(在庫管理のビジネスルール)と、Blocks が提供するテスト基盤(PGlite での SQL 実行、AsyncJob の非同期処理、CronJob の手動トリガー)の両方を踏まえて、適切なテストケースを組み立てています。
CRUD テスト
test('materials: create material with valid input', async () => {
const sku = uniqueSku('BOLT-M8');
const material = await api.createMaterial({
name: 'Steel Bolt M8',
sku,
unit: 'pcs',
category: 'Fasteners',
lowStockThreshold: 100,
});
assert.ok(material.id);
assert.strictEqual(material.name, 'Steel Bolt M8');
assert.strictEqual(material.sku, sku);
});
test('materials: duplicate SKU is rejected', async () => {
const sku = uniqueSku('DUP-TEST');
await api.createMaterial({ name: 'First', sku, unit: 'kg', category: 'Raw', lowStockThreshold: 0 });
await assert.rejects(
() => api.createMaterial({ name: 'Second', sku, unit: 'kg', category: 'Raw', lowStockThreshold: 0 }),
(err: any) => err.message.includes('SKU already exists'),
);
});
api.createMaterial() は本番でもテストでも同じ呼び出し。テスト内で「SKU ユニーク制約が効いているか」を実際の DB(PGlite)に対して検証しています。
在庫不足チェックのテスト
test('transactions: stock-out rejected when insufficient', async () => {
const mat = await api.createMaterial({ /* ... */ });
const wh = await api.createWarehouse({ /* ... */ });
// 50 入庫
await api.recordTransaction({ materialId: mat.id, warehouseId: wh.id, type: 'in', quantity: 50 });
// 100 出庫を試みる → 在庫不足で拒否されるべき
await assert.rejects(
() => api.recordTransaction({ materialId: mat.id, warehouseId: wh.id, type: 'out', quantity: 100 }),
(err: any) => err.message.includes('Insufficient stock'),
);
});
これはモックでは正確にテストできない典型例です。実際に「入庫 → 出庫」の順序で DB に書き込み、集計クエリで在庫不足を検出するロジックが正しく動くかを確認しています。
非同期処理(AsyncJob)のテスト
test('csv import: valid + invalid rows', async () => {
const mat = await api.createMaterial({ /* ... */ });
const wh = await api.createWarehouse({ /* ... */ });
const csvText = [
'material_sku,warehouse_name,type,quantity,note',
`${mat.sku},${wh.name},in,100,Bulk delivery`,
`NON-EXISTENT-SKU,${wh.name},in,50,Bad row`,
].join('\n');
// CSV インポートを実行(AsyncJob が非同期で処理)
const { jobId } = await api.importCsv(csvText);
// 結果をポーリングで取得
const result = await waitForImportResult(jobId);
assert.strictEqual(result.successCount, 1);
assert.strictEqual(result.failedCount, 1);
assert.ok(result.failures[0].error.includes('not found'));
});
ローカルでは AsyncJob は setTimeout でインプロセス処理されるため、ポーリングすれば数百ミリ秒で結果が返ります。本番では SQS + Lambda ですが、テストコードは同じです。
CronJob のテスト
test('alerts: cron job creates alert for low-stock material', async () => {
// 閾値 100 の資材を作成し、50 だけ入庫(閾値以下)
const mat = await api.createMaterial({ /* ..., lowStockThreshold: 100 */ });
await api.recordTransaction({ /* ..., type: 'in', quantity: 50 */ });
// CronJob ハンドラを手動トリガー
await api.triggerLowStockCheck();
// アラートが生成されたか確認
const { alerts } = await api.listAlerts();
const alert = alerts.find(a => a.materialId === mat.id);
assert.ok(alert);
assert.strictEqual(alert!.currentQuantity, 50);
assert.strictEqual(alert!.threshold, 100);
});
本番では EventBridge が1時間ごとに起動する CronJob を、テストでは triggerLowStockCheck() で手動実行。定期バッチの結果を即座に検証できます。
テスト実行結果
$ npm run test:e2e
# ✓ materials: create material with valid input (15ms)
# ✓ materials: list materials returns created material (8ms)
# ✓ materials: duplicate SKU is rejected (5ms)
# ... (40 tests)
# ✓ csv import: stock-out with insufficient stock (210ms)
#
# tests 40 | pass 40 | fail 0
# duration_ms 3400
40テストが約3.4秒で完走。 Docker 起動なし、AWS アカウントなし、モック手書きなし。
| 計測項目 | 数値 |
|---|---|
| Blocks ローカルサーバー起動時間 | 約1秒 |
| テスト総数 | 40件(7カテゴリ) |
| テスト実行時間(全件) | 約3.4秒 |
| 1テストあたり平均 | 約85ms |
| 最も遅いテスト(CSV インポート + ポーリング) | 約210ms |
参考として、従来の方法との開発ループ1回あたりの時間を比較します。
| 手段 | フィードバックまでの時間 | 5回繰り返した場合 |
|---|---|---|
| クラウドデプロイ(ampx sandbox) | 数十秒〜数分 | 15〜20分 |
| LocalStack (Docker 起動含む) | 30秒〜1分 | 5〜10分 |
| Blocks ローカル | 約5秒 | 約30秒 |
Kiro のスペック開発では「実装 → テスト → 修正」のイテレーションが何度も発生するため、1回あたり数秒の差が最終的な開発速度を大きく左右します。
Amplify Gen 2 統合プロジェクトでのテスト分離戦略
検証リポジトリでは AWS Blocks を Amplify Gen 2 プロジェクト内に統合して在庫管理システムを構築しています。Amplify との統合手順自体は前回の記事で詳しく解説しているので、本記事ではテストの観点に絞ります。
「何をどこでテストするか」の分離
Amplify Gen 2 + Blocks の構成では、テスト対象を明確に分離するのがポイントです。
| レイヤー | データストア | テスト手段 | AWS アカウント |
|---|---|---|---|
| Blocks API(業務ロジック) | Aurora DSQL → PGlite |
npm run test:e2e(段階3) |
不要 |
| Amplify Data(ユーザーメモ等) | AppSync + DynamoDB | PBT + sandbox 手動確認(段階5) | 必要 |
業務データ(資材マスタ、在庫、入出庫)は全て Blocks の DistributedDatabase で管理し、ユーザー固有データ(メモ、設定)は Amplify Data (AppSync + DynamoDB) で管理する構成にしました。
この分離により、日常の開発ループでは 業務ロジックのテストが AWS アカウントなしで即座に回る 状態が作れます。
Blocks E2E vs Amplify PBT — テスト信頼性の格差
同じプロジェクト内でも、Blocks で書いた部分と Amplify で書いた部分ではテストの信頼性に明確な差が出ます。
| 比較軸 | Blocks E2E テスト | Amplify PBT |
|---|---|---|
| DB 実行環境 | PGlite(実 PostgreSQL 互換) | インメモリ Map(手書きモック) |
| API 経路 | HTTP → Express → SQL → レスポンス | 関数直接呼び出し(HTTP なし) |
| テストが保証するもの | SQL が正しく動く + API 全経路が機能する | ロジックの入出力関係のみ |
| テストが保証しないもの | AWS リソース固有で発生する制約。例:Aurora DSQL(後述) | AppSync の挙動、DynamoDB の owner 認可 |
なぜこの差が生まれるかというと、AppSync にはローカルモックが存在しない からです。Amplify Data を使う部分は ampx sandbox でクラウドにデプロイしないとテストできません。
Blocks 側は PGlite のおかげで「実 DB に対する結合テスト」がローカルで完結するのに対し、Amplify 側は PBT(プロパティベーステスト)でロジックの正しさを形式的に検証する方法くらいしか取れません(別途テスト用の作り込みをしない場合)。
PBT(Property-Based Testing)とは?
「固定の入力値でテストする」従来のアプローチではなく、「満たすべき性質(プロパティ)を定義し、ランダム生成した大量の入力で検証する」手法です。今回は fast-check を使い、各プロパティに対して100種類のランダム入力を自動生成しています。たとえば「任意の不正なトークン文字列に対して認証が拒否される」「任意の有効な入力に対して CRUD のラウンドトリップが成立する」といった性質を、人間が思いつかない edge case(空文字、超長文字列、特殊文字等)まで含めて網羅的にテストできます。
3段階テスト戦略
検証リポジトリでは、以下の3フェーズでテストを進めました。
Phase 1: ローカル開発(npm run dev + npm run test:e2e)
└── 業務ロジックの検証。AWS 不要。日常はここで回す。
認証: ローカルバイパス / DB: PGlite / 非同期: setTimeout
Phase 2: Amplify Sandbox(NODE_OPTIONS="--conditions=cdk" npx ampx sandbox)
└── Cognito 統合、DSQL マイグレーション、AppSync 連携の検証。
認証: Cognito JWT / DB: Aurora DSQL / 非同期: SQS + EventBridge
Phase 3: Amplify Hosting(本番デプロイ)
└── CORS、HTTPS、CloudFront プロキシの確認。
環境変数に NODE_OPTIONS="--conditions=cdk" を設定。
日常の開発ループは Phase 1 で完結します。Phase 2 は機能が一通り実装できた段階でまとめて実施し、DSQL 固有の問題やCognito 連携を確認します。
デプロイ時に判明した詰まりポイント
ローカル E2E テストが全件パスしていても、実環境へのデプロイ時に初めて発覚する問題がありました。これは「ローカルテストの限界」として把握しておく必要があります。
DSQL 固有の制約
PGlite(ローカル PostgreSQL)では正常に通る SQL が、Aurora DSQL では固有の制約で失敗するケースです。
| エラー | 原因 | PGlite での挙動 |
|---|---|---|
unsupported mode. please use CREATE INDEX ASYNC |
DSQL は同期 CREATE INDEX を拒否 |
正常に通る |
specifying sort order not supported for index keys |
DSQL はインデックスに DESC 指定不可 |
正常に通る |
-- PGlite: ○ DSQL: ✗
CREATE INDEX idx_transactions_created ON stock_transactions (created_at DESC);
-- PGlite: ○ DSQL: ○(修正後)
CREATE INDEX ASYNC idx_transactions_created ON stock_transactions (created_at);
DSQL 固有制約の一覧: FOREIGN KEY 不可、SERIAL/SEQUENCE 不可(gen_random_uuid() で代替)、CREATE INDEX ASYNC 必須、インデックスのソート順指定不可。これらはマイグレーション SQL を書く際に意識しておく必要があります。
認証のローカルバイパスと本番の差異
ローカルの E2E テストでは、Cognito の環境変数(COGNITO_USER_POOL_ID 等)が未設定のため、CognitoVerifier が全リクエストを許可するバイパスモードで動作します。つまり認証に関するバグはローカルテストでは一切検出できません。
本番(Sandbox / Hosting)では Cognito JWT の署名検証が動くため、以下のような問題が初めて表面化します:
- トークンの取得・付与が正しく行われているか
- トークンの有効期限切れ時の再取得フロー
- ユーザーごとのデータ分離(
ownerベースのフィルタ)
これらは Phase 2(Sandbox)で手動確認する必要がある領域です。
共通する教訓
いずれも Blocks のローカルテスト基盤の不具合ではなく、「ローカルモックと実環境の構造的な差異」に起因する問題です。ローカル E2E テストで業務ロジックの正しさを高速に担保しつつ、デプロイ時に実環境固有の問題を潰すという2段構えが現実的なフローになります。
Kiro に E2E テストを回させた構成
これまでに説明した E2E テストを今回どのように Kiro に指示したのかも紹介します。
AGENTS.md + 自作Steering で実現
今回の検証リポジトリでは、Hook は使わず Steering のみで実行しました。Kiro がタスクごとに E2E テストを走らせていたのは、以下の2つの仕組みによるものです。
1. AGENTS.md(Blocks がデフォルトで用意)
AWS Blocks でプロジェクトを作ると、ルートに AGENTS.md が自動生成されます。ここに「テストは npm run test:e2e で実行する」「変更したらテストを回す」といったワークフローが書かれており、Kiro はこれを読んで動きます。
## Workflow
1. Make changes to backend (`aws-blocks/index.ts`) or frontend (`src/`)
2. Test with `npm run test:e2e` — starts a dev server automatically if one isn't running
3. For faster iteration: run `npm run dev &` in the background, then run `npm run test:e2e` repeatedly
2. Steering(検証用に追加)
AGENTS.md だけでも Kiro はテストを実行してくれる可能性がありますが、今回は念押しとして .kiro/steering/blocks-development.md を追加しました。「タスク完了の定義」として「テストが全て通ること」を明示しています。
## タスク完了の定義
**タスクが「完了」と見なされる条件:**
1. 実装コードが書かれている
2. `npm run test:e2e` が全テスト通過する
3. 型エラーがない
この Steering により、Kiro はタスクを実装するたびに npm run test:e2e を走らせ、全パスするまで修正ループを回す動きになりました。
Hook を使うパターン(別解)
もし Steering ではなく Hook で同じことを実現するなら、以下のような PostTaskExec Hook を .kiro/hooks/ に配置する形になります。
{
"version": "v1",
"hooks": [{
"name": "Run E2E Tests After Task",
"trigger": "PostTaskExec",
"action": {
"type": "command",
"command": "npm run test:e2e"
}
}]
}
今回は Hook を使わず Steering で対応しましたが、どちらの方法でも「タスク完了時にテストが回る」状態は作れます。Hook のほうが強制力は強い(Kiro がテストを忘れることがない)ので、プロジェクトの規模が大きくなったら検討しても良さそうです。
補足:Playwright を入れたらどうなるか
Playwright のようなブラウザ自動テストの存在は以前から知っていましたが、導入までは至っていませんでした。今回 Blocks の E2E テストを理解した上で整理すると、Blocks と Playwright はレイヤーが違うことがわかります。
| テスト種別 | 検証レイヤー | Blocks E2E | Playwright |
|---|---|---|---|
| API ロジック(入庫→在庫不足チェック) | バックエンド | ○ | △ |
| SQL 構文・集計クエリの正しさ | DB | ○ | × |
| 画面に正しい値が表示されるか | フロントエンド | × | ○ |
| ユーザー操作フロー(ログイン→登録→確認) | フロント+バック | × | ○ |
| レスポンシブ・アクセシビリティ | UI | × | ○ |
つまり Blocks の E2E テストは「バックエンド API + DB の結合テスト」であり、ブラウザの画面は見ていません。「画面に在庫数が正しく表示されるか」「ボタンを押したら一覧が更新されるか」は Playwright の領域です。
Blocks を導入したからといって Playwright が不要になるわけではなく、両方入れるとテストがさらに充実する関係です。将来的に Playwright も Kiro に書いてもらえれば、バックエンド(Blocks E2E)+フロントエンド(Playwright)の両面で自動テストが回る状態が作れそうです。
まとめ
今回初めて「Kiro が裏で何をしてくれていたのか」をちゃんと覗いてみました。
Blocks による E2E テストの効果測定をする中で、Blocks を使わないケースでも「もう少し Kiro にテストを任せられる余地がありそう」ということも見えてきて、テストフェーズに関する理解を深めることが出来ました。
AWS Blocks のローカル E2E テストと Kiro のスペック開発を組み合わせると、「実装 → テスト → 修正」のループが人間の介入なしに高速で回る環境が手に入ります。非プログラマの自分にとっては、Kiro にお任せできる範囲が広がったと感じています。
Blocks はまだプレビュー段階ですが、この体験が GA 後にどこまで広がるか楽しみです。
また、Sandbox 環境下での Cognito と連携した自動テストであったり、Playwright を用いたフロントエンドテストの拡充であったり、Blocks だけでなくテストフェーズ全体の見直しも進めていけると良いなぁと思いました。


