テスト駆動開発のサンプルを1つ紹介

Overview

この記事では、今ちょうど作ってる機能のテストと実装の両コードをご紹介します。

Motivation/Context

記事にするにはちょうど良い具合のコードだったので、紹介してみます。
今回は登録したユーザーがパーティー(Party)というグループを作成できる機能の中で、グループの編集リンクを出し分けるっていう処理を実装していきます。
自分の作成したパーティーなら編集リンクが出るのが当たり前ですよね?
逆に、他人のパーティーに編集リンクが出たらおかしなことになっちゃいます。
さらに、ログインしていないのに編集リンクは不要ですよね。
そういうパターンを検証していきます。

Get Started!!

まずはRedな状態を作る

テストコードはこんな感じ。

describe "HTML要素" do
  fdescribe "編集リンク" do
    context "ログインしている" do
      context "自身が作成したパーティー" do
        it "表示される" do
          party = FactoryBot.create(:party)
          sign_in User.find(party.user_id)
          visit party_path(party)
          expect(page).to have_link("Edit this party")
        end
      end
      context "他人のパーティー" do
        it "非表示" do
          party = FactoryBot.create(:party)
          sign_in FactoryBot.create(:user)
          visit party_path(party)
          expect(page).to_not have_link("Edit this party")
        end
      end
    end
    context "ログインしていない" do
      it "非表示" do
        party = FactoryBot.create(:party)
        visit party_path(party)
        expect(page).to_not have_link("Edit this party")
      end
    end
  end
end

現在の実行結果はこんな感じ。
わかりやすく2つのテストがRedとして落ちてますね。
Greenになってるテストは元々リンクが存在するのでたまたまGreenになってます。
テストコードで無駄に階層を深くしたのは、出力としていい感じに段落で文章化したかったからです。
人によってはネストは深すぎない方が良いっていう人も多いことは知っていますが、個人的には検証パターンを増やせるのでネストは深くても問題ないかなって思います。
どんな条件で落ちているのか明確ですからね。

テストをGreenにする

プロダクトコード
もう、本当に」最低限のコードだけで実装します。
かっこ悪くてもネストが深くても問題なしです。
ここでは早さが何より大事。

# 変更前
<%=
  link_to "Edit this party",
  edit_party_path(@party)
%>


# 変更後
<%=
  link_to "Edit this party",
  edit_party_path(@party)
  if user_signed_in? && @party.user_id == current_user.id
%>

実行結果はこんな感じ。
とりあえず、全部Greenになりましたね。
三角測量的にもokな感じがします。

リファクタリング

ここまでくれば、あとは気楽にやっちゃいましょう。
プロダクトコードの方をちょっとリファクタできそうですね。
ここからはエンジニアの発想力とか技術力の見せ所ですね。
僕は、modelのクラスメソッドを作るのが好きなのですが、今回はviewで利用する処理ということでhelperに書きました。
特に、sign_in?みたいなログイン処理ってmodelにかけそうにないので、
`party.belongs_to_user?`っていうインスタンスメソッドを作り、それをヘルパーで呼び出して実装しました。
なんか他にもイケてる実装方法ありそうですけどね。

こうしちゃえ!

def party_user?(party, sign_in_user)
  user_signed_in? && party.belongs_to_user?(sign_in_user)
end
<%=
  link_to "Edit this party",
  edit_party_path(@party)
  if party_user?(@party, current_user)
%>

最後にもう一度確認

うん!気持ち良い!

まとめ

いや〜テスト駆動開発って本当に気持ち良いですね。
開発のテンポが良くなって好きです。
それに、常にテストが通ってるっていう安心感。
コードの量が増えれば増えるほど、安心と自信が満ちていくぅ。

いいなと思ったら応援しよう!