お久しぶりです。プラットフォームチームの南です
TSUTAYAで昔のドラマをレンタルするのにハマってます
(最近はラスト・フレンズを観て哀しい気持ちになりました)
今回は自分が個人的に触ってみたe2eテストツールについて紹介したいと思います
なんでe2e
当然ですがリリースをする際には動作確認を各環境で行います
その時、毎度同じ操作を画面で行うのが煩わしく感じることがあると思います(自分はそんなに嫌いじゃないです)
- リリースを行う際、前後の動作確認は重要
- 手順書としてドキュメントを用意しているが、人がやることなので抜けやミスがある可能性は否定できない
- 確認事項は毎回変わるわけではない
- ある程度手順が決まっている
- 開発環境・ステージング環境・本番環境とそれぞれでやるのが割とコストとして重い
ざっとこんな感じの問題点があったので、e2eを導入して効率よく自動化できないかと考えました
Cypressとは?
ツールは
- 王道的なseleniumとかよりもちょっと新しくていい感じのやつ触りたい
- ciや他サービスとの連携がとりやすい
- 導入・学習コストは下げたい
このあたりをポイントとして選定し、Cypressにいきつきました
Cypressの特徴として
- javascriptで動作する
- 軽量さくさく
- dashboardが使いやすい
- 導入・実装が容易
このあたりがあるようです
とりあえず使ってみます
導入方法
yarnやnpmでインストールできるので簡単でした
$ yarn add -D cypress
インストールが完了すると
$ yarn run cypress open
上記コマンドで動作確認できます
Cypressにはチュートリアル的なテストファイルがデフォルトで用意されているので、動かしながら使い方を学べます
e2eテストを書いてみる
実際にe2eテストを書いてみます
以前、vueを自習してたときに作ったtodo listに対してテストコードを実装してみます
我ながらとてもシンプルです
機能としてはこんな感じです
まずcypress.jsonにテスト対象アプリケーションのbaseURlを指定します
{ "baseUrl": "http://localhost:8080/" }
テストファイルはintegrationディレクトリの中に作ります
今回はtodo_spec.jsというファイルを作ります
そして完成したコードがこちらです
describe('todo list e2e', function () { beforeEach(() => { // functionの前に必ず実行される // baseUrlのrootへ cy.visit('/'); // todoを1つ追加 cy.get('.todo') .type('test todo').should('have.value', 'test todo') cy.get('.addBtn').click() cy.get('.todo').clear() // 2つ目のtodoを追加 cy.get('.todo') .type('test todo2').should('have.value', 'test todo2') cy.get('.important').check() cy.get('.addBtn').click() cy.get('.todo').clear() }); it('should create new todo list', function () { // .todoList -> 1行目の.rowTodo => Titleには"test todo"が入ってるよね?ImportantはFalseだよね?のテスト cy.get('.todoList') .find('.rowTodo:first').should('have.class', 'rowTodo') .find('.tIndex').should('have.text', '1') .siblings('.tTitle').should('have.text', 'test todo') .siblings('.tImportant').should('have.text', 'False') // 全部でtodoは2行あるよね?のテスト cy.get('.rowTodo').should('have.length', '2') // .todoList -> 2行目の.rowTodo => Titleには"test todo2"が入ってるよね?ImportantはTrueだよね?のテスト cy.get('.todoList') .find('.rowTodo:last').should('have.class', 'rowTodo') .find('.tIndex').should('have.text', '2') .siblings('.tTitle').should('have.text', 'test todo2') .siblings('.tImportant').should('have.text', 'True') }); it('should delete complete todo', function () { // 2行目のtodoをCompleteするぞ!の動作 cy.get('.todoList') .find('.rowTodo:last') .find('.compTask').check() // 全部でtodoは1行あるよね?のテスト cy.get('.rowTodo').should('have.length', '1') // 残ったtodoの中身は正しいよね?のテスト cy.get('.todoList') .should('have.length', '1') .find('.rowTodo:first').should('have.class', 'rowTodo') .find('.tIndex').should('have.text', '1') .siblings('.tTitle').should('have.text', 'test todo') .siblings('.tImportant').should('have.text', 'False') }); });
checkやclickのアクションを使ってDOMを操作し、shouldでassertを行います
siblingsとかのselectorをみるとjQueryを思い出しました
作ったテストを動かすには
$ yarn cypress run --browser chrome --spec=./cypress/integration/todo_spec.js
これで動きます
コマンドをみればわかるように、動作させるブラウザを選ぶことができます
コマンドラインで実行もできますが、 cypress openのコマンドなら動かすテストファイルをGUIで選択することもできます
Cypress dashboardの紹介
最後にCypressの大きな魅力であるdashboardについて紹介します
CypressにログインしProject IDとRecord Keyを取得します
取得したProject IDをcypress.jsonに追記します
{ "baseUrl": "http://localhost:8080/", "projectId": "xxxxxxxx" }
設定はこれだけ
あとは実行コマンドにRecord Keyを追記して
yarn cypress run --browser chrome --spec=./cypress/integration/todo_spec.js --record --key 999999999
これでテストの結果がdashboardと連携できます
dashboardではテストの結果やciを含む外部サービスとの連携設定、テスト動画・スクショの確認などが行えます
正直、dashboardが使いたいからCypressを使ってる感じもあります
さいごに
今回、試験的にCypressを使ってみましたが
などの利点がありました
ただし
- DOMを変更したときの対応
- テストデータの管理
- dashboardを4人以上で使うには課金が必要
などなど考慮しなければいけない課題もあるにはあると思いました
Cypressだけでなく、Postman -> Newman などツールは世の中に山程あるので、うまく組み合わせられると効率化できそうですね
以上!