トピック入口・未回答のCI戦略へ
自分の声で振り返る:ラジオの話題と技術の小ネタ
https://github.com/MFQWKMR4/tech2026 の CHATGPT.md、AGENTS.md、
src/content/docs/career/index.md と次のファイルを読み、software-testing のlearnを始めてください。
- src/content/docs/software/testing.mdx
- src/content/docs/topics/software/testing.md
- reviews/software-testing.yaml
- sessions/2026-09-10-software-testing-01.yaml
reviewに新しいsessionがあればそちらも確認してください。
参照できたファイルとcommitを示し、不明はunknownとしてください。
この教材に図JSON・SQL実測ファイルはありません。
まず希望する節を一つだけ聞き、回答を待ってください。
指定がなければneeds_revisitから、一節ずつ説明→追加疑問→理解確認へ進めてください。
CIの再開問題は解答を先に出さず、回答を待ってください。
口頭learnは40分付近で区切りを提案してください。
終了時は実際の回答を根拠に、CHATGPT.mdと既存テンプレートに従ってYAML+Session narrativeを含む [Session Sync] GitHub IssueをMFQWKMR4/tech2026に作成し、URLを返してください。作成できない場合は未作成と明示し、コピー可能なタイトルと本文を返してください。
最終レビュー:2026-09-10 · 説明した(Explained)。ヒント後の理解と自力の説明を区別して記録しています。
次回、自力で確かめたいこと
- 2026-09-10 [2026-09-10-software-testing-01] unit / integration / E2E の用語を別の小例で再度独力分類し、名称だけでなく『何を本物にして何を偽物にするか』『何を保証するか』まで説明する。 根拠: 分類軸の説明後に実MySQLとmock Serviceを分類。独力の別例は未確認。
- 2026-09-10 [2026-09-10-software-testing-01] DI/interfaceを導入する判断を、testabilityの利益と抽象化コストのtrade-offから別例で再確認する。 根拠: 初回は「常に良い」、説明後にClockの利益を回答。
- 2026-09-10 [2026-09-10-software-testing-01] time / timezone / DSTの境界値テストを、仕様上必要なケースと過剰なケースに分けて再確認する。 根拠: 境界説明後に22:00直前/境界を選択、ZoneId整理後の回答。DSTは存在を問う追質問あり。
- 2026-09-10 [2026-09-10-software-testing-01] 今回未回答で終了したCIテスト戦略を続ける。unit 500 / integration 80 / E2E 20という演習条件で、毎PR・main merge後・夜間の振り分けを、検知速度・flakiness・実行コスト・failure localizationから判断する。 根拠: CIの問いを提示後に終了。未回答・解法ヒントなし。
2026-09-10のセッション
求人ページ path=src/content/docs/career/learning/line-mini-app.md、選択テーマ=A(ソフトウェアテスト)、絡めた求人要件=必須のソフトウェアテスト基礎知識+Spring等を使ったWeb開発。注文受付APIを題材に、unit / integration / E2E の責務分担、mockと実依存、外部API・DB・Kafkaの契約、interaction verification、DIとtestability、境界値・Clock・timezone/DSTまで学習した。初回回答ではAPI正常/異常系、DB更新とrollback、外部API mock、関数単位testを自発的に提示。途中でunit/integrationの用語境界と『テストのためだけのinterfaceは常に良いか』に迷いがあり、説明後に『本物にする境界と偽物にする境界』『抽象化コストとのtrade-off』へ判断を更新した。CIで毎PR / merge後 / 夜間にどう振り分けるかは未回答のまま終了。今回の学習内容を受けるsoftware-testing topicと振り返り教材を同期時に追加した。
初期テスト戦略、E2Eの組合せコスト、mockと実契約の役割は自発的に説明。用語分類・interaction・Clock・境界値・timezoneは説明後の回答を含む。DSTは追質問あり。CI戦略は未回答。詳細はsession summaryとIssue #12 Session narrative。
問い・回答の流れをIssueで読む
回答で示せたこと(ヒントの有無を含む)
- 2026-09-10 [2026-09-10-software-testing-01] 注文APIの初期テスト戦略として、API正常/異常系、DB更新と途中失敗時のrollback、外部APIのmock、ビジネスロジックのunit testを自発的に挙げた。回答:『クライアント側からAPIを叩いて…不正なリクエストに対して期待されるHTTPステータス』『データベースの更新…途中で問題が発生した場合にロールバック』『外部のAPI…その部分をモック』『関数レベルでの単体テスト』。ヒント: なし。
- 2026-09-10 [2026-09-10-software-testing-01] E2Eだけに依存しない理由を、分岐組み合わせの増加と変更時の検証効率から説明した。回答:『さまざまな分岐が発生すると組み合わせの数的にはかなり指数関数的に積み上がる』『境界で区切って、それぞれの中で正しさを確認』『E2Eはいくつかの主要パターンのみ』。ヒント: なし。
- 2026-09-10 [2026-09-10-software-testing-01] mockと実接続を、どちらが常に上位かではなく確認したい責務で使い分けた。回答:『ビジネスロジックだとした場合には…モックにしてもいい』『実際の本番に近い形でテスト』。ヒント: なし。
- 2026-09-10 [2026-09-10-software-testing-01] 決済timeout後の結果をsuccess/failedに決め打ちせず、unconfirmed/processingとして後続reconciliationで確定する考えを自発的に提示した。回答:『failedかsuccessにするのは間違っている』『unconfirmedやprocessingなど別の状態』『別のワーカー…reconcile』。ヒント: timeout時に外部側成功の可能性があるという演習条件は提示済み。
- 2026-09-10 [2026-09-10-software-testing-01] unit / integration / E2E の保証対象を支援後に整理し、実MySQLを用いたRepository testをintegration testと判断した。回答:『インテグレーションテストと呼びますね…実際の発行されるクエリが…スキーマとかに対してちゃんと正しいものになっているか、その契約』。ヒント: あり(層数だけでなく本物/偽物の境界と保証対象で分類する説明)。
- 2026-09-10 [2026-09-10-software-testing-01] OrderService + mock Repository + mock PaymentClient + no ApplicationContextをunit testと判断し、確認対象をbusiness logic/orchestrationと説明した。回答:『ユニットテストと呼びます』『Create Orderのロジック、ビジネスロジック』。ヒント: 直前にunit/integrationの定義説明あり。
- 2026-09-10 [2026-09-10-software-testing-01] 重要な副作用のinteraction verificationについて、DB保存・課金・メールを重視し、ログは通常不要だが分析上の契約なら重要になり得ると説明した。回答:『データベースへの保存と課金API』『メールの送信も』『ログの出力は検証する必要はない…ビジネス分析上重要なログ…重要』。ヒント: あり(interaction過剰検証と内部実装結合の説明後)。
- 2026-09-10 [2026-09-10-software-testing-01] integration testを残す理由をmockが見逃す実契約として説明し、DB、HTTP API、メール送信API、Kafka eventの各境界を実依存に近い形でも確認したいとした。回答:『できれば全部インテグレーションで保証したい』『モックだったら気づけないインターフェース上の違い』。ヒント: なし。
- 2026-09-10 [2026-09-10-software-testing-01] integrationだけでなくunitを残す理由を、依存結果を自由に制御して多数のbusiness scenarioを低コストで検証できる点として説明した。回答:『依存するところを自由に変えられるので、いろんなパターンでユニットテスト』『インテグレーションでやろうとすると確認のコストが高まる』。ヒント: なし。
- 2026-09-10 [2026-09-10-software-testing-01] メール送信失敗でも注文成功というルールをservice unit testで確認し、Payment/Mail/DB依存をmockにしてbusiness ruleを検証する方針を提示した。回答:『これはユニットテスト』『サービス層が依存している…モック化』『データベースも本物を用意しなくてもいい』。ヒント: なし。
- 2026-09-10 [2026-09-10-software-testing-01] 時刻依存についてClock等の注入を採用する理由を、特定時刻を再現可能にして決定的なテストを行うためと説明した。回答:『完全に注入可能にします』『時間という依存を操作する必要がある…その時間帯でしかテストができない』『利益が上回る』。ヒント: あり(interface抽象化にはコストがあり常に正解ではない、という説明後)。
- 2026-09-10 [2026-09-10-software-testing-01] 境界値テストについて、境界直前と境界そのものを優先し、22:01は同じ側の同値クラスとして削減できる判断を行った。回答:『22時直前でフォルス』『22時ジャストでトゥルー』『あとはいらない』。ヒント: あり(21:59/22:00/22:01の境界例説明後)。
- 2026-09-10 [2026-09-10-software-testing-01] 店舗timezoneをbusiness ruleの入力として扱い、server timezone固定に依存せず店舗現地時刻へ変換して判定する方向へ進んだ。回答:『店舗情報が含まれている』『ニューヨーク時間、現地時間を再計算するようなロジック』。ヒント: あり(current instant + store ZoneIdという整理後に最小ケースを選択)。
- 2026-09-10 [2026-09-10-software-testing-01] DSTについて、UTC instant自体ではなくlocal timeへのoffsetが期間で変わる点を説明した。回答:『UTCの時間は変わらない…現地時間に直す瞬間に、ある日以前以後で追加するべき時差が変わる』。ヒント: DSTの存在を問う追質問あり。
自力では説明しきれなかったこと
記録された項目はありません。
理由・設計を詰めたいこと
- 2026-09-10 [2026-09-10-software-testing-01] unit / integration の命名を『層をまたぐか』『DBが入るか』で一時的に迷い、定義軸が不安定だった。回答:『データベースもモック化されてたらこれはインテグレーションと呼べるのか』『モデルだけでDB操作までテスト…インテグレーションって呼ぶのかな』。ヒント: あり(本物にする境界/偽物にする境界、Spring containerや実DB等の実行基盤を軸に説明)。次回は別例で独力再確認する。
- 2026-09-10 [2026-09-10-software-testing-01] 『テストしやすくするためだけにinterfaceを切るのは常に良いか』に対して、初回は抽象化コストの反例を出せず『常に良い』とした。回答:『悪くなるようなシナリオが考えつかなかったので常に良いと今は考えています』。ヒント: あり(不要なinterfaceは型/ファイル/追跡コスト、存在しない差し替え可能性、mockへの実装結合を生むと説明)。その後Clock例では利益が抽象化コストを上回ると判断した。
- 2026-09-10 [2026-09-10-software-testing-01] `hour >= 22` の検討で『日付を見れてないので問題』と述べたが、毎日22:00以降という提示要件だけなら日付は必須ではない。回答:『アワーだけの指定だと日付を見れてないので問題』。ヒント: あり(特定日や翌朝まで等の追加要件がなければunknown/不要と説明)。
修正が必要な説明
記録された項目はありません。
まず「防ぎたい不具合」を挙げ、依存の何を本物にするかを決める。unit / integration / E2Eはチーム間で範囲が異なるため、クラス数や層数だけで会話しない。この教材では次の作業上の分類を使う。テストで確認できるのは選んだ条件・経路であり、全入力や本番動作の保証ではない。
| 注文APIの小例 |
本物/test double |
分類と確認対象 |
ここでは確認できないこと |
| OrderServiceを直接生成 |
serviceは本物、Repository/PaymentClientはmock、Spring contextなし |
unit:分岐、返す状態、依存への業務上の指示 |
SQL、HTTP契約、DI設定 |
| Repositoryの保存・再読込 |
repositoryと専用MySQLは本物 |
integration:実SQL・schema・mapping |
決済APIや注文全体 |
| Spring contextを起動しserviceを取得 |
bean構成は本物、外部APIはmockでもよい |
integration:配線・設定・対象proxyの振る舞い |
mock先の通信・本番設定との差 |
| 起動したAPIへ注文リクエスト |
アプリ・DBを通し、外部決済はsandbox等。境界を明記 |
APIを入口とするE2E:代表的な注文経路の観測結果 |
ブラウザ操作や本番決済との差、全分岐 |
Springではcontainerなしでserviceをmock/stubのrepositoryと組み合わせられる。逆に実DBを使うrepository testは、一つのモデルしか呼ばなくてもDBとの統合を確認する。Spring Framework 7.0.9 Unit Testing、Integration Testing。
実DBはintegrationの必要条件ではない。MockMvcのように実HTTPサーバーなしでWeb層の統合を確認する仕組みもある。HTTPでアクセスしただけでもE2E全体を確認したとは限らず、WebTestClientもmock環境への接続と稼働サーバーへの接続を持つ。Spring 7.0.9 WebTestClient。
多数の業務分岐はunitで依存結果を制御し、境界の実契約をintegrationで確認し、利用経路の代表例をE2Eでつなぐのが出発点。E2Eだけに全組合せを載せると準備・実行・原因特定のコストが増える。ただし固定の比率や件数を正解にせず、リスクと検知したい故障で選ぶ。
test doubleは代用品の総称。ここではstubは決めた応答を返す役割、mockは呼出しの期待を検証する役割、fakeは簡略実装と呼ぶ。同じライブラリのmock objectでstub応答と呼出し検証の両方を行える。
| 依存の置き方 |
確認する範囲 |
残る差分 |
| PaymentClientをmock |
成功・例外・結果不明を受けたserviceの分岐 |
JSON、header、認証、実clientのtimeout設定 |
| HTTP stub serverへ実clientで接続 |
request body/headerとresponseの変換、用意した遅延へのtimeout |
stub側に書いた仕様がproviderと合うか、本番network/TLSとの差 |
| provider sandbox |
sandboxが実装する認証・API・状態照会契約 |
本番固有の制限、障害、課金・メール配信の実結果 |
| 専用の実DB |
schema・SQL・制約・transactionの実動作 |
本番データ量・設定・競合を再現しなければその影響 |
| 実Kafkaへproduce |
producer設定とbrokerへの送信 |
consumerが読めるschema・業務意味 |
| 実Kafka+実consumer deserialize |
生成したeventが受信側の型へ変換できること |
未投入versionの互換性、業務処理完了、全障害経路 |
HTTP clientのmethodをmockする位置と、通信先をstub serverへ替える位置は違う。後者はclientの実際の通信処理を通せるが、stubの応答は自分で用意する契約である。Spring Framework 7.0.9 Testing Client Applications。
Kafkaのrecord valueはbyte列であり、brokerへのproduce成功だけでは「金額の単位が円」「consumerが必須fieldを読める」までは分からない。schema registry等を導入した追加の検証契約とも分ける。Apache Kafka 4.3 Message Format。メールもproviderの受付成功と受信箱への到達を分けてassertする。
決済timeoutを注入するunit testは「結果不明をfailedと決めつけない」分岐を確認できるが、同じkeyで再送すれば重複課金されないというprovider契約の証明にはならない。照会・retryの契約はAPI冪等性の教材で確認する。
演習上の追加条件として「決済成功後、メールだけ失敗しても注文成功」「注文結果は保存する」を置く。以下は設計例で、実装・実行済みテストではない。
| assertion |
捕まえたい不具合 |
限界 |
| 戻り値がPAID、金額が期待値 |
メール例外で注文が失敗になる、料金計算が違う |
保存指示を忘れても通る可能性 |
| repositoryへ期待する注文ID・PAID・金額を保存する指示 |
戻り値だけ正しくて保存を呼ばない |
mockへの指示であり、実DB commitは未確認 |
| paymentへ業務key・金額で課金を依頼 |
別keyや誤金額で課金を依頼 |
外部で実際に処理されたかは未確認 |
| 許可しない副作用が呼ばれない |
不正注文で課金してしまう |
この経路の観測であり全経路ではない |
戻り値や観測可能な状態で十分なら、内部helperの順番を固定しない。副作用そのものが契約ならinteractionを確認する。回数や順序も仕様に意味があるときに限る。retry可能な経路へ無条件に「必ず1回」を課すと正当な実装変更を阻害する。Mockitoも verifyNoMoreInteractions() の常用が過剰指定を生むと説明している。Mockito 5.20.0公式Javadoc source・section 8。
diagnostic logの細かい文言は通常の業務契約ではない。一方audit/analytics eventは下流が依存するならID・金額・必須field等を確認する。DBの最終状態は実DBのintegrationで別途確認し、mock呼出しの検証と混同しない。
| 対象 |
小さな設計の出発点 |
判断理由 |
| 外部HTTP I/O |
serviceの外でclientを構築して注入 |
成功・timeout・例外を制御できる。業務境界を表すinterfaceは候補 |
| 現在時刻 |
既存のClock、または呼出し元で取得したInstantを渡す |
待たずに特定時刻を再現できる。独自Clock wrapperは必須でない |
| 乱数 |
乱数源または生成済み値を渡す |
同じ条件を再現できる。ただし乱数の統計的性質を証明するテストとは別 |
| 純粋な料金計算 |
入力と戻り値を直接テスト |
外部依存がなければ、テスト目的だけのinterfaceを足す利益が小さい |
| 実装を一対一転送するだけのwrapper |
制御したい境界があるか確認 |
型・ファイル・追跡コストが増え、mockが内部構造に結合しやすい |
DIは「必ず独自interfaceを作る」ことではない。constructor引数、既存の抽象型、関数の入力で十分な場合がある。直接生成しているclientでもmock frameworkの機能で差し替え可能な場合はあるが、構築方法への結合と保守コストを考える。ClockはJava標準が提供する時刻の抽象で、Clock.fixed を使ってテスト時の現在時刻を固定できる。Java SE 25 Clock。
演習上の追加条件は「毎日、店舗の現地時刻22:00以上なら深夜料金」。翌朝までの継続、祝日、特定日は未提示でunknown。この条件では日付そのものの分岐は不要で、00:00にfalseへ戻る。22時から翌朝までが意図なら、終端時刻を確認して仕様を変える。
Java SE 25による概念例(コンパイル・実行は今回未実施):
boolean isLate(Instant now, ZoneId storeZone) {
LocalTime local = now.atZone(storeZone).toLocalTime();
return !local.isBefore(LocalTime.of(22, 0));
// 呼出し側はclock.instant()を渡す。テストは固定Instantを直接渡せる。
Instant は時間軸上の時点、ZoneId は店舗の地域ルール。同じinstantでも店舗ごとのlocal timeが異なる。serverのdefault timezoneは業務入力にしない。Instantからの変換と、曖昧なLocalDateTimeを受け取る処理は別である。Java SE 25 ZonedDateTime。
| 選ぶケース(概念例) |
目的 |
追加するかの判断 |
| 21:59:59.999999999 → false、22:00:00 → true |
境界の直前と包含を確認 |
入力精度が分なら21:59/22:00。精度を先に決める |
| 22:01 → true |
境界直後側の代表 |
単純な同一分岐なら22:00と同値クラス。予算に応じて省略可能 |
| 23:59 → true、00:00 → false |
一日の端・日付をまたぐリセット |
翌朝まで続く仕様との取り違えを防ぎたいとき |
| 同じ2026-09-10T13:00Zを東京とNYへ変換 |
東京22:00はtrue、NY09:00はfalse |
timezone入力を無視する不具合を区別 |
| NYの冬と夏の現地22:00 |
固定offsetの誤実装を区別 |
NYを扱うなら候補。冬は翌日03:00Z、夏は翌日02:00Z |
| DSTで飛ぶ・重複するlocal time |
存在しない時刻・二重の時刻の扱い |
LocalDateTime入力、予約、営業時間の要件次第。現要件では必須と断定しない |
同値分割は「同じ仕様上の扱いになる領域から代表を選ぶ」、境界値は「その扱いが変わる端を確認する」というテスト設計上の整理。2点だけで全バグを検出できる意味ではなく、異なる変換処理や日跨ぎには別ケースが必要になる。
DSTはUTCの時点を動かす仕組みではなく、地域のoffsetルールに従ってlocal timeへの対応が変わる。Instantからなら対応する時刻は一意に求まるが、逆方向のLocalDateTimeにはgap/overlapがある。テスト実行環境のJDK・timezone database差も調査対象になる。
実DB・brokerは専用環境と分離したデータを使い、本番のversion・schema・設定との差を記録する。HTTP stubの期待値がprovider仕様から古くなっていないか、sandboxでしか成立しない条件がないか確認する。DB test自体の後片付けでrollbackした事実と、アプリが途中失敗時に正しくrollbackした事実を区別する。
CIへの配分は未回答の再開問題で考える。この教材では毎PR・merge後・夜間の正解表を先に置かない。
失敗した入力・固定時刻・seed・DB状態・依存version・応答をまず保存する。単独では通るなら順序依存や共有データ、CIだけならtimezone・環境設定・依存起動の準備状態を確認する。HTTP timeoutは待ち時間設定とstubの遅延を照合し、Kafkaはproduce受付・consumer受信・deserialize・業務処理のどこまで進んだか分ける。
再実行で緑になっただけでは解決としない。コードの不具合、契約差、テスト環境の不安定さを切り分け、必要な証拠と担当を残す。内部呼出し順の変更だけで落ちた場合は、assertionが業務契約を超えていないか見直す。
2026-09-10-software-testing-01(Issue #12)の質問を一般化した教材。保証範囲、interaction、抽象化、時刻の最小ケースを扱う。比較表で説明できるため追加の図は作成していない。実DB・HTTP・Kafka・Javaの実験結果や本人の実務経験を表すものではない。
一次資料の対象はSpring Framework 7.0.9(Testing総覧)、Apache Kafka 4.3、Java SE 25、Mockito 5.20.0。各節に参照URLを記載し、2026-09-10に確認した。versionのないSpring URLは将来更新され得るため、上記は確認時の版。