📝

ジワジワとテスト自動化を進めて技術的負債に立ち向かった話

2023/05/14に公開

LTで使用したスライドです

前提

プロダクト:サブスク契約をよしなに管理するWebアプリケーション

開発関連の状況

・主要なユースケースで考慮すべきパターンが膨大で整理されていない
・主要なユースケースに関連する機能群(注文・契約・請求等)のデータ依存関係が整理されていない
・コードが技術的負債の塊

テスト関連の状況

・E2Eテストのみを手動で実施(基本は開発担当、手が足りなければ他のチームメンバーがテスターとして援護)
・Autifyが導入されていたが効果薄
・ユニット、コンポーネント単位でのテストは行われていない(自動化も困難)

課題

主要なユースケースのバックエンドロジックの変更・改修の設計段階で考慮漏れが発生しやすく、触ると大抵意図していない影響が出る。当然テスト設計でも考慮されずにスルーされ、リリース後バグが多発。
ユースケースやデータの依存関係を開発チームとして整理することはせず(機能担当者頼み)、テストの網羅率を上げる形で対応。しかし開発者がテストを行う為、テスト工数が増えれば開発工数が圧迫され、さらなるバグを生むという負の連鎖が発生していた。

やったこと(スライドの目次)と背景

Step1 手順を自動化
Step2 確認する値をデータで出力
Step3 確認する値の突合
Step4 テストシナリオのフォーマット化・自動化
Step5 リグレッションテスト自動化

ワイ「結合テスト手動なんキツイな。重いとこだけでもちまちま自動化しとこ」(スライドのStep1~3)

メンバーA「ここの改修テスト工数がヤベぇ!」
ワイ「そこツールで消化できるからこっちでやるで~」
メンバーB「すまんこっちも頼むわ」
メンバーC「よろ」
ワイ「差分は検出できるけど想定の値か問い合わせるのメンドイな......」
ワイ「項目表からシナリオ生成できるようにしといたから、各々で自動テスト回して確認して!」(Step4)

Q

リーダー「テストツール良さそうやからリグレッションテストとしてリリース判定に組み込むで」
ワイ「毎回やるには(項目数)デカすぎる......運用チームにお客さんの使用状況見てテスト実行対象絞ろ」(Step5)

リグレッションテストツールについて

リグレッションテストツールというよりはユースケースへの影響範囲可視化ツールと呼ぶほうが良いかもしれない。
今回のテスト自動化対象機能にはドキュメントがないため、アサーションを書くには期待値も調査に膨大な工数がかかり、かつその期待値が現状のプロダクトの仕様通り動いているかが怪しい。また、ドキュメントを作成しても、整備が追いつかないこと間違いなし。何より2000項目を超えるユースケースのドキュメントを読んで正確に製造設計・テスト設計するのは人間には不可能だろうと考えていた。

なので、本ツールではシナリオ実行時に動作毎にデータスナップショット(関連するDBレコードデータ)を出力するツールを作成、現行プロダクトの動作を正として、コミットしたブランチとデータスナップショットを突合し、製造担当が差分チェックを行うことでリグレッションが発生していないことを担保する形を取った。

入力

・ブランチ名×2 (テスト実行したいfeatureブランチと元ブランチ)
・テスト用のダンプデータ
・シナリオファイル

出力(差分確認)

例えばTest0001[注文登録]->[契約開始]->[日付変更してデイリーバッチ実行] といった動作を再現するシナリオを実行する場合、v1、v2ブランチでそれぞれ環境構築し、それぞれでシナリオ実行する。
実行後、データ差分を検出した場合はv1,v2の2つのディレクトリが出力されているので、これらを何かしらのdiffツールにかける(ここではWinMaergeを使用)と以下のように確認できる。

ツールは内部的にActionNoが割り振られていて、Action毎に関連するデータをレコードを出力している。ファイル名でテストNoと3番目のAction実行時に取得したデータに差分があることが分かるので、v2のコミットで[日付変更してデイリーバッチ実行]の実行に影響があったことが分かる。

注意した点

ツールの信頼性

ツールによるバグはもちろん、ツール実行による自動実行と手動によって結果に違いがないかは定期的に確認。特にチーム内で正式に導入されるまでは、自身のテスト範囲で手動テストをやりつつ、自動テストでも同様の結果が得られるかを確認することでツールの信頼性を担保していた。

偽陰性についてチームに展開

ツールの特性上、差分が出るべきだが出ない場合、つまり偽陰性の検出は難しい。これは割とどうしようもなかったので、エンジニアには 「差分のチェックだけでなく、変更・改修内容から重要な項目はある程度めぼしをつけて、差分の有無をチェックしてほしい」 と展開しつつ、自分からも重要なチケットは設計やコードレビューに参加して、めぼしをつけて確認をしていた。

使わなかったE2Eテストツール

Autify,selenium,seleniumIDEも検討したが没。詳細は以下の記事にまとめた。
https://zenn.dev/ikeda1151/articles/cd9e7101a40d89

所感

1. 誰が使うかを意識して自動化するのが大事

最初はbashとかpythonスクリプトに直接シナリオ書いてたけれど、やはり理想は「製造した人がその機能を担保する」なので、いずれは自分以外が使うことを想定して作るのがよいと思う。

2. 半端なツールは展開しないほうが良い

とはいえ他の人に展開する前提でいきなりツール作り始めるのはハードルが高い。
今回作ったテストツールを他メンバーに展開する際には少なくとも以下の情報を正確に伝える必要があった。

・使用できる条件(環境やバージョン等)
・対応範囲(実行可能なシナリオ)
・実行手順
・出力(何が実行、確認、担保できるか。OK/NG、差分、スナップショット等)

他のメンバーに 「そのテスト、ツールで確認できるよ!はい手順書!」 と言っても、まず 「ちょっとよくわからない……」 となり、対面や通話しながら解説する工数が発生する。
さらにツールに未完成部分がある場合は手順書に
\textcolor{red}{※条件〇〇の場合は使用できません!}
とか

とか目立つように記載することになる。そして大体読み飛ばされて問い合わせ→調査コース
「こんなことなら未完成部分作ってから展開すればよかった!」 と後悔することが多かった。

3. 開発チームの認知負荷を下げる経験を得られた

シナリオを生成する組み合わせ表は最終的に因子が十数個、それぞれ水準が2~5個あり、仕様として発生しない項目を差し引いても2000項目程度に膨れ上がったが、これを観点や因子で無理に分けずスプレッドシートで2000行ひとまとめでユースケースリストとして管理していた。
一見すると組み合わせ表は見ずらいものだが、そのシートで主要機能で担保すべき動作が揃っている安心感や、実行したいシナリオを選択してワンクリックでシナリオ出力できるようにしていたこともあって、次第に開発者が 「ソースのここ直したらNoXX〜YYに影響あるな」 と見込みを付けれるようになってゆき、さらにはコードレビュー前にテスト実行しておいてで 「影響ありそうなNoXX~YYは確認済みです」 とレビュアーに対する意思疎通が捗った。
理想は 「人間の認知限界を超えるような仕様、設計はしない」 なのだろうけれど、IT業界で働く以上は技術的負債と向き合い続けなければならないので、対策を一つ得られたのはとても良い経験だった。

Discussion