無量大数の結果と戦うテスト技法

## はじめに
本記事で紹介するテスト技法は、特定のフレームワークに依存したものではありません。これまでの経験や手法を組み合わせた、完全オリジナルのアプローチです。特殊なプロジェクトで採用した方法ではありますが、結果的に成功したと感じています。

似たようなプロジェクトは存在するかもしれません。しかし、情報にたどり着けないケースも多いため、このノウハウを共有することで、どこかのプロジェクトの役に立てばと思います。

序盤はプロジェクトの概要説明が中心です。テストに関する内容だけをご覧になりたい方は[こちら](#役割)、結論のみを知りたい方は[こちら](#最後に)をご参照ください。

## プロジェクトの概要
* <b>テーマ</b>: 発達特性検査サービスの新規開発
* <b>開発期間</b>: 約4年（実装期間 約2年）
* <b>サービス内容</b>:
  質問群（回答時間20分程度）に基づき、検査対象のお子様に合わせた「トリセツ」を作成。困難を抱えるお子様のサポートツールとなるサービス。
  サンプルイメージ: [サンプル.pdf](https://h-navi.jp/assessment/static/%E6%A4%9C%E6%9F%BB%E7%B5%90%E6%9E%9C%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB.pdf)
* <b>技術スタック</b>:
  * フロントエンド: Nuxt.js
  * バックエンド: Ruby on Rails
  * インフラ: AWS


## プロジェクトの性質
1. <b>センシティブな検査結果</b>
  検査結果が非常に重要なため、アルゴリズムの変更が頻繁にはできない。
1. <b>膨大なテキスト</b>
  結果作成に使用するテキストデータが膨大。

## 無量大数とは
無量大数は、10の68乗（10^68）を意味します。
以下は、日本の伝統的な数の単位の一部です。
<img
  class=""
  width="300px"
  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932288/939b757f-3f23-66f9-d71c-16806a28e5ea.png"
  alt="無量大数" />

本記事はタイトル詐欺ではありません。このシステムで生成される結果パターンは、計算の結果、無量大数を超えています。

* <b>出力内容</b>: 対象者の属性に応じた情報を提供し、個別最適化を実現。
* <b>膨大なパターン</b>: 分岐になる変数が多いため、パターン数が膨大
* <b>応用可能性</b>: 論理的に組み合わせパターンが多い、成果物間の整合性が求められる開発の検証に応用可能。


図で公開するのは難しいのでロジックは数で例えると約90個で構成されています。

<img
  class=""
  width="300px"
  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932288/3db57304-6a27-c9ca-7328-9daa1a079b39.png"
  alt="大分類" />

※ 実装がそのままの数にはなっていません。
このロジックから生成される大分類は7分類、小分類は18分類になります。
<img
  class=""
  width="300px"
  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932288/a8e40619-b407-16a7-9d2b-45a8ca2471ee.png"
  alt="大分類" />

## 役割分担
* <b>研究</b>:
  アルゴリズム開発、シミュレーターを用いた閾値調整。
* <b>コンテンツ</b>:
結果に使用するテキストの作成・監修。
* <b>エンジニア</b>:
実装、テキストの反映。

## 単体テスト

* <b>Rspec</b>:
    * フレームワーク外のコードを網羅的にテスト。
    * Github Actionsを活用。pushやdevブランチへのマージ時に自動実行。
    * ファイル生成とダウンロード機能を用いてカバレッジを確認可能。
      ![スクリーンショット 2024-11-19 13.52.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932288/70e711b2-3d62-888c-b96e-c1cf5d532187.png)
      ![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932288/b6fd3ca3-43e0-495d-5a30-95cf4063fac6.png)
      * コードの一部  
        * Gemfile
        ```
        group :test do
          gem 'simplecov', require: false
        end
        ```
        * Github Actions
        ```
        - name: Archive coverage artifacts
          uses: actions/upload-artifact@v4
          with:
            name: coverage
            path: api/coverage
          if: always()
        ```
<br>

* <b>入稿データ（マスターデータ）</b>:
  * seedとバッチ処理でデータ投入。
  * 定義書とクエリ結果を比較し、一致確認を自動化。
  ![スクリーンショット 2024-11-19 13.39.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932288/60c5e4be-8ed7-1d30-3fa8-48429419d7ac.png)
  レコード数は様々ですが、50シートあります。
  * 管理シートでバージョンごとの結果も記載。
  例:
  ![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932288/7f53af77-2f75-c5ee-81f2-73c7f0260440.png)
* <b>結果データのテスト</b>:
  * シミュレーターから生成されたCSVをフルスキャンまたはランダム実行。

## アルゴリズム特化のテスト
全体図:
<img
  class=""
  width="400px"
  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932288/a0120877-e946-ab78-a1c9-a7bf8defa05f.png"
  alt="ユーザテスト" />

* アルゴリズムの修正時、コンテンツの修正時の動き

<img
  class=""
  width="400px"
  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932288/421160d2-dd88-770f-174f-e4b100668d36.png"
  alt="ユーザテスト" />

## 何をもってOKにするか？

* <b>修正時の確認基準</b>
1. シミュレーターの結果とアプリの出力が一致していること。
2. コンテンツが正確にアプリとシミュレーターに反映されていること。
<img
  class=""
  width="400px"
  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932288/345db276-8866-e4f5-6d4c-a54a75b4b5d6.png"
  alt="大分類" />

## ベータテスト

* <b>対象</b>: 日本全国から抽選で選ばれた150人（社内・社外問わず）。
* <b>実施内容</b>: 主要機能のみ搭載したバージョンでの利用テスト。
  <img
  class=""
  width="400px"
  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932288/1a7f2078-f210-d963-d13b-50f6e4183bea.png"
  alt="ユーザテスト" />
* <b>結果反映</b>:
フィードバックを基に調整を実施。調整後、新たなCSVデータを生成し、期待する結果が得られることを確認。
<img
  class=""
  width="400px"
  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932288/271844c4-caf2-3542-43e9-849881de6b87.png"
  alt="ユーザテスト後" />

## 最後に

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932288/b83c4716-b5d0-1fd8-5e3e-183a96f77c38.png)

テストがなぜ大事なのか？
=> 開発者自らの時間を守るため