テストコードを書きながらアプリケーションコードを書くメリット
この記事はiCARE Dev Advent Calender 2021 5日目です。
どうも、いっせいです。
先日英語でLTをさせていただきました。
I talked a lightning talk in English for the first time | 働くひとと組織の健康を創る iCARE
そこでは「テストコードを書きながらアプリケーションコード書くのがよいよ」というお話をおさせていただきました。
その中でメリットを2つ挙げさせていただいたのですが、深くは説明できなかったので補足したいと思います。
テストを先に書くメリットは他にもあると思うのですが、LT内で挙げたメリットは以下の2つです
- Aware badness of design of the application code
- Avoid writing wrong test code
Aware badness of design of the application code
これは「テストが書きにくいと思ったら、アプリケーションコード自体の設計がよくないかもしれないことに気付けるかも」ということです。
たとえば簡単ですが
def send_invitation_mail(user_id)
user = User.find(user_id)
body = "ようこそ #{user.name}さま! ~~~~(本文構築する処理が続く)"
InvitationMailer.send(body).deliver_now
end
のようなメソッドがあったとします。
(コードがいけてないのはすみませんすみません :bow:)
そして本文構築処理をテストしたいとします。
このままテストしようとするとInvitationMailerをモックしたり、メールの送信をテストごとにリセットしないといけません。
そこで「これ本文構築する処理を抜き出してテストすればいいんじゃない?」と気付けるわけです。
def send_invitation_mail(user_id)
user = User.find(user_id)
body = compose_body(user)
InvitationMailer.send(body).deliver_now
end
def compose_body(user)
"ようこそ #{user.name}さま! ~~~~(本文構築する処理が続く)"
end
send_invitation_mailのテストをするのではなく、compose_body メソッドのテストをすればよくなり、メーラーのことを気にしないでよくなりました。
このようにテストを書きながらすすめることで、テストの書きづらさやメソッド使いづらさに気付けるかもということが1つ目の伝えたかったことです。
Avoid writing wrong test code
2つ目は「間違ったテストコードを書いてしまうことを避けられるかも」ということです。
実装を先にすませてしまい、あとからテストコードを書こうとすると、
「実装に関わらずパスしてしまうテストを書いてしまう」ということがたまに起こります。
そのようなテストは意味がありません。
たとえば商品を追加する処理があったとします。
しかしそこでは実装に間違いがあり商品が追加されていないとします。
そこで以下のようなテストコードがあったとします。
describe Factory do
let!(:product_1) { create(:product)}
(たくさんのテストコード)
describe "#add_product" do
let!(:current_product) { create(:product) }
it '商品が2つあること' do
factory.add_product
expect(Product.count)to eq 2
end
end
end
テストコードの最初にあったproductの作成に忘れていて、最初からproductの数が2個にも関わらず「追加する処理を走らせて2個になったからOKだ」という勘違いをしてしまいます。
アプリケーションコードがない状態でテストコードを書いて実行し、「正しく失敗すること」を確かめてからアプリケーションコードを書くことにより、そのような意味のないテストを作成することを避けることができます。
これが二つ目の伝えたかったことです。
おわりに
私が思うテストコードを書きながらアプリケーションコードを書くメリットを説明しました。
ぜひ「Hurry around - 急がばまわれ」の気持ちでテストコードを書きながら実装を進めてみてください!
ではまた!