t_wadaさんによるテスト駆動開発ワークショップが開催されました!(レポート)

2018/2/27(火)に和田 卓人(@t_wada)さんに、テスト駆動開発(Test Driven Development, 以下TDD)の1日ワークショップを開催していただきました!

本ワークショップは前半と後半で2部構成になります。

  • 前半: TDDの講義およびライブコーディング
  • 後半: TDDの実習およびt_wadaさん含む全員参加型のコードレビュー

特に後半の全員参加型のコードレビューはワークショップの特徴的な要素であり、なかなか無い機会です。人数が多いと参加者全員のコードレビューができない可能性があったため、今回は小規模(全14人)で開催しました。

以下でワークショップの内容を振り返り・議論となったポイントを記載します。

前半: テスト駆動開発とは?

午前中は、テスト駆動開発についてt_wadaさんから説明いただきました。

講演の中では、まずはじめにKent Beck氏の著書"テスト駆動開発入門"の書き出しが引用されています:

「動作するきれいなコード」Ron Jeffriesのこの簡潔な言葉が、テスト駆動開発(TDD)のゴールだ。動作するきれいなコードはあらゆる意味で価値がある。

TDDのゴールである、 動作するキレイなコード に行き着くためには、大きく2つ道のりがあります。

上段のオレンジの道は。すぐ動かさずに念入りに設計・検討をして、その後にコードが動作するように直していく道です。これまでのソフトウェア工学では、オレンジの道が推奨されていました。しかし、日々の実際の開発ではコードを書いて始めてわかることもたくさんあります。また、考えに考え抜いてきれいなコードを書けても、実際にうごかしてみたら遅かった、といったケースもあります。言い換えると、予測可能性が低いということです。

現代のシステム開発では、周囲の環境が高速で変化していきます。たとえば、OSもアップデートされますし、周囲のソフトウェアのエコシステムやプログラミング言語が変化していきます。現代のソフトウェア開発では、このような変化の側面を考慮しつつ開発していく必要があり、オレンジの道は実体として険しいということが分かっています。

そこで、現代(2018年)のソフトウェア開発では、青色の道を辿っていく開発があります。今回のTDDは青色の道に沿った開発手法なのですが、青色の道には心理面での罠が3つあります。罠とは以下の感情を持ってしまうことです:

  • 堕落: 動くからいいじゃないか、と考えてしまう
  • 焦り: 作るものはいっぱいあるから、きれいにする時間はない
  • 恐れ: せっかく動くところまできているのに、きれいにするために触ったら壊れてしまうのではないか

TDDは最後の難関である「恐れ」に対処するための技術です。TDDのサイクルは以下の流れとなります:

  1. 次の目標を考える
  2. その目標を示すテストを各
  3. そのテストを実行して失敗させる(Red)
  4. 目的のコードを書く
  5. 2で書いたテストを成功させる(Green)
  6. テストが通るままでリファクタリングを行う(Refactor)
  7. 1-6を繰り返す

実際のTDDでは、上記のサイクルを繰り返してコードを書いていきます。

ワークショップでは、FizzBuzz問題を例に、TDDのライブコーディングで説明がありました。

後半: ペアプログラミング + TDD の実践kkk

後半(午後)は、実際に参加者同士でペアを組んで、TDD実習を行いました。

テーマは、Semantic Versioning(semver)で、semverを表すオブジェクトの実装およびmajor/minor/patchのアップデート方法を実装していくというものです。後半のプログラムは"1-1.5時間程度の実装の後に、全員参加型のコードレビュー"を2サイクル回すという流れで実施します。実装言語は自由であり、今回の参加者は Python/Ruby/Node.js/Java を選択していました。

通常の開発では1-2名のコードレビューを受けるのはあるかと思いますが、参加者全員の目で、さらに異なる言語のレビューをするのはなかなか無い機会です。参加者からも、「別の言語での実装は参考になる」という声があがっていました。

以下で、実際のコードレビューの質疑の中で、参考になるものがあったので共有します:

値を設定するメソッドのテストについて

Q: たとえば、setVersionのような値を設定するメソッドのテストはどうすればいいのか? A: getVersionのような対となるメソッドを利用して、テストできる。基本的にはリフレクションを使わない。 Q: その場合、getVersion自体が壊れてしまった場合は、setVersionのテストも壊れるがそれはしょうがないのか? A: YES。受け入れるべきリスクと考える。

例外のテストについて

Q: 例外のテストの書き方は悩んだが、どのような方法あるのか? A: 例外のテストの書き方はいくつかある。try/fail/catchパターンというのは1つで昔からある。メリットとして、catchした後のアサーションも書けるので、例外の中身自体のテストもできる。また、アノテーションを使って、ある例外が出たらテスト成功という書き方もある。

どこまでモックすべきなのか?

Q: たとえばデータベースような状態を保持してくれるソフトウェアや、外部APIのように3rd Party側が状態を保持するようなケースで、どこまでモックすれば良いのか? A: 1つのポリシとして、1台のラップトップに入るものは全て実際のものを使うようにしている。したがってデータベースは実際のものを使うが、3rd PartyのAPIが外部のものなので、モックする。


参加者からの感想

参加者からは以下のような声が挙がっていました:

  • TDDのアンチパターンである、Assertionルーレット等、テストを書く上でのアンチパターンに名前が付いているのが面白いし、覚える役に立ちそうでした。
  • プログラミングやテストを行う中で発生するジレンマや葛藤に対し、分かりやすい視点・解説で論理的に説明下さり、見通しが立ったように思います。メンテナンス性を確保するために、機能を細分化することの必要性や意義についても認識が深まりました。
  • これまで業務等でRuby/Golangのテストを実装したり、テスト駆動開発に挑戦したことはありましたが、体系的に学ぶことは初めてで、とても勉強になりました。

上記のコメントからも、非常に有用なワークショップであったことが伝わってきます!

おわりに

NTTコミュニケーションズでは、ソフトウェア開発の内製に力を入れています。テスト駆動開発のような汎用的なソフトウェア開発スキルを学ぶワークショップは、エンジニアにとって刺激的で、そして非常に有用なものでした。今回は参加者数を絞っていましたが、参加を希望する社員も多くいるため、t_wadaさんに協力を依頼しつつ、ワークショップを継続的に開催し、エンジニアのソフトウェア開発スキルを向上させていきたいと考えております。

© NTT Communications Corporation All Rights Reserved.