天の月

ソフトウェア開発をしていく上での悩み, 考えたこと, 学びを書いてきます(たまに関係ない雑記も)

Qiita Conference2023のセッションまとめ〜サバンナ便り - 自動テストに関する連載で得られた知見のまとめ(2023年5月版)〜

※予約投稿が効いていなかったので、再度の投稿になります。

increments.connpass.com

こちらのイベントで、基調講演である「サバンナ便り - 自動テストに関する連載で得られた知見のまとめ(2023年5月版)」を聞いてきたので、会の様子と感想を書いていこうと思います。

学習用テスト

まず、学んだことを自動テストとして書いていく学習用テストの話がありました。

あの時調べたことが今でも正しいのか?というのを担保することができるため、他の人が書いたコードやふるまいが不明なテストに対して活用することが多いということです。
学習目的で使用するテストのため、不要になる場合も多く、@learningなどといった何かしらのタグで管理しておくと便利だということでした。*1

また、驚きをテストすることにも有効であるため、例えばPHPでコンストラクタをもう一度呼ぶことでイミュータブルなクラスに破壊的変更を起こして、それをテストに落としておくことも有効だということでした。

こういった学習用テストは、バグレポートとして報告したりすることもできるため、Issueをたてるときにも

偽陽性偽陰性

自動テストの信頼性の高さ*2は企業の業績にも直結しているということで、自動テストの誤検知の話として、偽陽性*3偽陰性*4の話がありました。
このうち特に、テスト対策ロジックのテストコードへの漏れ出しはt_wadaさんが色々な現場で見ているそうです。

偽陽性偽陰性は、プロダクトコードとテスト結果の関係性から、

  • テスト結果が成功×プロダクトコードが正しい...期待値通り
  • テスト結果が成功×プロダクトコードが誤っている...偽陰性
  • テスト結果が失敗×プロダクトコードが正しい...偽陽性
  • テスト結果が失敗×プロダクトコードが誤っている...期待値通り

と整理できるということです。

テストサイズ

テストスコープの問題は、DBのテスト/NWアクセステスト/ファイルアクセステストをどこまでやるのか?という話があったり、そもそもUnit testのUnitにも古典派とロンドン学派があったりと、定義や考え方にかなりばらつきがあるため、テストのスコープよりもテストのサイズで考えようという話が続いて紹介されました。*5

そのため、テストサイズとテストスコープもパターンごとに整理するのが有効ということで、以下の内容が紹介されていきました。

  • Unit × Small Size...大いに推奨
  • Integration × Small Size...書けるならコスパ良い
  • E2E × Small Size...実質不可能
  • Unit × Midium Size...避けるべきだが仕方がないときもある
  • Integration × Midium Size...普通
  • E2E × Midium Size...小さいシステムなら可能
  • Unit × Large Size...最悪(ただしよく見かける)
  • Integration × Large Size...できれば避けたい
  • E2E × Large Size...普通(CUJにしぼりたい)

テストダブル

続いて、テストダブルの話がありました。

テストダブルもテストスコープと同じように用語の混乱があったそうですが、X Unit test patternsで統一されたということで、今回はこの定義に沿って話が進んでいきました。

テストダブルはテストしにくいものがテスト可能になったりテストの速度と決定性を向上させる一方で、テストが脆くなったりテストの偽陰性を招くリスクがあるため、注意が必要だということでした。

テストピラミッド

最後に、自動テストの信頼性を中長期的に保つためのテストピラミッドの話がありました。
テストピラミッドは、コストが高い速度が遅いE2Eテスト < コストも速度も普通なIntegration test < コストが安く速度が速いUnit testとテスト量を整理しようというアイデアですが、これは個々人がUnit testをどう考えているかによって解釈の混乱が起きがちなので、ここまで説明してきた内容を活用しようというアイデアの紹介がありました。

テストピラミッドのサイズ変更戦略

最後に、テストピラミッドの形に戻していくための戦略に関して話がありました。

まず、Large sizeのテストをMedium sizeのテストに移植する方法ですが、これはFake Objectが有効だということです。

次に、Medium sizeのテストをSmall sizeのテストに移植する方法ですが、これはテストにできるようにテスタブルな設計にしていくことが重要だということでした。

その他(t_wadaさんの失職危機)

単体テストの考え方/使い方」という本の登場、ChatGPTはt_wadaさん的に失職の危機を感じるほど正確だという余談が紹介されていきました。

全体を通した感想

基本的には先日Forkwellさんであった講演と同じような内容だったので、二度目の講演を聞いていくような感覚でしたが、それでも十分に楽しかったです。

最後のテストピラミッドに近づけていくような戦略に関しては、今回が初めてだったので、次回の連載(一旦最終回となる予定)にもつながってくる話なのかな?と思いながら聞いていました。

*1:詳細な内容はPHPカンファレンスで書いたDateTimeとDateTimeImmutableの違いを参照

*2:Googleのソフトウェアエンジニアリングによれば、信頼不能性が1%に接近すると価値を失い始める

*3:Flaky test、脆いテスト

*4:空振り、カバレッジ不足、テスト対策ロジックのテストコードへの漏れ出し

*5:Googleのソフトウェアエンジニアリングに乗っているアイデア。t_wadaさんが支援している現場でも単体テストとUnit testが違うという現場が非常に多い