Slide 1

Slide 1 text

Capybaraで変更に
 強いE2Eテストを書く Yuichi Goto (@_yasaichi) July 29, 2018 @ TokyuRuby会議12

Slide 2

Slide 2 text

self.inspect @_yasaichi yasaichi http://web-salad.hateblo.jp ピクスタ株式会社  技術推進チームリーダー !2 一般的には「技術基盤」と 言われるようなチーム

Slide 3

Slide 3 text

https://pixta.co.jp/business !3 ピクスタは「クリエイティブプラットフォーム」を創る会社です 3つのサービス全てでRubyを利用。
 感謝のRubyKaigi協賛(過去5回)

Slide 4

Slide 4 text

Agenda 変更に弱いE2Eテストとは   変更に強いE2Eテストを書く方法   残った小さな問題とその解決   まとめ !4

Slide 5

Slide 5 text

変更に弱いE2Eテストとは • Webアプリケーションでは、次のようなUI上の変更に 強く影響を受けるE2Eテストと定義できそう • HTMLタグの構造を変更する • コンポーネントのスタイリングを変更する • 画面内の文言を変更する !5

Slide 6

Slide 6 text

対応するCapybaraのコード例 • タグ名で指定: all("table > tr")[1] • 既存のクラス名で指定: find(".for-styling") • 画面内の文言で指定: click_button("จݴ") !6 _人人人人人人人_ > 見たことある  <  ̄Y^Y^Y^Y^Y^Y^Y ̄

Slide 7

Slide 7 text

放置するとどうなるか 1. UI周りを数行変更したらなぜかCIが落ちた 2. エラーを見るとE2Eテストで落ちていることが判明 3. 該当のテストを手元のマシンでデバッグする # !7 じわじわと開発のボトルネックになってつらい

Slide 8

Slide 8 text

Agenda   変更に弱いE2Eテストとは 変更に強いE2Eテストを書く方法   残った小さな問題とその解決   まとめ !8

Slide 9

Slide 9 text

https://blog.kentcdodds.com/making-your-ui-tests-resilient-to-change-d37a6ee37269 !9 Kent C. Dodds氏(TC39の一員)の提案手法がおすすめ

Slide 10

Slide 10 text

要旨: テスト用のdata属性を使おう • スタイリングに使っているクラス名をテストで再利用 すると、UIの変更によってテストが壊れうる • テスト用のクラス名を用意すると既にスタイリングで 使っているそれと混ざってしまい、管理が大変 !10 data-testid のような見るからにテスト専用の
 カスタムdata属性をセレクタとして使えば解決!

Slide 11

Slide 11 text

お題: ログインフォーム

Sign in

<%= form_with model: resource, url: session_path(resource_name) do |f| %> <%= field_set_tag nil, class: "form-group" do %> <%= f.email_field :email, placeholder: "Email", class: "form-control form-control-lg", "data-testid": "email" %> <% end %> <%= field_set_tag nil, class: "form-group" do %> <%= f.password_field :password, placeholder: "Password", class: "form-control form-control-lg", "data-testid": "password" %> <% end %> <%= f.submit "Sign in", class: "btn btn-lg btn-primary", "data-testid": "submit" %> <% end %> <%= render "users/shared/links" %> !11 テストで使う要素にdata属性を振っておく

Slide 12

Slide 12 text

data属性を使って書くE2Eテストの例 require "rails_helper" RSpec.describe "User sign in", type: :system do let(:user) { FactoryBot.create(:user) } before do visit new_user_session_path end it "should allow users to sign in with their email and password" do find("[data-testid='email']").set(user.email) find("[data-testid='password']").set(user.password) find("[data-testid='submit']").click expect(page).to have_current_path(root_path) end end !12 タグ名、クラス名、画面内の文言に 依存していないのがポイント

Slide 13

Slide 13 text

カスタムセレクタを使うと便利 • 毎回 find("[data-testid='email']") のように
 書かないといけないのは面倒くさい • Capybaraではカスタムセレクタを定義できるので
 これを使うとよい !13 Capybara.add_selector(:test_id) do css { |val| %Q([data-testid="#{val}"]) } end find(:test_id, "email") # == find("[data-testid='email']")

Slide 14

Slide 14 text

Agenda   変更に弱いE2Eテストとは ɹ 変更に強いE2Eテストを書く方法 残った小さな問題とその解決   まとめ !14

Slide 15

Slide 15 text

そのdata属性、本番環境では不要では? • 本番環境に残っていても大きな問題ではない • 気になる人向けの解決策(Reactの場合) • babel-plugin-react-remove-properties • BabelでのJSXのトランスパイルに介入して、コン ポーネントに渡した任意のプロパティを取り除く !15

Slide 16

Slide 16 text

Ruby on Rails向けにも作れないか? • Haml/Slim向けにならほぼ同じ方法で作れるが・・・ • テンプレートエンジンごとにgem作ることになる • 素のHTML + ERBで書いている人は使えない !16 Railsのヘルパー呼び出しに介入する方法なら
 制約はあるものの汎用的なものが作れるのでは?

Slide 17

Slide 17 text

イケそうだったのでつい作ってしまった yasaichi / remove_data_attributes • RailsのViewヘルパーで生成されるHTMLタグから 任意のカスタムdata属性を取り除くgem • 設定ファイル(YAML)で取り除きたい属性名を指定 !17 # Configure which data attributes should be removed. data_attributes: - data-testid

Slide 18

Slide 18 text

data-testid を取り除く例 # (snip) !18 <%= form_with model: resource, url: session_path(resource_name) do |f| %> # (snip) <%= f.submit "Sign in", class: "btn btn-lg btn-primary", "data-testid": "submit" %> <% end %> オプションとして渡したものが 取り除かれる

Slide 19

Slide 19 text

仕組み • Railsの link_to などのViewヘルパーは内部的ʹ tag_options というメソッドを呼び出している • このメソッドに渡されたオプションを書き換える !19 # remove_data_attributes/lib/remove_data_attributes/ tag_options_filter.rb define_method(method_name) do |options, escape = true| options.is_a?(::Hash) ? super(processor.call(options), escape) : super(options, escape) end

Slide 20

Slide 20 text

Agenda   変更に弱いE2Eテストとは ɹ 変更に強いE2Eテストを書く方法 ɹ 残った小さな問題とその解決 まとめ !20

Slide 21

Slide 21 text

まとめ • UI上の変更に強いE2Eテストを書くために、各要素を 指定するためのよりよい方法を紹介した • data-testid のようなテスト用の属性を使う • Capybaraではカスタムセレクタを使うと便利 • 本番環境では不要なこれらの属性を削除するために
 remove_data_attributesというgemを作った !21

Slide 22

Slide 22 text

ご清聴ありがとうございました !22