2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
リンクをコピー
記事をブックマーク
和田卓人氏:次に、テストサイズという考え方にいきます。自動テストにも「〇〇テスト」というやつがいろいろあるんですよね。
特に我々ソフトウェアエンジニアにとって馴染み深い名前はユニットテストとか、単体テストとか、インテグレーションテストとか、システムテストとか、エンドツーエンドテストとか。「〇〇テスト」というやつがいろいろあります。それらの分類基準は、実は言うほど明解ではないんですね。
ということで、ちょっと講演で時間差があるのでリアルタイムに決を採ることはしないんですが、ここでみなさんに質問です。ユニットテストとは何か。これが人によっていろいろ違ったりするんですよね。
チャットでもバンバン答えてもらえればと思うんですけど。ちなみに、データベースにアクセスするのはユニットテストですか? あなたはどう思いますか?
データベースにアクセスするのはユニットテストである、Yes/No。ネットワークにアクセスするのは? Yes/No。ファイルにアクセスするのはユニットテストでしょうか、Yes/No。じゃあ現在時刻にアクセスするのはユニットテストでしょうか、Yes/No。依存先のクラスに本物を使うのはユニットテストでしょうか。
あるクラスAのインスタンスのテストをしているとします。AがBとかCのクラスのインスタンスに依存しているとします。BとかCに本物を使うテスト、あるいはモックオブジェクトとかで置き換えたテスト。ユニットテストはどちらでしょうかという(質問をする)のも変な話ですが、本物を使うのもユニットテストですか?
今Zoomのチャット欄がバーッと流れています。「Yes」とか「No」とかがいっぱいありますね。そうなんですよ。なにが言いたいかというと、人によって解釈がブレブレなんです。「ユニットテストと単体テストというものは同じものを指しますか?」というと、人によって違ったりするんですよね。僕は技術書籍の翻訳とかもやるんですが、「Unit test」を「単体テスト」と訳すのは避けるようにしているんです。“ユニットテスト”と訳しているんです。
なんでかというと、企業によってユニットテストと単体テストは違うものを指していたりするからなんですよね。というぐらい、実はブレブレなんです。
自動テストの分野において大きく分かれるところの分水嶺の1つが、先ほどの5番目の質問、「依存先のクラスに本物を使う? 使わない?」というところで。実はスタイルが大きく分かれます。5問質問した最後のやつですね。
(スライドを示して)真ん中の点線で囲まれているところがテスト対象のクラスだとします。テスト対象のクラスが、別のクラスのインスタンスに依存しています。何かが横に2つありますね。
「本物を使うのもユニットテストだよ」と言う人もいれば、それはユニットテストじゃなくて、この四角の点線で置き換えているように「テスト対象を独立してテストさせるためにはモックとかスタブとかで置き換えるべきである」というような考え方の人もいます。
実は歴史的にはテスト駆動開発には2つの流派があって。デトロイト学派とロンドン学派というんですけど。デトロイト学派は概ね左側、「メモリ内であれば本物を使ってよし」という考え方をする。右側のSolitary Tests、「テスト対象を独立させてコラボレータ、モックやスタブにしよう」というような考え方がロンドン学派と言われたりします。ということで、ブレブレなんですよ。
ここまでブレブレだと、例えば「ユニットテストの方針はこうする」とかの議論がうまくいきそうでいかないんですよね。ここまでブレブレだと(うまく)いかないんですよ。だから例えば転職したりすると、(その企業で)「〇〇テスト」(という言葉)が指しているものがぜんぜん違ったりしていて。
一種のコントみたいに指しているものが違うみたいな感じになってしまいがちなので、「もっと一貫性のある分類ってなにかないかな」「曖昧さの少ない分類ってないかな」と考えるわけですよね。
そういった時に、これはGoogleから始まったんですが……。具体的には『Googleのソフトウェアエンジニアリング』という本の中で説明されているんですけど。
例えばテストのユニットとか、インテグレーションとか、E2Eテストとかをよく「テストスコープ」と呼んだりするんですが、それに対してスコープじゃなくてテストサイズという考え方で分類する。分類するというより、「そういう分類の軸を設けたほうが曖昧さが少ないんじゃないか」というような考え方が出てきています。
そのことを「テストサイズ」と言います。「サイズ」と言っているから小・中・大とか、スモール・ミディアム・ラージとかがあって。
スモールテストは何かというと、1つのプロセスの中で閉じているテストです。だからプロセス外にアクセスしたらスモールテストではない。例えばデータベースにアクセスしたらスモールテストではない。ネットワークにアクセスしたらスモールテストではない、みたいなかたちです。
ミディアムテストは何かというと、1つのマシンの中に閉じているテストです。1つのマシンの中に閉じているというのは、実はけっこう応用が利いて、最近はDockerのコンテナとかで開発する時代になってきていますよね。Dockerのコンテナを組み合わせれば、1つのマシンの中でデータベースを立ち上げて、ブラウザを立ち上げてテストすることもできるわけですよね。なので、ミディアムというのはけっこう応用が利きます。ただ、マシンの中で閉じている。これがミディアムサイズのテスト。
ラージテストというのは、それらの制約がない。プロセスに閉じていないし、マシンにも閉じていないテストその他全部みたいなテストがラージテストという。
曖昧さがえらく少ない分類でやっています。ちなみにGoogleは超大企業なので、ラージの上のエナーマスという超巨大みたいなやつがあるらしいですが、一般の我々にとっては3つのサイズがあれば十分です。
なので、例えばGoogleのAndroidチームの開発においては、スモールテストはネットワークアクセスをしない、データベースアクセスをしない、ファイルシステムもアクセスしないみたいな感じで、(表に)No、No、No……その代わり超高速で動く。
ミディアムテストはどういうテストかというと、ネットワークはlocalhost。マシンに閉じていればアクセスOK、データベースはマシン内で立ち上げればOKみたいな感じなんですよね。
ラージテストはなんでもあり。全部本物にアクセスする代わりにすごく不安定で、すごく遅くなるという感じです。Googleはその外部システムがものすごくいっぱいあるので、たぶん数のレベルで超巨大(なテストサイズ)というものを設けているんでしょうね。
というと、我々が一般に理解しているユニットテスト、インテグレーションテスト、E2Eテスト。「仮にこの3つのスコープを設けるとしましょう」みたいなもの。それとテストサイズ。そのテストの実行が単一プロセスに閉じているのか、単一マシンに閉じているのか、それとも閉じていないのかは、実は3×3の表にできるわけですよね。そうすると、我々が目指したいところとか、大いに推奨するところも見えてくるわけです。
例えばユニットテスト。テストスコープのほうはちょっとフワッとした定義です。テスト範囲が狭い。エンドツーエンドテストは大外から全部をテストするみたいな感じなんですね。これとテストサイズのかけ算にすると、推奨エリアとか避けたいエリアが見えてくるわけです。
単一プロセスに閉じたユニットテスト×スモールテストはいくらでもスケールするので、一番推奨するエリアです。(スライドを示して)よく見ると真ん中に普通のエリアがあるんですね。インテグレーションが単一マシンに閉じた状態でミディアムテストとして動かせるというのは普通のことです。インテグレーションが単一プロセスに収まるものも、小さいシステムならあり得ますよね。書けるならコスパが良いです。
逆にインテグレーションテストが1つのマシンに溢れてしまうのは、できれば避けたい。例えばE2E×ラージ、E2Eテストがラージテストになるのは普通である。ただ、いっぱいあればあるほどどんどん開発が不安定になる。
エンドツーエンドテストとかラージテストというものは、当たり前ですが外部のネットワークにアクセスします。テストの中でflakyさ、不安定さの原因として一番大きいのは、外部ネットワークアクセスなんですよね。ということで、E2E×ラージは本質的にすごく不安定なんですよ。だけど、そこじゃないとテストできないものもありますよね。
それがエンドユーザーのレベルで対象のシステムをテストできるか、使えるかどうかというようなテスト。これはE2Eテストでしかできません。なので、普通かつCUJ(Critical User Journey)に絞りたい。CUJは「クリティカルユーザージャーニー」と言います。日本語で雑に訳すと、ド正常系ということですね。主要動線というやつです。
システムの主要動線に関して、つまり深さ優先のシナリオテストは、エンドツーエンドテストのラージテストじゃないとできないし、意味がないかもしれない。でも、実は「エンドツーエンドテストだけどSeleniumのコンテナとデータベースのコンテナがあれば走るよ」というシステムももちろんあります。
そうしたら、小さいシステムならミディアムでエンドツーエンドテストを動かすほうがコスパが良い。スモールなエンドツーエンドテストは原理上不可能に近いと思いますが、小さいシステムならある程度はある、みたいな。
逆にバッドエリアにいきましょう。ユニットテストなんだけどデータベースにアクセスしているテスト。けっこういっぱいあるんですよね。避けたいんだけど、仕組み上、仕方がない時もあります。
例えばRuby on Railsのモデルのテストとかはユニットテストと言っていますが、データベースがないと動かないものが多いので、実質的にはミディアムテストです。避けたいけど仕組み上、仕方ないというのもありますよね。だからけっこう遅くなってしまう。不安定ではないけど遅くなってしまう。
(スライドを示して)問題は一番右上のエリア。ユニットテストレベルとか、例えば画面のバリデーションのテストとかをラージテストレベルで行ってしまう。外部システムにアクセスし得るようなステージングとか、本番システムとかでやってしまうということもけっこうあるんですよね。
ということで、そういったところを避けたいんですが、例えば画面レベルのテストでエンドツーエンドテストと言っているにもかかわらず、やっているのは網羅的に画面のバリデーションのテストとかだと、実質的にはラージレベルでユニットテストをやっていることになっちゃうんですよね。
こういうのを避けようということで、実はものすごく単純化すると、コスパの良いエリアと悪いエリアがあります。(そうなると)「なるべく投資対効果の高いようにテストを設計していきたいですね」という話になるわけです。
ちなみに「DBアクセスするユニットテストがダメ」と言っているわけではありません。仕組み上避けがたい時もあるし、それによって担保できるものもあります。
(次回につづく)
関連タグ:
2024.12.20
日本の約10倍がん患者が殺到し、病院はキャパオーバー ジャパンハートが描く医療の未来と、カンボジアに新病院を作る理由
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.17
面接で「後輩を指導できなさそう」と思われる人の伝え方 歳を重ねるほど重視される経験の「ノウハウ化」
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05