7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

凸凹のRSpec平らに均すshared_contextがマジ便利

Last updated at Posted at 2018-12-24

この記事はOkinawa.rb Advent Calendar 2018の19日目の記事です。
昨日は @hanachin_ さんのRe: 10分間隔で 10時〜23時台の配列をつくるでした。

凸凹はつらい

みなさんのRSpec凸凹してませんか。

app以下のコードだとコードレビュー通らないぐらい凸凹しているコードもなぜかspecだと通ることが多い印象です。何を隠そうわたしも凸凹させたことがあります

え?凸凹って何かって? 凸凹の例はこういう感じです

RSpec.describe "動画が見れる", type: :system do
  context "ログインしている場合" do
    before do
      ログイン
    end

    context "クレジットカードを登録している場合" do
      before do
        クレジットカードを登録する
      end

      context "動画がある場合" do
        before do
          動画をつくる
        end

        it "動画が見れる"
      end

      context "動画がない場合" do
        it "動画がないと表示されている"
      end
    end

    context "クレジットカードを登録していない場合" do
      it "動画が見れない"
    end
  end

  context "ログインしていない場合" do
    it "動画が見れない"
  end
end

いろんな深さのネストがあります。凸凹してますね。
ネストが複雑すぎると読みづらい、どこに書けばいいかわかりづらい、exampleを実行するための前提条件がわかりづらいみたいな辛さが発生します。

凸凹になる原因

RSpecのdescribeやcontextはネストを深くしてもちゃんと動きます。
書けてしまうものはみんな書く。避けられない!

一方Gherkinはどうでしょう?
Featureの下にScenarioがあるだけ、文法が深いネストを許さない。
https://docs.cucumber.io/gherkin/reference/

凸凹の直し方

凸凹に書けてしまうので凸凹に書くのであれば、凸凹に書けないGherkinを真似してRSpecを書けば凸凹しないでしょう。

先程の例をshared_contextを使って書く

GherkinでいうGivenBackgroundに相当するStepをshared_contextで宣言します。
あとはGherkinのように並べるだけ。

RSpec.describe "動画が見れる", type: :system do
  shared_context "ログインしている" do
    before do
      ログイン
    end
  end

  shared_context "クレジットカードが登録されている" do
    before do
      クレジットカードを登録する
    end
  end

  shared_context "動画がある" do
    before do
      動画をつくる
    end
  end

  describe "動画が見れる" do
    include_context "ログインしている"
    include_context "クレジットカードが登録されている"
    include_context "動画がある"

    it "動画が見れる"
  end

  context "動画がない場合" do
    include_context "ログインしている"
    include_context "クレジットカードが登録されている"

    it "動画がないと表示されている"
  end

  context "ログインしていない場合" do
    it "動画が見れない"
  end

  context "クレジットカードが登録されていない場合" do
    include_context "ログインしている"

    it "動画が見れない"
  end
end

平らになって読みやすくなりましたね。

まとめ

わたしはappでは書かないようなネストをspecで書いてしまうことがあります。結果、RSpecが凸凹しすぎててつらくなることが少なからずありました。
わたしがGherkinでテストを書くとき深くネストすることはありません。なぜならGherkinの文法では深くネストした仕様を書けないからです。
Gherkinを真似してshared_contextで前提条件を細かく分けinclude_contextを並べて書くとわたしでもネストを減らして平らにできることがわかりました。

shared_context使ってRSpecのテストを平らにしていきましょう!

Gherkin♡のまとめ

Gherkinの文法はネストできないのでべんり。
ネストしたRSpecのテストに疲れたらGherkinでテストを書きましょう。

# language: ja
機能: 動画が見れる
  シナリオ: 動画が見れる
    前提 ログインしている
    もし クレジットカードが登録されている
    かつ 動画がある
    ならば 動画が見れる

  シナリオ: 動画がない場合、動画がないと表示される
    前提 ログインしている
    もし クレジットカードが登録されている
    ならば 動画がないと表示されている

  シナリオ: ログインしていない場合動画が見れない
    もし ログインしていない
    ならば 動画が見れない

  シナリオ: クレジットカードが登録されていない場合、動画が見れない
    前提 ログインしている
    しかし 動画が見れない

Gherkinで書くと仕様とステップの実装を分離できます。
読みやすいし書きやすいですね。

7
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?