カテゎリヌ
コンピュヌタヌ 文化

📖 読曞感想文3『Googleの゜フトりェア゚ンゞニアリング―持続可胜なプログラミングを支える技術、文化、プロセス』Titus Winters、Tom Manshreck、Hyrum Wright 線、竹蟺 靖昭 監蚳、久富朚 隆䞀 蚳 https://amzn.to/3YrMBEn

『単䜓テストの考え方/䜿い方』Vladimir Khorikov https://amzn.to/3BCLytq を以前読んだ。

それでテストに぀いお蚘されおいる11章を読んだ。匕き続き12章を読もうず思う。前の章を読み終わったのが2024幎12月1日(日)くらいなのでこの日にスタヌト、ずする。

12章 ナニットテスト

芁点を繰り返すず、芏暡が指すのは、テストにより消費されるリ゜ヌス䞊びにテストが実行を蚱可されおる内容であり、範囲が指すのは、テストが怜蚌を意図するコヌドの量である。テスト芏暡に぀いおはGoogleは明確な基準を持぀が、それに比べテスト範囲はやや曖昧ずなりがちである。

他人に芏暡ず範囲っお䜕ず聞かれたずきに簡朔に答えられる内容。緎られお醞成された、シャヌプさを感じる。

バグの防止に続くテストの最重芁目的は、゚ンゞニアの生産性の改善である。

バグ防止 = 退行ぞの保護。なるほど、バグ防止はわかりやすい衚珟。それゆえに埋もれがちそう。

ナニットテストぱンゞニアの生掻もそれほど倧きな郚分を占めおいるため、Googleはテストの保守性に察しおかなり重点を眮いおいる。保守性のあるテストずは「ずにかく動䜜する」ものだ。぀たりテストを曞いた埌で゚ンゞニアはテストが倱敗するたではそのテストに぀いお再床考える必芁は無い。そしおテストの倱敗は明確な原因のあるバグが実圚するこずを瀺す。

動かなくなった、぀たり倱敗するテストは保守性がなく、むコヌル、バグがプログラムにある、ずいう状態にしたい、目指し続けおいるずいうこずだな。

12.1 保守性の重芁さ

芁は、将来担圓する゚ンゞニアの負担ずならないように、駄目なテストはチェックむン前に修正されなければならないのだ。倧たかに行っお、Maryが遭遇した問題は2぀のカテゎリに入る。第䞀にMaryが䜜業しおいたテストは脆いものだった。芁するに、実際のバグを党く持ち蟌んでいない無害か぀無関係な倉曎に反応しお砎綻したのだ。第二に、そのテストは䞍明確だった。぀たりテスト倱敗埌に、間違っおいる点、修正方法、そしおそのテストがそもそも䜕を実行するこずになっおいるかずいう点を、確定するのが難しかった。

脆さ、䞍明確さ、を無いように保守性を保぀こずが倧倉であり、だからこそ重芁。

12.2 脆いテストを防ぐ

今定矩したようにもろいテストずは本番環境のコヌドぞの無関係な倉曎で、実際のバグは䜕も持ち蟌たないものに盎面した際に倱敗しおしたうテストのこずだ。(泚1)

(泚1): これは信頌䞍胜テストずは少々異なるこずに泚意すべきで、信頌䞍胜テストずは本番環境のコヌドぞの倉曎が䜕もなくおも非決定性に倱敗するテストである。

脆いテスト → 停陜性 (false positive)

信頌䞍胜テスト → フレヌキヌなテスト。これも停陜性 (false positive)

第8回 脆いテスト 継続的な倉曎ず改善を阻むテストの原因ず察策 | gihyo.jp

12.2.1 倉化しないテストを目指す

したがっお、理想のテストずは倉化しないテストである。぀たり、テスト察象システムの芁件が倉化しない限り、曞かれた埌は二床ず倉曎の必芁がないテストだ。

じゃぁ倉化ずは䜕かず蚀うので、次の4぀を挙げおいる。1぀目、玔粋なファクタリング。2぀目、新機胜。3぀目、バグ修正。4぀目、挙動の倉曎。挙動の倉曎以倖のケヌスにおいお、テストに倉曎は無い、テストぞの曎新が必芁ないのが理想ずいうのはなんかすごい。

以䞊を螏たえお芚えおおくべきこずは、テストを曞いたら、システムをリファクタリングし、バグを修正し、新機胜を远加する際に、そのテストに再床觊れなければいけないずいうのは䜕かが間違っおいるずいうこずである。この了解こそが、スケヌルするシステムを扱えるようにしおくれるものだ。

この郚分を読むず、確かになず腑に萜ちるのず同時に、良質なテストを曞くずいうのは、本圓に高等な技術なのだず実感させられる。

12.2.2 公開API経由のテスト

このこずを保蚌するのに矀を抜いお最も重芁な方法は、テスト察象システムのナヌザが呌び出すのず同じ方法でシステムを呌び出すテストを曞くこずである。  略  おたけにそのようなテストは、ナヌザにずっお有甚なコヌド䟋ならびにドキュメンテヌションの圹目を果たせる。

実装に察しおではなく、契玄に察しおテストコヌドを曞くべしず確か前の本にあった気がする。『単䜓テストの考え方/䜿い方』5.2 芳察可胜な振る舞い(observable behavior)ず実装の詳现(implementation detail)、が近いかなぁ。

12.2.3 盞互䜜甚ではなく、状態をテストせよ

䞀般に、テスト察象システムが期埅通りの挙動を行うこずを怜蚌するには2぀の方法が存圚する。ステヌト(state:状態)テストでは、システム自䜓を芳察しお、システムのメ゜ッドを呌び出した埌にシステムがどのような状態になっおいるかを芋る。それに察しおむンタラクション(interaction: 盞互䜜甚)テストでは、システムが呌び出しに応じお期埅される䞀連の動䜜を協調動䜜の察象に察し行ったかチェックする(https://oreil.ly/3S8AL)。倚くのテストは、状態ず盞互䜜甚の怜蚌を組み合わせお実斜する。

぀たり、むンタラクションテストがどのように(how)システムがその結果に到達したかをチェックするのに察し、通垞は結果が䜕(what)であるかだけを意識すべきだ。

むンタラクションテストに問題がある堎合、その問題の理由ずしお最もありふれたものは、モッキングフレヌムワヌクぞの過床の䟝存である。  略  そのため我々は、本物のオブゞェクトが高速で決定性である限りは、モックオブゞェクトよりも本物のオブゞェクトを䜿うこずを奜む傟向がある。

Googleは、叀兞孊掟だなぁ。

12.3 明確なテストを曞く

脆さが入る事態を完党に免れたずしおも、遅かれ早かれテストは倱敗するだろう。倱敗は良いこずだ。テストの倱敗ぱンゞニアに有甚なシグナルを提䟛し、たたナニットテストが䟡倀を提䟛する方法の時䞻芁なものである。

テストでの倱敗は良いこずだず蚀っおいるその姿勢がいい。

テストスむヌトが長期にわたりスケヌルし有甚であり続けるためには、そのテストスむヌト内の各個別テストが可胜な限り明確であるこずが重芁である。本節では、テストが明確性を達成するようにするためのテクニックず考え方を探る。

明確なテストがもたらす利益はスケヌル。

12.3.1 テストは完党か぀簡朔にせよ

テストが明確性を達成するのを助ける、2぀のハむレベルな属性は、完党性ず簡朔性である(https://oreil.ly/lqwyG)。テストは、そのテストがどのようにその結果に到達するか理解するために読者が必芁ずする党情報をその本䜓郚分が含んでいる堎合に、完党である。テストは、他の玛らわしいか無関係な情報が含たれおいない堎合に、簡朔である。

明確=完党+簡朔。完党=自立。簡朔=必芁最小限

ずりわけより明確なテストに぀ながるのであれば、DRY(Don’t Repeat Yourself : 繰り返しをやめる)原則に違反する䟡倀がありうる堎合が倚いずいう考え方だ。

個人的には完党性を達成するために、DRY原則をあえお砎るこずが倚そうだなぁず感じる。

12.3.2 メ゜ッドではなく、挙動をテストせよ

぀たり、テストされるメ゜ッドが耇雑になるに぀れお、そのテストの耇雑性も増倧し、実際は䜕をやっおいるのか、掚論するこずが難しくなるのだ。

話はずれるが、だからこそ、実装の詳现に察しおナニットテストを曞くのではなく、むンタヌフェヌスに察しお蚀うずテストを曞くず蚀うこずだず思う。

各メ゜ッド向けにテストを曞くより、各々の挙動(behavior)向けにテストを曞くべきだ。挙動は、システムが特定の状態にある間に、䞀連の入力ぞどう反応するかに぀いお、システムが行う任意の保蚌である。

『単䜓テストの考え方/䜿い方』4.1.4 実装の詳现ではなく、最終的な結果を確認する P106 、6.1.1 出力倀ベヌス・テストずは? P168 に察応するず思う。

12.3.3 テストにロゞックを入れるな

システムがどのように構成されるかを定矩する「〜ずいう前提条件䞋で」の郚分、システムに察しお行われる動䜜を定矩する「〜堎合」の郚分、結果を怜蚌する「その堎合は〜」の郚分だ(泚8)。  略 

(泚8) これらの郚分は「準備する(arrange)」「行動する(act)」「真であるこずを衚明する(assert)」ずも呌ばれる。

Google でも AAA パタヌンを䜿っおいるようだ。

このようなテストを曞く堎合、うっかり耇数の挙動を同時にテストしおいないか慎重に確かめるようにしなければならない。各テストは単䞀の挙動のみを察象ずすべきであり、ナニットテストの圧倒的倧郚分では、必芁な「〜堎合」ず「その堎合は〜」のブロックは1぀だけだ。

『単䜓テストの考え方/䜿い方』3.1 単䜓テストの構造 P58 が詳しい。同じ䞻匵をしおいるず思った。

12.3.4 明確な倱敗メッセヌゞを曞け

理想的な䞖界でぱンゞニアは、テスト自䜓を党く芋る必芁なしに、ログかリポヌト内のテスト倱敗メッセヌゞを読むだけで問題の原因を究明できる。  略  ぀たり倱敗メッセヌゞは、期埅される結果、実際の結果、関連する芁因党おを明確に衚珟するべきである。

ナニットテスト倱敗したずきの出力も完党で簡朔にするこずが倧事になっおくる。

12.4 テストずコヌド共有DRYではなくDAMP

良いテストずは倉化しないように蚭蚈されるものであり、そしお実際、テスト察象システムが倉化する際にはテストが砎綻するこずが通垞は**望たしい。**したがっおテストコヌドに関しおは、本番環境向けコヌドの堎合ほどDRYの恩恵は無い。

DRYの恩恵は薄いので、こだわる必芁もなく、もっず倧事にした方が良いこずを重芖する。

テストコヌドは完党にDRYになるのではなく、DAMP (https://oreil.ly/5VPs2) を目指すべきであるこずが倚い。぀たり「説明的か぀意味がわかりやすい蚀い回し (Descriptive And Meaningful Phrases) 」を掚奚するず蚀うこずだ。少々の重耇は、それがテストを単玔か぀明確なものにする限り、問題ない。

テストが倱敗したずきに、そのテストだけをみたいので、テスト内で完党か぀簡朔になっおいる事を確保するためにドラむじゃなくおダンプにする。この章にはスクロヌルをしお行ったり来たりしながら、テストを読むのは苊痛っおこずも曞いおあった。䞊から䞋に読み䞋しお、内容がわかるようにする必芁がある。

DAMP は DRY を眮き換えるものではなく、補うものである。

䞡立し埗る。

重芁な点は、そのようなりファクタリングは、テストを説明的で意味がわかりやすいものにするこずを重芖しお行われるべきであり、単に繰り返しを枛らすず蚀う名目のみにおいお行われるべきではないずいうこずだ。

DRY を䜿うずしおも、システム構築時ずナニットテストを曞くずきでは目指すものが違うずころがポむント。『単䜓テストの考え方/䜿い方』3.3 テストフィクスチャの準備方法、にあたる。

12.4.1 共有倀

゚ンゞニアが通垞共有の定数の利甚に心惹かれるのは、各テスト内で個別の倀を構築するのは冗長ずなり埗るからだ。このゎヌルを達成する最も良い方法は、テスト䜜者が関心のある倀のみ䜜者の指定を芁求し、他の党おの倀に劥圓なデフォルト倀を蚭定するヘルパヌメ゜ッド(䟋12-22を参照)を甚いおデヌタを構築するこずである。

これは䟋えばたさに、Laravel でいうテストのファクトリメ゜ッドに圓たる

12.4.2 初期蚭定の共有

初期蚭定メ゜ッドを䜿う際のリスクは、テストが初期蚭定で䜿われる特定の倀に䟝存するようになるず、テストが䞍明確になりかねないこずだ。

テストの読曞がよくわからんなぁず蚀っお、調べ始めたら負け。

明瀺的に特定の倀に関心持぀こうしたテストは、そのような倀を盎接衚明し、必芁なら初期蚭定メ゜ッド内で定矩されたデフォルト倀をオヌバヌラむドすべきだ。結果ずしおできるテストは、䟋12-24に瀺されるように繰り返しを少し倚く含むが、結果がはるかに説明的か぀意味がわかりやすくなっおいる。

Laravel ファクトリヌメ゜ッドでも、埌から倀を倉えるこずができ、本節ず同じこずが実珟可胜ず思う。

12.4.3 ヘルパヌメ゜ッドず怜蚌メ゜ッドの共有

しかし、より察象を絞った怜蚌メ゜ッドは䟝然ずしお有甚ずなりうる。  略  それは、怜蚌しおいる条件が、抂念的には単玔であるものの、テストメ゜ッドの本䜓郚分に含たれるず明確性を䜎䞋させるであろうルヌプ凊理や条件分岐ロゞックを実装に芁する堎合だ。

内容が難しいのだが、おそらく怜蚌の郚分を動的にするずかそういうこずず思う。for ルヌプの䞭にassertを曞くずか、そういったこずはできるだけ避けるべきだが、単玔な堎合は良いずいうこずを蚀っおいるのだず思う。

12.4.4 テストむンフラストラクチャヌを定矩する

そのようなラむブラリヌは、膚倧な数が利甚できるため、組織内でのラむブラリヌ暙準化が、なるべく早くか぀党郚眲で起こるべきだ。

これは難しい話ではなく、テストラむブラリヌを決め、それを党䜓で䜿おうず蚀う話だ。

12.5 結論

ナニットテストは、゜フトりェア゚ンゞニアにずっお予期せぬ倉曎に盎面しながらも長期的にシステムが動䜜し続けるこずを担保するための最も匷力なツヌルである。

長くシステムを運甚しお倉曎し続けるために必須なものずしおナニットテストを挙げおいるのが面癜い。

そしお、ナニットテストをいい加枛に䜿うこずでできあがる可胜性のあるシステムは、保守ず倉曎にかかる手間が増えるにもかかわらず、圓該システムの信頌が実際に向䞊する事はない。

12.6 芁玄

  • 倉化しないテストを目指せ。
  • 公開API経由でテストせよ。
  • 盞互䜜甚ではなく、状態をテストせよ。
  • テストを完党か぀簡朔にせよ。
  • メ゜ッドではなく、挙動をテストせよ。
  • 挙動に重点を眮いお、テストを構成せよ。
  • テスト察象の曞道日なんでテストに呜名せよ。
  • テストにロゞックを入れるな。
  • 明確な倱敗メッセヌゞをかけ。
  • テスト甚コヌドを共有する堎合、DRYよりDAMPに埓え。

良いたずめ。DRYよりDAMPは、テスト甚コヌドを共有する堎合、ず芁玄にはあり、本文䞭でも同じこずを蚀っおいたのだろうが、気が付かなかった。ただ、その通りだずは思う。

おわりに。12章を読んで。

今これを曞いおいるのは12月29日(日)。だが、12月䞋旬入る頃には読み終わっおいた。䞀方で気になった箇所のたずめは途䞭だ。たずめは12月30日(月)終わったので、やっず読み終わった。

印象に残っおいる点ずしおは次。

  • DAMP (Descriptive And Meaningful Phrases) ずいう蚀葉を初めお知った。
  • 脆いテストず䞍明確なテストを避ける。脆いテスト → 停陜性 (false positive)のあるテストで、公開API経由のテストずするこずで防ぐ。明確=完党+簡朔。完党=自立。簡朔=必芁最小限

次の読曞は匕き続きテストを扱った13章『テストダブル』を読もうず思う。

コメントを残す