天の月

ソフトウェア開発をしていく上での悩み, 考えたこと, 学びを書いてきます

「リーダブルなテストコードについて考えよう」に参加してきた

veriserve-event.connpass.com

こちらのイベントに参加してきたので、会の様子と感想を書いていこうと思います。

会の概要

以下、connpassのイベントページから引用です。

読みやすいテストコードは自動テストを長期で運用するために重要な技術の1つです。

しかし、テストコードを読みやすくするにはどうすれば良いかといった議論はユニットテスト以外ではあまり行われていないと感じています。

そこで今回、さまざまなテストレベルとロールで活躍されている方々からテストコードをリーダブルにする方法について語っていただき、それぞれの違いや共通点について議論していただきます。

会の様子

リーダブルテストコード〜伊藤淳一さん〜

まず、リーダブルなテストコードの特徴として、

  • DRY原則にこだわっていないこと(DRY原則は、行数こそ短いが読みにくいテストコードを生成するリスクが高い)。もちろん、絶対NGではなく適切な抽象化はOK
  • ドキュメントのように読めること
  • 変数を使わずに文字列や数値を使用すること
  • テスティングFWを多用した"凝った"テストコードを書かないこと
  • 脳内メモリの消費が激しくないこと

の紹介をしてくれました。*1

その上で、実際のサンプルコードを見せてくれながら、上記のリーダブルなテストコードの特徴を守らないとどうなるか?守るようにリファクタリングするとどうなるか?というのを説明してくれるという発表で、

「その言語を知らない人が読めるようなテストコードを目指そう」「実行可能なAPIドキュメントになっているかどうかチェックしよう」という指標はめちゃくちゃ直感的で、今後自身がテストコードを書くときに必ず意識しようと思いました。

コンテキストとセマンティクスを意識して リーダブルなE2Eテストコードを書こう〜末村拓也さん〜

E2Eテストはどうしてもコードの量が長くなりがちで、ページ遷移も頻繁に起こるため、脳内メモリの消費を抑えることが重要で、そのためにどんなことができるか?ということをお話してくれました。*2

具体的には、タイトルにもあるように、

  • セマンティックな書き方を用いるために、文言*3とサイトのアクセシビリティを活用する。ユーザにとって意味のある書き方をする。
  • 今何をしているのか?今どこにいるのか?をコードベースで明確にしていくことで、コンテキストをコード上に明示する*4

の2点が紹介されていました。テスタビリティが高ければアクセシビリティも自然と高くなるという観点を知ったり、Context Enclosureというアプローチを知ることができたりと、初めて学ぶ点も多くて面白かったです。

ん?こういう場合はどうするの?となったタイミングや、もうちょっと詳しい説明が欲しいと思ったタイミングで、見事に補足説明してくれて、メモリの消費をあまりせずに聞ける発表でした。

テストコードにはテストの意図を込めよう〜ブロッコリーさん〜

テストメソッド名がテストの意図を表現できるようにこだわろうということで、実際に現場であったテストケース名をエッセンスだけ残した上で改変して紹介しつつ、そのテストケース名のどの部分に改善の余地があるか?というのを会話しながら改善した例を説明してくれました。

どのテストケースも改善の余地がある部分は感じられましたが、実際になぜそのようなテストケースになったのかの意図を深掘りしていきながら改善するというのは面白くて、一見すると意味がよくわからないテストケース名にも根拠*5が隠されていたのは驚きました。

ブロッコリーさんの発表は、実例マッピング感があってとても好きなのですが、今回も具体例をベースにリーダブルなテストメソッド名について探求することができて、面白かったです。

質疑応答&パネルトーク

パラメタライズテストの可読性を上げたい

必ずしもパラメタライズテストだけに限った話ではないですが、

  • テスト設計の意図を明確に記載する
  • 意図の部分を仕様書とテストコードを分かりやすく紐づける。カバレッジをどのように分かりやすくするか考える

という意見が挙がっていました。

なお、伊藤さんはDRY原則をテストコードにいきなり適用することに警鐘を鳴らしていましたが、パラメタライズテストはよく使用するので、DRY原則はあくまでも使いすぎないことが重要で、使わないことが重要ではないよ、ということです。

すでに書いたテストを捨てる基準は?

機能がなくなった時はもちろんですが、テストを書いた瞬間もテストを捨てるのに適したタイミングだという話が出ていました。

定数はプロダクションコードとテストコードで揃える?(同じ定数を参照する?)

絶対にこう!とまでは言い切れないけれど、基本は別々*6に書く方がいいんじゃないか?という話が出ていました。
アプリの振る舞いが変わったときにテストの振る舞いも変わってしまうのは、原則としてはあまりよくないという文脈で、「プロダクションコードとテストコードが仲良くしちゃだめ。テストコースが一緒に歩いていくと、バグも一緒に歩かないようにしてもらわないと」という発言が出ていたのは特に印象的でした。

リーダブルなテストコードをどのように浸透させるか?(良いコードの共通理解をどのように醸成するか?)

以下のような話が挙がっていました。

  • まずは自分自身がやってみて共感を集めること
  • わかる人が本などを参考にしつつ、教えていく
  • 徹底したコードレビューをしていく。レビューを続ける内に、段々これはダメなんだ、ということがわかる
  • 勉強会を開く
Mockすべき内容が多すぎる場合のテストってどうするの?

Mockを使うことがそもそも少ないという話が出ていました。
Mockを使う状況に直面している時点で、なんか複雑すぎることを考えている(テストしようとしている)可能性があるので、テスト分割を考慮したり、アプリケーション側のコードを見直したりとするサインじゃないかというお話も挙がっていました。

Contextやitを日本語で書く基準

日本語で楽をして書いちゃうことも多いという話が挙がっていました。
英語でかっこよく書きたい気持ちにはなりつつ、日本人しかいないようなプロジェクトでは、素直に日本語で書いた方がリーダブルになるということです。

これに派生して、日本人しかいないようなプロジェクトなら、テストメソッドや変数名は日本語にすることも積極的に検討して良いのではないか?というお話が挙がっていました。

テストコードのレビューに実例マッピングが活用できる?

実例マッピングのプラクティスは活用していないけど、実例マッピングの考え方は活用しているということでした。
実例マッピングのプラクティスの方はテストケースのインプットにするものなので、順序が違うということです。

テストケース名の可読性を上げる

ブロッコリーさんが話してくれた内容で詳しく触れられていましたが、プログラマー視点ということで伊藤さんにも質問が来ていて、答えてくれました。

伊藤さんも、ブロッコリーさんが話してくれた内容が非常に良いということでしたが、強いて付け加えるなら「後から読みやすいかどうか?」を考えているということです。

また、ブロッコリーさんからも補足があり、テストケース名に注目するのは大事だけどテストケース名が書けない=そもそもテストで確認したいことが曖昧、という場合も多いので、テストで何を確認したいのか立ち返ることも重要ということです。

テスト分析の学び方

マインドマップから始めるソフトウェアテストから学んだり、ブロッコリーさんの話から学んだり、The BDD Booksがエントリーポイントとしてはおすすめだということでした。

他にも、テスト開発方法論の一歩目で何がされているのか?をまず考えてみるのが良いというお話が出ていました。

テスト効率のためだけにidやnameを指定する、というやり方は可読性や保守性の観点ではありか?

可読性や保守性の観点ではなしだということでした。
msレベルのパフォーマンスを追求したければ検討するが、実践的に考えると基本はなしだと思うということです。(それをやるならプロダクションコードのパフォーマンスを改善した方がいい)

明日からリーダブルなテストコードを書くためにまず何をやるか?

最後に御三方から、明日からまず何をやるといいか?というアドバイスがありました。

伊藤さん...わからない時は「このコードわからない」と言うこと。自分のことを棚に上げること(自分も書けてないけど...で萎縮しない)

末村さん...読みにくいから触りたくないな、というコードに立ち向かう勇気を持つ

ブロッコリーさん...まず自分でやってみる。今日のモチベーションを維持した状態で一歩テストコードを今日聞いた観点で書いてみる。

全体を通した感想

自分は数十人くらいの時に参加したのですが、テーマに加えて登壇者の方々が超豪華ということもあって、今日見たらすごい参加人数になっていて驚きました笑

リーダブルをテーマにしているというだけあって、皆さんの説明がめちゃくちゃ分かりやすく、学びが多い最高のイベントでした。

*1:他にも、「実際のユースケースに近いこと」「describe/context/itの説明を丁寧に書く」「テストコードを一画面に抑える」も紹介されていましたが、本発表では、特に上記箇条書きで記載した点にフォーカスして話をしてくれました

*2:「脳内メモリの消費を抑える」という話は伊藤さんに引き続きの登場でした!

*3:文言が書けない場合(=画像が適切に表示されていることなどをテストする場合は)Testing Libraryを使用することで可読性を上げられる

*4:Page Objectは、この原則を守ろうとすると重いアプローチなので、Context Enclosureを活用する

*5:事前にしていたテスト設計がインプットになったり...

*6:=プロダクションコードの定数とテストコードの定数は別々に書く