「画面で動いた」から一歩進み、守るべき約束をテストと照合で確かめます。
重要なコードの抜粋へ ↓このページでわかること
- 成功と失敗のテスト
- 二重送金・同時送金の確認
- 帳簿と残高の照合
何を守るテストなのかを言葉にする
「送金APIが200を返す」だけでは、正しさを十分に説明できません。送金元と送金先の残高、借方と貸方、取引履歴、監査ログが同じ一件を指しているか確認します。失敗時には、どの表にも半端な結果が残らないことを確かめます。
入力の境界値、権限のない利用者、同じキーの再送、同時送金は、普段の画面操作だけでは見逃しやすい条件です。
異常を見つけた後の流れも必要
照合は差を見つける仕組みです。差が出たら、対象期間と口座を絞り、原因を調べ、記録を残して訂正します。黙って cached_balance を帳簿へ合わせるだけでは、原因が消えてしまいます。
v1には整合性チェックと管理画面があります。一方、通知先、担当者、復旧手順まで含む本番運用は、この学習サイトで「追加検討」として扱います。
送金テストの一件を深く見る
Aに3万円、Bに1万円あるときAからBへ1万円送るテストでは、APIの成功だけで終えません。Aが2万円、Bが2万円になり、Aには支出、Bには受取の履歴があり、仕訳の借方と貸方が1万円ずつで、監査ログにも一件残ることを確認します。
どれか一つだけ正しくても、一つの送金としては完成していません。テストで複数の記録を結びつけます。
失敗テストでは「何も動かない」を確認
残高不足、凍結中、本人確認未了、他人の口座、同じ口座への送金を試します。適切なエラーが返るだけでなく、残高、取引、仕訳が変わらないことが重要です。
OTPの誤入力や期限切れでは、申請の状態と実際の送金成立を区別して確認します。失敗を一種類にまとめると、どの境界が守られたか分かりません。
再送と競合を機械的に再現する
二重クリックは手作業でも試せますが、タイミングは毎回違います。並列リクエストを意図的に出し、同じ残高を二度使えないことを確認します。同じキーで同じ内容を再送したときと、同じキーで別内容を送ったときも分けます。
このようなテストは一度通れば終わりではありません。送金処理やデータベース関数を変えるたびに繰り返し、以前守れていた条件が崩れていないか見ます。
照合の結果をどう使うか
日々の照合で差が見つかったら、対象の口座や仕訳を特定し、関連する取引と監査ログを調べます。差を消すためにキャッシュを書き換えると、原因の証拠を失うかもしれません。
v1は照合の仕組みを学べます。本番の運用では、異常を誰に知らせるか、いつまでに調査するか、復旧をどう承認するかまで決める必要があります。
層ごとに異なるテストをする
入力形式を調べる小さなテスト、データベース関数の不変条件を調べるテスト、画面から送金後の履歴まで通すテストは、見つける不具合が違います。画面の一件が通っても、同時送金の競合は見つかりません。SQLの関数だけが正しくても、利用者へ誤った金額を表示するかもしれません。
v1の回帰テストとE2Eテストは、同じ機能を異なる境界から確認する手がかりになります。
テストデータも帳簿の約束を守る
テストのたびに残高を直接書き換えると、帳簿の不一致を生む準備方法に慣れてしまいます。初期資金や訂正を通常の記帳経路で作れば、本番で守る条件をテスト環境でも保てます。
またテスト同士が同じ顧客や口座を使い回すと、順番によって結果が変わります。独立したアクターと繰り返せる準備・片付けが必要です。
重要なコードを読む
v1.0.0 の実コードから、この章で押さえたい箇所だけを抜粋しました。前後の定義は省略しています。
失敗時に取引行が残らないことを確認する
JavaScriptfor (const u of createdUsers) {
const cnt = countTransfersFor(u.userId);
if (cnt !== 0) allZero = false;
details.push(`${u.email}=${cnt}`);
}
record("failed transfer attempts leave no public.transfers row (atomicity)", allZero, details.join(", "));まず理解する失敗させた送金について、transfers 表に取引行が増えていないか確認します。エラーが返っただけでは「記録が残っていない」とは言えません。
一歩深くこのテストは原子性の一面を確かめています。より広くは、仕訳・残高キャッシュ・監査ログも同じ取引として矛盾なく扱われるか確認します。
出典:scripts/regression/suites/transfer.mjs