この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
テストコードを書くのは辛い。
みなさん、テストコードは好きですか? 私は嫌いです。ええ、とても。
でも、書いた方が良い、よりもうほぼほぼ書かなくてはいけないものなので、書きます。
書いた方が結果的に楽なので、書きます。
書くのは辛いけど、書きます。
辛いのは書く時だけで、後々とても楽になるので書きます。
それでも辛いけど書きます。
楽をする為に書きます。
書きます。
なぜ、テストコードを書くのか
開発作業では、全ての作業が良いタイミングで進んでいくという事はまずありません。
例えばサーバー、クライアント両方でAという機能を開発していく時、タスク量としてはサーバー側の方が軽く、実装が完了して実際に動かしてみようとしてもクライアントのAが完成していないから動かせない、という事は多々あります。
コンソール上からAPIやメソッドを叩いて試す、とか、そんな事もやろうと思えば出来ますが、書いたものはコンソールから出てしまえば全部消えてしまいますし、またAPIからやろうとするとリクエストヘッダが必須だったり、引数が複雑だったりすると色々と面倒です。
しかし、テストコードを書いておけば、最終的にコマンドを一つ叩くだけできちんと動作するのかが分かり、仕様変更が入った時などもその動作が保証されているのか、実機確認などを挟まずとも簡単に分かります。
↓大体実例。
テストコードを書かない場合(サーバー側)
- サーバー・クライアント新規実装決定!
- サーバー実装完了! でも、クライアントがまだ完了してないから待つしかないよ……。まあ、コンソール上で試したら動くみたいだし問題無いかな。
- クライアント実装完了! 実機確認! 何? 動かない? ここが悪いのか。直してコンソールで確認して、ああ面倒臭いな、ユーザー作って条件満たさせて、その状態でここのコード叩いて、あー動かない、ミスった、再度直してまたコンソール叩いて、また違うところでエラー? はぁ……。
- 動くようになった! デプロイ! もう一度実機確認! 何? また動かない? ここが悪いの? あ、仕様ミスってる! 直してコンソールで確認して、ああ面倒臭いな、ユーザー作って条件満たさせて、その状態でここのコード叩いて、あー動かない、今度はtypoだ、再度直してまたコンソール叩いて、また違うところでエラー? ここもtypoじゃねえか! はぁ…………。
- 動くようになった! デプロイ! もう一度実機確認! 何? 動かない? もう勘弁して! 僕が悪いんだけど! どこが悪いの! 悪いコード! 書いたの僕だけど! コンソールで確認して、もう慣れたよこの手順、ユーザー作って条件満たさせて、その状態でここのコード叩いて、あれ動く! 今度はどこミスったの僕! 僕は悪い子!
- 動くようになった! デプロイ! もう一度実機確認! 何? 動かない? ウッ あ、試してる時に書いたコード消し忘れてる……。
- できた……。疲れた……。
〜〜〜〜時が過ぎた〜〜〜〜
「その機能仕様変更ね」
「分かりました(ほげぇぇぇぇぇぇぇぇぇぇぇ)」
2に戻る。
テストコードを書いた場合(サーバー側)
- サーバー・クライアント新規実装決定!
- サーバー実装完了! テストコードも書いて、と。AマスタとBマスタとCマスタとDマスタとそれに紐づくEマスタとFマスタとGマスタとHマスタのダミーデータ用意して、あー面倒だけど書いとかないとな。え、Eマスタに紐づくIマスタとJマスタ足りない? はい用意しますよ。え、更にIマスタからKマスタ参照してる? あーもう、面倒だな。 あー、やっと動いた。あ、エラー処理動いてない。直しておこう。
- クライアント実装完了! 実機確認! 何? 動かない? ここが悪いのか。テストコードきちんと網羅してなかったな。直して、テストコード動かして、あ、ここミスってる。直して、動いたな。うん。
- 動くようになった! デプロイ! 実機確認! 何? 動かない? いやテストコード動いてるけど……。あ、仕様間違えてる。直して、その分テストコードも直して。うん、動いた。
- デプロイ! 実機確認! 何? 動かない? あー、些細なミスしてんなこれ。テストコードの範疇外だから、でもまあ、すぐに分かったし、ここ直して、完了。
- 出来た。ふぅ。
〜〜〜〜時が過ぎた〜〜〜〜
「その機能仕様変更ね」
「分かりました(サーバー側ここ直して、テストコード自体は余り変わらんな。まあ、そんな手間じゃない)」
2には戻らない。
要するに
テストコードを書くのは面倒です。とても。そのコードを動かす為のDBデータを全て自らで用意しなければなりません。ユーザーを使うテストで、ユーザー登録処理などを事前にやっておいたり、クライアントで生成されるデータをこちらで入れてあげなければいけないといけない、などなどテストをする為には色々な障害があります。
必要なデータが多ければ、テストをする以前に1時間以上の手間が普通に掛かる事さえも。
でも、エラーが発生した時など、テストコードがあればコンソールなど動かさなくとも1コマンドを打つだけで簡単にコードに問題ないかを確認する事ができます。
テストコードが動いているのにエラーが発生しているとなれば、それはテストコードが条件を漏らしているという事が逆に判明し、それ以外の部分で何かが発生しているのだとすぐに理解、注力する事が出来ます。
最初に数時間、テストコードを書く事に時間を費やしておけば、エラーが起きたりしてもその対処がとても楽になるのです。
Railsでテストをする為に
まずテストコードを書くと言っても、元となるのはそのアプリケーションのコードです。そのコードがスパゲッティコードだとテストコードも書けなくなってしまいます。
MVCをきちんと分けよう
正直なところ、最もな事柄はこれに尽きます。
MVCがきちんと分けられていないコードはとてもテストし辛いです。特に単体テスト。
ControllerやViewに処理が書かれているとなると、その部分のコードをテストする為には、テストコードの中からAPIを叩かなくてはなりません。
MVCそれぞれのテストはそれぞれだけで完結出来るようなコードを書きましょう。
メソッドを小分けにしよう
メソッドを小分けにしておくと、それぞれでのテストが可能になり、仕様変更となった時に確認、保守が楽になります。
そしてテストコードを書く時は。
面倒臭いけどやらないと後々もっと面倒になるからやる
本当に。
自分が書くのが好きじゃないって言うのもあるかもしれませんが、やらなければ後々もっと面倒な事になります。本当に。
テストデータを数十の単位で作成しておかなければいけなかったり、吐くエラーの数だけ本当に正しく吐かれるのかを試すようにデータを弄ったりと。
Rspec、FactoryBot(もうGirlじゃないんですね)を使っている分Railsのデフォルトのテスト機能よりは楽なはずでしょうが、それでも手作業の部分は膨大になりがちです。
書いた事のない貴方も、後々楽になると信じて書きましょう。
それでは、時には面倒だけれどより良いRailsライフを送る為に頑張りましょう。