一休.com Developers Blog

一休のエンジニア、デザイナー、ディレクターが情報を発信していきます

E2EテストをSelenium Webdriver からCypress.io に移行した話

こんにちは。 一休.comの開発基盤を担当しています、akasakasです。

今回は、E2EテストをSelenium WebdriverからCypress.ioに移行した話をしたいと思います。

一休のE2Eテスト事情

一休では staging/production へのリリース完了をフックにして、主要導線に対してE2Eテストを実施しています。

これを実施している主な理由としては

  • 検証環境での障害の事前検知
  • リリース後も正常に予約ができるかどうかの確認
    • ECサイトで予約を止めるのは致命的なので、これを防ぐ

があります。

詳しくはこちらのスライドに書いてあるので、興味のある方はみてください。

speakerdeck.com

あれから、数年が経過して、、、

完全に動かなくなりました。悲しいです。

f:id:akasakas:20190421204926p:plain

どうしてこうなった???

理由としては

  • SelniumではSPAへの対応が難しくなってきた
  • なんでもかんでもSeleniumに任せようとした弊害

がありました

SeleniumではSPAへの対応が難しくなってきた

一休ではSPA化が徐々に進んできています。

具体的な取り組みについては下記のエントリで紹介しているので、ご興味があれば、ご覧ください。

user-first.ikyu.co.jp

user-first.ikyu.co.jp

Selnieum Webderiver は画面遷移をしていくMPAに対して、効果を発揮するブラウザテストツールであり、

  • 非同期リクエストや動的な画面の書き換え
  • 画面遷移が発生しない

SPAでSelenium Webdriverを使って安定したテストを継続していくのが困難でした。

Wait処理などを上手く使えば、不可能ではないですが、一休ではQA・テストエンジニアのようなポジションはいなく、開発者がテストも修正するようになってます。

開発者にテストを書く負担を減らして、サービス開発に集中して欲しいというのも思いとしてありました。

なんでもかんでもSeleniumで頑張ろうとした弊害

一休.com ではUTが充実していないためか、「なんでもかんでもSeleniumでテストしよう」みたいな雰囲気がありました。

具体的には、APIの疎通確認をしたいが為に、SwaggerUIのようなテスト用の画面を作成し、その画面をSeleniumを使って、APIの疎通確認を行っていました。

APIのテストをわざわざブラウザテストをする必要はないです。 ただでさえ、ブラウザテストは不安定で時間がかかるので、適切なレイヤーで適切なテストができていないというアンチパターンに陥っていました。

いざリプレイスへ・リプレイスをする上で気をつけたこと

上記の理由からSeleniumから別のブラウザテストツールの移行を検討しました

単純なツールの乗り換えだけだと、同じ過ちを繰り返す恐れがあったので、下記の点を注意しました。

  • 開発者フレンドリー
  • 安定性
  • 然るべきレイヤーでテストする(何でもかんでもブラウザテストにしない)

開発者フレンドリー

Selneiumの課題として、セットアップが面倒というのがありました。

開発者にテストへの時間を軽減して、サービス開発に集中して欲しいというのも思いがあったので、下記の点を重視しました。

  • セットアップの敷居が低いこと
  • 開発者が容易にテストを作ることができる

安定性

言わずもがなですが、「移行したはいいが、テストが落ちまくっている」というのは有り得ないので、

  • SPAでも安定してテストが動く

ということにフォーカスしました

然るべきレイヤーでテストする(何でもかんでもブラウザテストにしない)

前述でも書きましたが、

  • APIのテストを無理やりSeleniumで書いていた

というのが、テストの安定性を損ねていた原因の一つでした。

この問題に関しては、APIテストライブラリを導入して、ブラウザテストとは切り分けました。

APIテストライブラリに導入については後日、どこかで書きたいと思います。

技術選定

ブラウザテストでSeleniumからどのツールを選ぼうかを考えた際に、以下の3つが選択肢としてありました

  • WebdriverIO
  • Puppeteer
  • Cypress.io

どの技術を採用するかで重要視したポイントが「開発者フレンドリー」であるかです。

具体的には

  • セットアップ
  • 書きやすさ

の2点です。

f:id:akasakas:20190421211638p:plain

セットアップという点だと、Puppeteer・Cypress.ioがいい印象でした。

書きやすさで見た場合、Cypress.ioの方がテストを書くことに集中できると思ったので、Cypress.ioを採用することに決めました。

Cypress.io とは?

JavaScript製のブラウザテストに特化したE2Eテストフレームワークです。

Seleniumはテストを書くこと以外にもスクレイピング等の用途で使うことができますが、 Cypress.ioはテストを書くことに特化したE2Eテストツールです。

Cypress.io のいいところ

Cypress.io の特徴は色々あると思いますが、個人的に感じるところとしては、次の3点が大きいと思います。

  • セットアップが楽
  • テストを書くことだけに集中できる
  • CI連携が楽

セットアップが楽

Cypress.io はセットアップが非常に簡単です。

npm install cypress

これだけで終わりです。

SeleniumだとGeckodriverやChromedriverをインストールしたり、パス設定したりと、 少し手間がかかるので、セットアップの敷居が低いという点で、非常にありがたいです。

テストを書くことだけに集中できる

SeleniumやPuppeteerを選ぶと、

  • テストランナーどれを選ぼう
  • レポーティングはどれにしよう
  • アサートのライブラリはどれにしよう

などといったところも考えると思います。

Cypress.io はオールインワンでサポートしているので、テストを書くことだけに集中することができます。

https://www.cypress.io/how-it-works/ で紹介されている、下記の図のようなイメージです。

f:id:akasakas:20190421205119p:plain

CI連携が楽

CI連携が楽という点も個人的にはありがたかったです。

  • DockerImageが用意されている
  • 各CI Provider に対して、 example project が用意されていて、わかりやすい

こちらに詳細が書かれているので、興味のある方はご覧ください。

https://docs.cypress.io/guides/guides/continuous-integration.html

Cypress.io の頑張って欲しいところ

Cypress.io に対する不満はそんなにありませんが、あえて1点だけ挙げるなら

  • クロスブラウザ未対応

という点です。

一休で、E2Eテストを実施している目的は

  • 主要導線が正常に動くことを確認すること

なので、クロスブラウザで確認する必要性はないです(確認するに越したことはありませんが)

Cypress でもOpen Issue として挙げられているので、今後クロスブラウザ対応がされる日が来るかもしれません(いつになるのかはわかりませんが)

Proposal: Support for Cross Browser Testing · Issue #310 · cypress-io/cypress · GitHub

その他、移行に関しての細かい話

あと、移行に関する細かい話としては以下の3つがあります

  • 重複テストケースの排除
  • Page Object Design Patternで設計
  • 移行に乗じて、CIもJenkinsからCircleCIに変更

重複テストケースの排除

既存のテストケースを見直すと、同じようなことをテストしている部分があったので、 移行の際にテストケースを精査して、必要最低限のテストケースを実施するようにしました。

Page Object Design Patternで設計

既存のSeleiumでもPage Object Design Pattern を採用しましたが、 画面変更に対して強い設計方法なので、ここは変えませんでした。

移行に乗じて、CIもJenkinsからCircleCIに変更

以前はCIのためにオンプレサーバのJenkinsを用意していましたが、Jenkins起因でE2Eテストが失敗することもしばしばありました。 テストの安定性を考えた場合、CIも乗り換えた方がいいと感じていたので、このタイミングでCircleCIで実行するように変更しました。

そして、E2Eは復活し、平和はおとずれた

かくかくしかじかありまして、E2Eテストが復活しました。めでたしめでたし。

f:id:akasakas:20190421205259p:plain

まとめ

今回は、E2EテストをSelenium WebdriverからCypress.ioに移行した話をしました。

Seleniumがよくないとか、Cypress.ioがいいという話ではなく、 一休のサービス開発が進んでいった結果、SeleniumによるE2Eテストが難しくなり、今回Cypress.ioへの移行をしました。

Cypress.io の利点としては、上述でも書いた通り

  • 開発者フレンドリー

であることだと感じます。

一休のようにQAやテストエンジニアがいなく、開発者がE2Eテストを修正するようなワークフローになっている開発現場ではCypress.ioを採用するのは選択肢の一つとして、ありなのかなと思います。

しかし、正直な話、この仕組みも数年後には破綻するかもしれません。 その時はまたサクッと捨てて、その時に一休のサービス・開発現場にマッチする新しい仕組みに乗り換えればいいと思います。 そういうことができるようにブラウザレベルのテストを極力書かないほうがいいのかもしれません。

また、この数年間、一休.com を守ってくれたSeleniumには感謝と敬意を払いながら、未来のために新システムに切り替えていきたいです。