"ゆるWeb勉強会@札幌 Advent Calendar 2022" 5日目の記事です。
webに限った話では無いですが、webアプリーケーションエンジニアとしての経験、ということでご容赦いただければ・・・
この記事の内容について
私はここ数年、積極的にテストコードを書いて自動化することを検討・実施しています。しかし、最初からそうだったわけではなく、ソフトウェア開発を長く経験していく中で、そのように変わっていきました。そこで、なぜ私はテストコードを書くようにしたのか、それをどのように始めていったのかを紹介します。
内容としては「個人で始めるにあたりどのように考えたか」に焦点を当てており、実際に組織やプロダクトに適用していく戦略や、技術的な部分(導入方法など)には触れておりません。
テストを書こうと思っているがなかなか始められない人にとって、最初の一歩を踏み出すきっかけになれば幸いです。
不安な開発
まずテストを書き始めるにあたって私が抱えていた問題を一言で表すと「開発に対する不安」です。
私が経験してきたソフトウェア開発は手探りで進めることが多く、多くの痛みに耐えて前に進める状況でした。最初は「そういうもの」と思っていたのですが、関わっていたプロジェクトの炎上・焼失なども経験し、それを変えなければならないと思いました。
痛みに耐えて進めるのは一時的なもので、それではプロダクトもエンジニアも長続きしません。私はその不安や痛みがどこから来ているのか考え、それはテストにあると思いました。
なぜテストなのか?
ソフトウェアはアップデートが必要です。新しい機能を追加する、バグを修正する、リファクタリングする、依存関係を更新する。理由は様々ですが、サービスを長く続けていくためには、たくさんのアップデートをしなければなりません。そしてアップデートをリリースするにはテストが必要です。
これまでの開発でも、もちろんテストはしています。しかしそれはリリース前の確認のような位置づけで、積極的にバグを探していくようなテストであったり、広い範囲を確認するようなテストではありませんでした。その結果として「何かを壊しているのではないか」「リリースすると何か問題が起きるのではないか」といった不安を解消されなかったのだと思います。
まとめ
私は「開発に対する不安」の大きな原因は、複雑なソフトウェアを安心してリリースできるだけのテストが出来ていないことにある、と考えます。そして、これを解決するためにテストを自動する必要があると思いました。
なぜテスト自動化なのか?
なぜテストコードをかいて自動化するのか。その理由は様々ですが、手動のテストは時間がかかるという点と、ドキュメントという形は失われやすいという点があります。
テストを素早く実行したい
テストに時間がかかるとき、全ての機能を網羅することはできず、多くのテスト(特にリグレッションテスト)を削ることになるでしょう。そのため、できるだけ変更を開発対象に絞ることになり、結果として積極的なリファクタリングの実施を妨げることになります。
また、時間がかかるのでスケジュールの最後にまとめて実施されます。そのため、バグの発見が遅れるので修正にも時間がかかりますし、リリース間際に切羽詰まって対応することにもなります。
テストを残して、改良していきたい
ドキュメントという形は失われやすい、というのは残念ながらテスト仕様書に限ったことではないでしょう。テスト仕様書に関しては、テストを実施する機会が少ない、という点があると思います。その結果として有効なテストが残らない状況になっています。
テスト仕様書も一度では有効なものが出来ないでしょうし、残しておいてリグレッションテストなどで活用してきたいものです。
まとめ
自信を持って開発を進めていくためには、それなりに多くのテスト用意し、それを洗練させていく必要があります。そして、開発者がテスト結果が必要としているのは、リリース間際ではなく開発している最中なのです。それを実現するために、テストコードを資産として蓄えて素早く実行されるように自動化し、そして日々最適化していく必要があります。
テストを書くと何か困るのか?
ここまでは主に動機について説明してきましたが、ここからはどのように始めていったかについてです。新しいことを始めるにあたって不安を感じることも多いでしょう。ではテストを書き始めるにあっての不安は何であるか、自問自答してみました。
Q. まずテストフレームワークのインストールが必要だ。テストフレームワークをインストールすると何か困るだろうか?
A. テストフレームワークは本番環境で動作しない(またはインストールされない)から、サービスに不具合が出ることはないだろう。
Q. テストコードがあると何か困るだろうか?
A. テストコードはプロダクトコードの実行に影響は与えない。テストコードがあっても何かが壊れることはないだろう。
Q. 私がテストを書くと誰か困るだろうか?
A. 他に誰も書いていないのだから困らないだろう。逆の立場でも、個人のスタイルとして書いてるだけなら、私は困らない。
Q. それでも何か困ったことが起きたらどうする?
A. どうしても解決できない問題が出たら、テストフレームワークをアンインストールして、テストコードを削除すれば元通りになる。
まとめ
このような自問自答を行った結果、テストを書き始めるにあたって大きな障害は無く、仮に何か問題が起こっても元に戻すことができる可逆の試みであることがわかりました。
ハードルを下げる
それでも「テストコードを書くと時間がかかるのでは」とか「良いテストコードを書ける自信がない」といった不安はあると思います。しかし、それは無用な心配です。なぜなら、最初は時間が掛かるし、最初から良いテストコードは書けないからです。
「現在のスピード感で役に立つテストコードを書く」という目標は、残念ながら高いハードルでしょう。なのでハードルを下げて「まずはテストコードを書く経験を得る」と考えます。
また「組織に導入する」というのもハードルが高いでしょう。しかし「個人のスタイルとして」始めることはできます。
前節の結論の通り、うまくいかなかったとしても元に戻すことが出来ます。削除するとテストコードは残りませんが、それに使った労力は決して無駄なものではなく、テストコードを書いた経験は残ります。私が伝えたいのは、まずは経験を得ることが重要で、そのためのハードルはそれほど高くない、ということです。
実際テストを書いてどうだったか
当たり前ですが最初は良いテストコードは書けませんでした。
始めて書いたテストコードは、どんなテストしているのか良く分かりませんし、モックを使いすぎて信頼できないテストになったりしました。
しかし、それを続けていて多くの良いことがありました。まず、経験が増えるにつれてテストコードの質が向上しました。テストに自身が持てるようになり、テストが増えるにつれて、安心して開発できるようになっていきました。また、仕様を示すようにテストを書いた結果、よりコードがわかりやすくなりました。
それから、テストを書けるようにするにはプロダクトコードの設計をよく考える必要があります。ソフトウェアの保守性という品質を構成するものにテスト容易性があるのですが、簡単にテストが出来るような設計を意識した結果、プロダクトコードの品質も向上したのです。
このように、テストを書くことによって私が当初感じていた開発に対する不安が徐々に薄れていくと同時に、コードの品質も高くなっていきました。
残念ながら良いことばかりではない
もちろん良いことばかりではありません。
例えば、テストコードも増えてくるとわかりにくくなりますから、プロダクトコード同様にメンテナスも必要です。
テスト自動化を進めていくと新しい痛みが出てくるでしょう。しかしそれは進歩だと思っています。
まとめ
- テスト書き始めるのは思っているより簡単
- 価値のあるテストコードの前に、まずは価値のある経験
- テスト自動化は開発の不安や痛みを和らげる
- ただしテスト自動化は終わりではない
「テストコードを書くスキル」はこれからのソフトウェア開発において必須と言えるものになってきていると思います。実際にどのようなテスト書いて自動化するかは状況によりますが、テスト自動化の選択肢があることが重要になります。まずは「選択肢を手に入れる」と思って、始めてみてはいかがでしょうか。
おまけ:どのようにテストの書き方を学んだのか
『テスト駆動開発』
TDDは設計手法ではありますが、テストの書き方も学ぶことができます。サンプルコードはJavaとPythonですが、もちろんPHP + PHPUnitでもできます。(申し訳程度のweb要素1)
『初めての自動テスト』
ユニットテストだけではなく、統合テストやUIテストも含めたWebシステムの自動テストについて学ぶことができます。(申し訳程度のweb要素2)
著者は『アジャイル・サムライ』を書いた方で、そちらと同様に初学者にやさしい内容になっています。
t_wadaさんのライブコーディング
ライブコーディングでテストを書いて、それをリファクタリングしていく過程を見ることができます。最終的にテストコードが仕様書のようになっていくのがとても印象的でした。PHPはネストして構造化できないのが残念です。(申し訳程度のweb要素3)