BASEプロダクトチームブログ

ネットショップ作成サービス「BASE ( https://thebase.in )」、ショッピングアプリ「BASE ( https://thebase.in/sp )」のプロダクトチームによるブログです。

単体テストの考え方/使い方 社内読書会をしました

この記事はBASE アドベントカレンダー 2023の24日目の記事です。

基盤グループ エンジニアの田中 (@tenkoma) です。 2023年5月から8月にかけて、書籍「単体テストの考え方/使い方」の読書会を社内有志でしました。 読書会の様子や感想をまとめます。

書籍「単体テストの考え方/使い方」について

2022年12月に出版されました。 2020年1月に出版されたUnit Testing Principles, Practices, and Patterns (Manning)の翻訳書です。

単体テストについて定義し、その価値を最大限に高めるための方法について解説されています。

書籍への期待

テストコードを構成する概念やそれを書くテクニックがまとめられているところが気になりましたが、1.2 なぜ、 単体テストを行うのか?(7ページ)で紹介された「持続可能」という言葉に惹かれました。

それでは、単体テストをすることで何を成し遂げたいのでしょうか?その答えは、ソフトウェア開発プロジェクトの成長を持続可能なものにする、ということです。そして、この 「持続可能」という言葉が鍵となります。と言うのも、プロジェクトは簡単に大きくなってしまうものであり、特に、プロジェクトをゼロから作り始めた場合、その傾向が強くなります。 しかしながら、その成長を長いあいだ持続させることは簡単なことではありません。

例えば、テストコードも量が増えてくるとさまざまな問題が起こることがあります。テスト実行が遅くなる(Slow Tests)、テスト結果が不安定になる(Flaky Test / Erratic Test)などは代表的かと思います。 それらの兆候を発生しにくくし、プロジェクトの持続可能性を高めるテストにしたい。そのための知見が得られそうだと期待しました。

読書会の経緯と進め方

4月下旬くらいに個人としてテストコードの書き方をレベルアップする方法やら、知識をうまく他人に説明できるようになりたいと思い 何か参考になりそうな資料はないか検索したところこの書籍を見つけました。 内容をみてみると、未だ日本語訳が出版されていないxUnit Test Patternsの知識も多く取り込まれてそうと感じました。 話題共有できるSlackチャンネルを作ったところ、興味がある方、積読してた方などが集まったため、読書会を行うことにしました。

  • 書籍の内容で分からない箇所や話したいトピックをNotionに書いてもらう(事前に読まなくても参加OK)
    • 事前に読んでもらうのは少しハードルが高いかもしれませんが、グループ横断でメンバーが集まったので、スムーズに進行するために可能なら読んでもらう感じにしました
  • 毎週月曜日9:30から1時間、Slack Huddleで話す時間を用意する
    • 1章分のテーマについてその時間で話す
    • 章末に書かれている2〜3ページのまとめを音読
    • その後、Notionに書かれたトピックについて話す
  • 最小実施人数は3名で集まらなかったらスキップ。祝日の場合もスキップ

1章を読み始める前に、進め方について話す回を用意して大枠を決めました。

読書会の結果

参加者は日頃からプロダクションコードとテストコードの両方を書く開発者が多かったですが、そのノウハウや課題がチームをまたいで共有される良い場になったと思います。 また、プロジェクトのプロダクションコード・テストコード改善にこの書籍の内容や、Slackチャンネルが紹介されることもあり、やってよかったなと思いました。

書籍についての感想

まずは、書籍の中で定義されている様々な用語を普段テストコードを書いたりコードレビューするときに活用できるものが増えたと思います。 例えば、以下のような用語たちです。

  • テスト対象システム(System Under Test: SUT)
  • テスト・ダブル(モック・スタブ・スパイなど)
  • AAAパターン(3Aパターンとも)

用語自体は知ってはいたのですが、これらをテストコードに使ったり、コードレビューで用いなくてもテストコード運用に支障なく、説明するコストも必要なので、使わなくていいのでは?と思っていました。 しかし、用語の意味を理解し、テストコード中の変数名に sutstub を使ってみると、効果があると思い直しました。

テストメソッド中で変数名が $sut なら、それがテスト対象であり、$**Stub なら、テスト対象に間接的に入力を与える依存であるとわかります。$**Spy なら、メソッド呼び出しを記録して、あとでアサーションするんだろうな、と推測できます。テストコードを理解するコストを下げる効果がありそうです。

次に以下のようなトピックについて丁寧な解説があり、読み進めているときはやや過剰さを感じていました。

  • 網羅率(coverage)
  • 単体テストにおける古典学派とロンドン学派

その後の章を読むために必要な基礎知識であるとわかります。

古典学派とロンドン学派については、テスト駆動開発 - オーム社で紹介されていましたが、正直知識も興味もなかったです。しかしテストダブルの使い方の違いがテストコードの書き方にも大きな影響を与えることが理解でき、テスト戦略を考える上で必要な解説なのか、と思い直しました。

第4章からは「良い単体テストを構成する4本の柱」として以下を軸に詳細な議論を進めていきます。

  • 退行(regression)に対する保護
  • リファクタリングへの耐性
  • 迅速なフィードバック
  • 保守のしやすさ

モックの使い方や統合テストの章も頻繁にこの軸を使って説明が進むため、理解しやすいと思います。

依存、偽陽性・偽陰性、テストダブルなども図を多く使って解説されるためわかりやすいです。 以下のポストを紹介します。

ここまで特長や良い点について書きましたが、一方で鵜呑みにできない点はありそうです。 関数型アーキテクチャについては僕にその知識がほぼなく、活用できるか分からなかったこと、紹介されるサンプルの多くがバックエンドのロジックであり、 フロントエンドアプリケーションに適用できるかについても網羅的ではないかもしれません。

以上、この書籍だけでテストについて網羅できるわけではない部分はありそうですが、日常的なテストの書き方、コードレビューから、テスト戦略を組み立てる上で参考にできる部分が多く、良書だと感じました。

明日は、川口 (id:dmnlk) さんの組織の話です。お楽しみに!

おまけ