Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TIPSTARのユニットテスト

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Takayuki Yamamoto Takayuki Yamamoto
December 08, 2025
83

 TIPSTARのユニットテスト

Avatar for Takayuki Yamamoto

Takayuki Yamamoto

December 08, 2025
Tweet

Transcript

  1. ©MIXI 5 ソフトウェアの全体像 メソッド メソッド メソッド メソッド メソッド メソッド APIモジュール

    ドメインモジュール ・・・ ・・・ メソッド メソッド メソッド DBモジュール ・・・ サーバーソフトウェア ソフトウェアはコンポーネント(部品)の集合で構成
  2. ©MIXI 7 ユニットテストについて ユニットテスト (Unit Test) は、ソフトウェア開発プロセスにおけるテスト手 法の1つで、プログラムのソースコードの中で 最小のテスト可能な部分 (こ

    れを「ユニット」または「単体」と呼びます)が、設計通りに正しく動作するか どうかを検証する工程です。 by Gemini 先ほどの例だとTIPSTARでは「メソッド」をテストすることが多い
  3. ©MIXI 8 ユニットテストの保証対象 メソッド メソッド メソッド メソッド メソッド メソッド APIモジュール

    ドメインモジュール ・・・ ・・・ メソッド メソッド メソッド DBモジュール ・・・ サーバーソフトウェア ユニットテストはそれぞれの細かい部品の動作が正しいと保証する
  4. ©MIXI 9 簡単なユニットテストを⾒てみよう func CalculateTax(x) { return x * 1.1

    } 例:消費税を計算するメソッドのテスト 要件 1. 値を入力したら10%の消費税が足された値が返る 2. 小数点以下は切り下げる 3. マイナスの値が入力された場合はエラーを返す 実装したメソッド 入力 入力を1.1倍して返す 入力:100 出力:110 テストケース 要件1 入力:85 出力:93 要件2 入力:-100 出力:error 要件3 入力:100 出力:110 テスト結果 要件1 入力:85 出力:93.5 要件2 入力:-100 出力:-110 要件3
  5. ©MIXI 10 モジュールを跨ぐユニットテストを⾒てみよう(1/2) メソッド メソッド APIモジュール ドメインモジュール メソッド DBモジュール サーバーソフトウェア

    呼び出し 呼び出し APIリクエスト データ保存 例:ドメインモジュールのメソッドでDBモジュール内のメソッドが使われている
  6. ©MIXI 11 モジュールを跨ぐユニットテストを⾒てみよう(2/2) 例:TIPSTARで車券を購入するメソッドのテスト 要件 1. 購入する車券は最低1枚は指定される必要がある 2. 正しい買い目である必要がある 3.

    車券購入情報がDBに保存される必要がある さっきと同じようにメソッドの入力と出力を決めて ... 1, 2は同じ方法で検証できそうだが3はどうする...? 正しくDBに保存されたかどうかは DBを見に行かないと分からない 外部の情報を確認するのは大変 func PurchaseTickets (...) { // 1. 車券の枚数検証 … // 2. 買い目の検証 … // 3. 車券情報のDB保存 db.Store(tickets) } 実装したメソッド DBモジュールのStoreメソッドを呼び出す
  7. ©MIXI 12 モックテストを使おう モック = 模型, 試作品 ソフトウェアテストの文脈では外部モジュールをモックとして扱うことがある func PurchaseTickets

    (...) { // 1. 車券の枚数検証 … // 2. 買い目の検証 … // 3. 車券情報のDB保存 db.Store(tickets) } 実装したメソッド 実際にはDBへの保存はせず、 保存が成功する前提でテストする ただし、db.Storeに渡る値が 正しいかどうかを検証する
  8. ©MIXI 13 モックテストを使おう モック = 模型, 試作品 ソフトウェアテストの文脈では外部モジュールをモックとして扱うことがある func PurchaseTickets

    (...) { // 1. 車券の枚数検証 … // 2. 買い目の検証 … // 3. 車券情報のDB保存 db.Store(tickets) } 実装したメソッド 実際にはDBへの保存はせず、 保存が成功する前提でテストする ただし、db.Storeに渡る値が 正しいかどうかを検証する それだと正しく DBに保存されているか分からないよ ...
  9. ©MIXI 14 モックを使う上で重要な考え⽅ 完全なテストは存在しない(全てのテストケースを網羅することはできない) 要点を抑え、責務を明確に分離したテストを用意すること func PurchaseTickets (...) { //

    1. 車券の枚数検証 … // 2. 買い目の検証 … // 3. 車券情報のDB保存 db.Store(tickets) } 実装したメソッド db.Store に tickets を渡す所までが検証すべき内容 db.Store に tickets を渡した後の挙動は DBモジュール側のテストで保証する 実際にTIPSTARではDBモジュールのテスト用にDB を用意して動作を保証している
  10. ©MIXI 15 何をモックするか? 1. 外部システムとの連携が必要なモジュール a. DBへの読み書き b. 外部APIとの通信 c.

    ファイルシステム 2. 複雑な処理を行うようなモジュール 3. ランダム性の高い値を扱うモジュール a. 時間 b. ランダム関数 外部のデータまで検証するのは大変 そもそも無闇に外部と通信できない 呼び出し先のモジュールへ渡す データを作るのが大変 テストの実行毎にテスト結果が変わる 値を固定したい
  11. ©MIXI 16 エンジニア視点でいつも抜けがちなテスト項⽬ 1. エンジニアが想定するケースに漏れが発生する場合がある a. これにより適切なテストケースを網羅できない 2. モジュール間の繋ぎ込みで失敗する a.

    モックに対する誤った入力値を正としてしまい、実際に外部モジュー ルを繋ぎ込んだ場合に誤った挙動をする 3. 前任の実装者のテスト項目が漏れていて次の変更で挙動が変わる
  12. ©MIXI 17 ここでQAさんが登場 1. エンジニアが想定するケースに漏れが発生する場合がある a. これにより適切なテストケースを網羅できない 2. モジュール間の繋ぎ込みで失敗する a.

    モックに対する誤った入力値を正としてしまい、実際に外部モジュー ルを繋ぎ込んだ場合に誤った挙動をする 3. 前任の実装者のテスト項目が漏れていて次の変更で挙動が変わる エンジニアが網羅できていない仕様を 第三者目線で評価してもらう(ダブルチェック) 実ユーザーが取りうる行動パターンベースで 挙動を確認してもらう 回帰チェックによって従来の挙動に問題が起きていないか 確認してもらう TIPSTARではリリース毎に回帰チェックをしている