RSpec/Capybaraのテストコードを画面操作から出力するChrome拡張をつくった

ほぼ表題の通りの内容で、Chrome拡張を作ってみた。

完成度としてはまだまだだけど、とりあえずざっくり触れる程度にはなったので公開した。

f:id:mugi1:20171001221735g:plain

github.com

chrome.google.com

イコン画像は、カピバラの写真を適当になぞって作った。

なんでこんなものを?

Capybaraのテストコードを書くのが面倒だなって感じることが多かったのが1つの理由。

TDD的に、先にテストコードを書いていけるのが理想だな〜とは思うものの、Webアプリケーションの開発をしていると、現実には一度は画面から一通り確認して、その後にfeature specを書く流れが多いように感じる。

そしてCapybaraでfeature specを書こうと思うと、

  • 「これはテキストじゃなくてIDで選択しないとダメか〜」
  • 「あ〜、これはfindしてからsetしないといけないのか〜」

という感じで、スムーズに書けない自分がいる。

そのあたりを都度試行錯誤しているのが面倒だな〜と思い始めて、「どうせ最初に一通り画面を触ってるんだから、そのときの操作がそのままfeature specとして出力できればいいじゃん!」と思って作り始めた。

あとは、Chrome拡張って興味があったけどなにげに作ったことがなかったので、やってみたかったというのもある。

つかったもの

ContentScript ⇔ Background ⇔ DevTools という流れでデータのやり取りを非同期で行う必要があった。

ごちゃごちゃしそうだったので、非同期になる箇所はすべてeventsでラップして、全データがDevTools上にVue&Vuexで構築たストアに集約するようにしたところ、わりとスッキリした。

役割としては、

  • ContentScript : 操作の監視 & 情報を集約してeventsをpublish
  • Background : ContentScriptとDevTools間を中継するのみ
  • DevTools : ContentScriptのデータをsubscribeしCapybaraのコードを生成

みたいな感じになった。

できること

  • テキストフォーム・テキストエリアの入力 → fill_in の生成
  • ラジオボタンの選択 → choose の生成
  • チェックボックスの選択 → check/uncheck の生成
  • セレクトボックスの選択 → select の生成
  • 要素クリック → find(xxx).click / click_link / click_button の生成

あたりはできている。

一番やりたかった部分として、何でその要素を特定できるかで生成コードが変わるようになってる。

fill_in '一意のラベル', with: '入力値' # ラベルで特定できる
fill_in 'id', with: '入力値' # idで特定できる
find('.class').set('入力値') # classで特定できる
find(:xpath, '/div[1]/input[1]').set('入力値') # 上記全てが無理な場合はxpath

できないこと

まだまだ発展途上感がある。 現時点で以下は対応できていない。

  • 画面遷移後の継続動作
  • visit とかも作る
  • fill_in 前の要素の click が不要なので省く
  • などなど..

というわけで

公開してあるので、興味のある方はどうぞ。

個人的には、label/id/class/xpathの自動判別が作れたのである程度満足しているけど、機能的にもっと充実させていきたい。

要望などがあればissueにもらえると嬉しいです。