要約
RSpec::Code::ExampleGroup.define_example_group_method
,
RSpec::Code::ExampleGroup.define_example_method
を使うと、独自のexample_method ((x)it, (x)example など) やexample_group_method ((x)describe, (x)context など) を定義することができ、特定のタグを自動付与できて便利だった、という話を紹介します。
サンプル実装
# ./spec/supports/rspec_extend.rbなどを作って以下を記述。
RSpec::Core::ExampleGroup.define_example_group_method(:ciskipdescribe, :ciskip => true)
RSpec::Core::ExampleGroup.define_example_method(:ciskip, :ciskip => true)
# itの代わりにciskipを使うとciskipタグが自動付与される
# `rspec --tag @ciskip` で一時的にこのタグがあるテストをCIで回さないようにしたい
ciskip 'hoge spec' do; end
# it 'hoge spec', ciskip: true do; endと同等
ciskipdescribe '#hoge' do
it 'hoge' do; end
end
# describe 'hoge spec', ciskip: true do
# it 'hoge' do; end
# end
# と同等
テスト方法
# ciskipタグが付いているテストだけ実行する
$ bundle exec rspec . --tag @ciskip
# ciskipタグが付いているテストを除外して実行する
$ bundle exec rspec . --tag ~@ciskip
この部分は純粋にrspecのはなしですね
NOTICE!
@private
と打たれている、いわゆるruby外で用いられる一般的な意味でのprivateメソッドを呼び出しているのでお行儀はよくないと思われます...
よりよい方法があればコメントお寄せください
以下、この導入にいたった経緯や参考URLまとめなので、必要なければ読み飛ばしてください
詳細
なにを解決したかったのか
- ciでだけ一時的にskipさせたいテストがある
- xit, pendingはこの場合使えない
- 全テストケースから、ciskipさせているものだけを抽出して定期的にローカルでテスト走らせたい
- それに限らずともローカルでは常に実行対象にしておきたい
- また、安易に使うと「未実装の機能」「failの原因調査中」などの理由でpendingにしているテストと混同する
- 全テストケースから、ciskipさせているものだけを抽出して定期的にローカルでテスト走らせたい
- さてどうしよう
そこで考える選択肢
- rspecにはタグを打てるのでそれを使うのが王道だろうな
- rspecは特定のタグだけ実行対象としたり除外したりできる
- でも都度タグを書くのは面倒
- できればxitにするだけでpendingにできるみたいなのが嬉しい
- RSpec::Code::ExampleGroup.define_example_group_method がxit, itなどを定義している
- xitはskipタグを自動で付与し、pendingはpendingタグを自動で付与している
- CIでは
rspec --tag ~@ciskip
すればよさそう (実際はparallel_rspecをつかっています) - 良さそう
方針
- 愚直にタグを付ける
- ex
it ciskip: true do; end
- ex
- example_method, example_group_methodを増やす
- 実装は冒頭サンプル実装の通り
- ex
ciskip do; end
- これでciskipタグが自動でつく
メリットとデメリット
方針2の立場からみてみます。(方針1のメリット・デメリットはおおよそこの逆)
- メリット:
-
it ciskip: true { }
がsyntax errorで厄介なのを回避できる - パット見、わかりやすい気がする
-
- デメリット
-
RSpec::Core::ExampleGroup.define_example_group_method
,RSpec::Core::ExampleGroup.define_example_method
には@private
と書かれているのでご法度感はある- とはいえ追従は直ぐにできそう
- 独自定義したメソッドなので「ciskipというexample_methodみたこと無いんですけど」とチームに思われうる
-
NOTICE!
話の筋からはそれますが、そもそもCIでテストをスキップさせるのはよろしくありません。
そもそもciskipというexample_methodの導入をするべきかという議論はチーム内でするべきだと思います。
今回は一時的な利用目的ということで採用しました。
結果
一時的な利用目的ではありますが、 ciskipが導入されました
(実際はxitに併せてcitという名前になりました)
しばらく運用してみて様子を見てみたいと思います。