この記事は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でいうGiven
やBackground
に相当する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で書くと仕様とステップの実装を分離できます。
読みやすいし書きやすいですね。