Thanks Driven Life

日々是感謝

rspec-html-matchers 使い初め

自作 RSpec HTML Formatter のテスト、とりあえず出力される HTML もチェックしてる。たとえば ↓ な感じでやってた。

https://github.com/gongo/turnip_formatter/blob/6f1896f0ab9fd0f19fa7093f9a23e6499f570f83/spec/turnip_formatter/printer/step_extra_args_spec.rb#L6-L22

context 'Turnip::Table' do
  describe '.print_out' do
    let(:string) do
      ::Turnip::Table.new([
          ["State", "Money"],
          ["<Tokushima>", "555"],
          ["<Okinawa>", "368"]
        ])
    end

    #
    # <tr>
    #   <td>State</td><td>Money</td>
    #   <td>&lt;Tokushima&gt;</td><td>555</td>
    #   <td>&lt;Okinawa&gt;</td><td>368</td>
    # </tr>
    #
    subject { StepExtraArgs.print_out([string]) }

    it { should match %r{<td>State</td>[[:space:]]+<td>Money</td>} }
    it { should match %r{<td>&lt;Tokushima&gt;</td>[[:space:]]+<td>555</td>} }
    it { should match %r{<td>&lt;Okinawa&gt;</td>[[:space:]]+<td>368</td>} }
  end
end

わかるようでわからない。なんかこうすっきりと HTML チェックできるやつないかなって思ってたら今日見つけた。結構前からあった

kucaahbe/rspec-html-matchers · GitHub

試しにさっきのをやってみた

@@ -15,9 +15,18 @@ module TurnipFormatter::Printer
 
         subject { StepExtraArgs.print_out([string]) }
 
-        it { should match %r{<td>State</td>[[:space:]]+<td>Money</td>} }
-        it { should match %r{<td>&lt;Tokushima&gt;</td>[[:space:]]+<td>555</td>} }
-        it { should match %r{<td>&lt;Okinawa&gt;</td>[[:space:]]+<td>368</td>} }
+        it {
+          subject.should have_tag 'table.step_outline' do
+            with_tag 'tr:nth-child(1) td:nth-child(1)', text: 'State'
+            with_tag 'tr:nth-child(1) td:nth-child(2)', text: 'Money'
+
+            with_tag 'tr:nth-child(2) td:nth-child(1)', text: '<Tokushima>'
+            with_tag 'tr:nth-child(2) td:nth-child(2)', text: '555'
+
+            with_tag 'tr:nth-child(3) td:nth-child(1)', text: '<Okinawa>'
+            with_tag 'tr:nth-child(3) td:nth-child(2)', text: '368'
+          end
+        }
       end
     end

コード量増えてしまったが、ひとまず何をチェックしたいのかってのが明確になった気がする。

その他変更履歴 https://github.com/gongo/turnip_formatter/commit/74b84ff66d66084489960e5c968a14b1c8c8b1ef

ちなみに、なんで subject を省略せずに subject.should って書いてるかというと

暗黙的なsubjectを使用する場合、ブロックがあると不具合がでる

Rspecマッチャー rspec-html-matchersを試してみてる - そんなこと覚えてない

っていうことがあったからです。

一応これは回避策があって

@@ -16,7 +16,7 @@ module TurnipFormatter::Printer
         subject { StepExtraArgs.print_out([string]) }
 
         it {
-          should have_tag 'table.step_outline' do
+          should(have_tag('table.step_outline') do
             with_tag 'tr:nth-child(1) td:nth-child(1)', text: 'State'
             with_tag 'tr:nth-child(1) td:nth-child(2)', text: 'Money'
 
@@ -26,6 +26,7 @@ module TurnipFormatter::Printer
             with_tag 'tr:nth-child(3) td:nth-child(1)', text: '<Okinawa>'
             with_tag 'tr:nth-child(3) td:nth-child(2)', text: '368'
           end
+          )
         }

みたいな感じで、しっかりと「このブロックは have_tag() に渡している」って明示すればいける。

RSpec::Matchers#matches? はブロック取らない想定なのに、rspec-html-matchers だとブロックうけとるようになってる のが関係してんのかなーと思いつつよくわかってない。

とりあえずはこれ使っていこう。そして rspec-html-matchers が1ファイルですごいがんばってるのでリファクタしたくなりますね。