🔍

「Nextbeat Tech Bar:第一回ソフトウェアテストについて考える会」レポ

2024/03/22に公開

自動テスト実行結果の目的を整理する by @t_wada

https://speakerdeck.com/twada/organizing-objectives-of-automated-test-results

ひとこと要約

https://x.com/tomohisa/status/1771118045379060076

自動テストの信頼性とは

自動テストの成功も失敗も信じられること
成功していれば正しい、失敗していれば誤っていると確信できる

しかし自動テストは嘘をつくことが稀によくある

今日は偽陽性と偽陰性の話ではないので詳細は割愛
信頼性が高いなら何をするかが今日の話題

意思決定と行動を促す「情報」としてのテスト結果

テストの実行結果は「情報」である
情報→意思決定と行動を促すもの
テストの実行結果が促す行動:デプロイ、マージ、コードの修正

信頼性が低いテストは判断を鈍らせる

自動テストの出力にはいくつかの役割がある

  1. 信号機

全件成功した→次の行動に移れる
人間には緑と赤、機械には0と1で表示

  1. 欠陥の絞り込み

Execution Error: テスト実行中にプロダクトコードから発生する実行時エラー
Assertion Failure: テストコードの中に書いたアサーションの失敗
問題箇所の特定のために区別するとよい

  1. ドキュメント

動作する詳細設計書、仕様書

  1. データ

データとして蓄積して将来の意思決定や行動を促すこともできる
テストの不安定さなどの解析に使える

情報量のコントロール

テスト名と構造は基本

問題の絞り込みやすさのためにテストサイズやテストスコープを小さくしたり適切なマッチャを使う
 Assertion failureの情報を使うにはきちんと適したマッチャを使わないといけない

テストサイズの概念 cf Googleのソフトウェアエンジニアリング
範囲による分類(単体、結合、E2E)は人によって定義がバラバラになりやすい
テストサイズのSMLによる分類
S テストの実行が1つのプロセスに閉じている
M テストの実行が1つのマシンに閉じている CIに乗せやすい
L 1つのマシンに閉じていない

偽陽性のよくある原因がネットワークアクセス
小さくなるほど安定して決定的な動きをする
テストサイズとテスト範囲でマトリクスができ、マスごとに位置付けが異なる
左下ほどコスパが良い
https://x.com/nihonbuson/status/1771120950219800970

UnitなんだけどDBにアクセスせざるを得ないこともある

本邦初公開の表

https://x.com/nihonbuson/status/1771121273256726973

上から順に想定するシーン
手元でさっと回して開発継続を判断するTDDのワンシーン
開発がどのくらい進んでるか、テスト項目の抜け漏れといったレビューのため
PRの分のテストが成功したらメインラインにマージできる
全範囲のテストが成功したら本番環境にデプロイできる
何件のテストがどれくらいの速度で回っていてカバレッジはどれくらいというのを定時で回しておいてレポートにする

「コンパイル時のユニットテスト」を導入するとユニットテストを書かなくてもいいというのは本当なのか?(リモート発表) by @tomohisa

https://speakerdeck.com/tomohisa/konpairushi-noyunitutotesuto-dao-ru-surutoyunitutotesutowo-shu-kanakuteyokunarunoka

ひとこと要約

コンパイル時のユニットテストとは、オブジェクトの状態遷移を別の型で表現することにより入力に関する場合分けのテストを減らすこと

どこからきた、どんな概念なのか

Scott Wlaschin "Domain Modeling Made Functional"

https://www.youtube.com/watch?v=2JB1_e5wZmU
オブジェクトの状態遷移を別の型として定義する
各機能は特定のオブジェクトの状態でないと実行できないことにする
メールアドレスを表現する型をVerifiedEmailifiedEmail | UnverifiedEmailifiedEmail
フラグをチェックするのではなく型を分けることでユニットテストが不要になる
これをコンパイル時のユニットテストという

どのような書き方なのか

データの作成
検証済みでも未検証でも使えるオブジェクトを作るのではなく
検証成功した時はVerifiedEmail失敗した時はUnverifiedEmail
検証成功していなければVerifiedEmailという型が生まれない
パスワードリセットメール送信
ResetEmailの入力でVerifiedEmailのみ受け付けるようにすることでフラグチェックが不要になる

テストがどう変わるのか

一般的にはフラグごとにテストケースを書く
コンパイル時のユニットテストではResetEmailの中にUnverifiedEmailを入れようとするとコンパイルエラーになる→入力に関するテストを書く必要がない!

https://x.com/tomohisa/status/1771128615176204449

フラグや状態が増えたときにシンプルな書き方が効いてくる
全体としてどう振る舞うかのテストはまだ必要
フラグを持たないことによる型の自己文書化と型が増えることによる複雑化のトレードオフがある

原著者はフラグのチェックやテストの個数を減らすことのメリットを強調していたがこんな声も
https://x.com/ratmie1/status/1771125668337873255

Union型があるとパターンマッチングで網羅性、完全性をコンパイルでチェックできるので便利

https://x.com/uechang16/status/1771125844402176303

関数型にすることで色々なところの影響が減って1つ1つの処理に集中できるというところもある

BDD(Cucumber)コミュニティが無料提供しているコンテンツの紹介と現在起きている危機 by @nihonbuson

https://speakerdeck.com/nihonbuson/bdd

"The BDD Book: Discovery"に沿った話

ひとこと要約

CucumberコミュニティはBDDについてたくさんの有益な情報を発信してくれているが、現在ピンチ

cucumberとは

BDDをサポートするツール
プレーンテキストで書かれた仕様を読み取り、実行できる形にする
自然言語で書いているので開発に詳しくない人とも認識を合わせられる
BDDが人々にテストだと誤解されている

コミュニティがBDDについて色々発信している

BDDとは

ユーザーストーリーからコードの自動テストまでの隔たりを埋めるもの
最初はDiscoveryから始める
テスト自動化の改善は下流の成果
発見、定式化、自動化という順番がある
ビジネスチームと協調しない開発アプローチはBDDに従っていない!
https://x.com/tomohisa/status/1771130822206333371
https://x.com/gennei/status/1771129462899474943

cucumber schoolが提供する資料

動画ではスムーズに発見が進んだけど、実際にはなかなか人を集めても意見が出てこないという声も
https://x.com/ratmie1/status/1771130454596616486
実例マッピングなどで具体的な例を出すことを重視している
具体例がうまく思い浮かばない→ユーザーストーリーから営業のチラシやヘルプドキュメントを書こうとしてみる

  • 定式化
    BRIEFの原則Gherkin記法で書かれたテストシナリオを整理するための原則
    テストシナリオが長くなると何を知りたかったのかわからなくなる

https://x.com/nihonbuson/status/1771131118026445146

画面の表示ロジックへの自動テストで悩んだ話(リモート発表) by @yuuabsoft

コンテンツの表示ロジックが重要なプロダクト
 表示ロジックの自動テストを導入したい

APIテストやユーザの操作を元にして実施するテストに比べて
コンテンツが多い
ページ内のロジックの分岐が多い

  • VRT
    コンポーネントの部品ではなくページ全体に対して画像として比較することでロジックのテストができないか
    導入保守コストが低い
    細かい分岐やユーザの操作を伴うようなロジック
    検証の粒度が荒くなる
    takepepeさんのフロントエンドテスト本の8章9節みたいな話?

  • リアーキ
    表示ロジックがviewによっているのでmodelに寄せる
    コストは小さくなる
    model肥大化の懸念
    表示ロジックのテストのためだけにリアーキはコスト重い
    PJ立ち上げ時からやっておく必要があった

  • 自動テストしない
    グロースハックABテストしている
    表示ロジックが高頻度で変わっていく
    自動テストを作成しても保守コストが増えるだけでメリットが薄いのでは
    他のところで担保する必要がある
    保守コスト考えるの大事

技術スタック、アーキテクチャ、ビジネス特性の理解がないとテスト戦略を適切に組めない

理想のテスト像を業務のコードに適用できずに悩んでいる話 by @verdy_266

テストの理想像ができた
全ての単体テストと落ちたらまずいページの統合テストを書く
factoriesはシンプルに
 テーブルのレコードはテストのたびに生成する
WETに書く

業務のコードで理想のテストがしづらい
どのページは落ちたら困るのかの合意が取れていない
複雑なtraitが剥がせない

各画面の重要な仕様がどこなのか?

問題になっていないならテストは増やさなくてもいいのかも?
 Rubyのバージョンアップの時に全部動作確認するのはつらい

Testcontainersが便利だった by @takapi327

開発中のOSSで使っているMySQLの認証で役立った
認証プラグインが色々使える
キャッシュの有無によるテストが必要
サーバーとクライアントの認証プラグインが違う場合を想定する必要がある
さらにMySQLの2つのバージョンに対応する
それぞれ綺麗な環境を用意したいがdocker-composeでは大変
TestContainersが便利
コンテナの情報を定義してそのコンテナを使った環境でテストできるようになる
設定がテストコードと一緒に管理できる

複雑なドメインを扱うプロダクトの探索フェーズではいつどのようにテストをするのか by @boykush315

https://speakerdeck.com/boykush/how-to-testing-during-exploratory-phase

クリーンアーキテクチャ、モジュラモノリスを前提に

探索フェーズのプロジェクト
複雑なドメインの新規コンテキストに参入する場面でのこと

  1. ドメインモデル仮実装
    書いては捨ててだったのでテストは書かない
  2. ユースケース駆動実装
    ユースケースが依存するコンポーネント群をIFのみ
    テストは書かない
  3. ドメインロジックを書く
    がっつり単体テスト
  4. 外部通信層
    統合テスト
    探索の中でIFの変動が少ない部分なのでここでレッドグリーンの変動を支える

探索中盤で手戻りが発生した場合テストを捨てるのか
ignoreでスキップすることで将来的な再利用のためにおいておける

そもそも探索の手戻りを減らすには
実例マッピングなどをやる
https://x.com/nihonbuson/status/1771142679470260399

GitHubで編集を提案

Discussion