賃貸領域でフロントエンドエンジニアをしている齋藤です。
今回はここ数年取り組んでいたフロントエンド領域における自動テスト導入とテスト工数削減について、書いていきたいと思います。 なぜ導入したのか、導入して見えた課題、そしてその課題を解決するためにどうしていったのか、という流れで書いていきます。
目次
なぜ導入したのか
まず弊社では日々の機能開発は基本的にABテストを実施して効果を検証しながら進めていきます。 そのため、対象となるページが見られたか、対象となる要素が表示されたか・使われたかなどを計測する必要があります。 静的な単一ページであればそれほど問題はありませんが、動的であったり複数のページでそれを行うとなると正しく計測できているかをテストするケースが膨れ上がっていきます。
LIFULL HOME'Sにおいては、物件の検索結果ページがまさにその典型例で、さまざまな切り口で検索でき、またその切り口によって表示されるものが異なります。 意図した切り口で表示されていること、意図しない切り口では表示されないこと、ちゃんと使えるか、計測が正しく行えているかなどをABテストのパターン数×切り口数×テスト項目数でテストする必要があります。
ちなみに切り口は以下のようなものがあります。
- マーケット(賃貸・マンション・一戸建て等)
- エリアの指定方法(都道府県、市区町村、路線・駅等)
- テーマ(条件を組み合わせたもの)
- タグ(物件に付けられたタグ)
などなど、さまざまな切り口およびその組み合わせで表示できます。
そういった中、弊社で機能開発時にどんなテストをしているかというと、基本的にはスプレッドシート等で作ったテストケースを元に、 デバイス・ブラウザの組み合わせで手動テストを実施しています。 このテスト方法自体はシンプルで、テストを書くのはもちろん、実施するのも誰でもできるという面があります。 一方でテストするページが増えるなどテストケースが増えるとそれだけテスト工数が増えるという一面もあります。
日々機能開発・改修が行われているので、このテスト工数が開発効率に大きな影響を及ぼしてきます。
たびたび障害が発生
上記の通り、切り口の組み合わせで出るものが変わるような複雑なページにさらにABテストが組み合わさるというのは、障害が発生しやすいということでもあります。 当然というとおかしいですが、意図しないページに改修したものが影響していたということが何度も起こりました。 事前調査やコードレビュー等で影響範囲等を見ていても網羅することは難しいのです。
開発効率が悪い
複雑で障害発生しやすいとなると、調査も時間が掛かりますし、テストも手を抜けません。 結果として、物件の検索結果ページに機能追加等改修をかける際には、非常に多くのURLでテストを実施する必要があります。
精神衛生的にもストレスが掛かって良くないですね。
自動テストを導入する
ではどうしていくかというと、設計やコード面での複雑性を解消していくというのが一つの方法です。 当然そういう活動も大小行われていますがそれらは一朝一夕では終わりません。
そこで、別の切り口として自動テストを導入し、開発効率を上げていこうということになりました。
自動テストの導入
導入に際しては、まずは開発効率が上がるのかが重要ですので、お手軽にできることから始めることにしました。 実はこれ以前からPuppeteerを使って要素の存在確認やスクリーンショットを撮るなどしていたということがありました。 ですので、使い慣れているということもあってPuppeteerを使った自動テストを行うことにしました。
※ PuppeteerとはChromeを操作するためのAPIを提供するNode.jsのライブラリです。
導入して見えてきたもの
いくつかの機能開発PJで自動テストを書いたのち、それらを共有して導入を進めていきました。 そこで見えてきたのは、テスト実施は効率化されるが、テストを書くということの障壁でした。
PuppeteerはNode.jsのライブラリであるため、普段JavaScriptを書かないエンジニアにとっては障壁があります。 また、テスト項目が増えればそれだけコードも増えるため、テスト作成だけでなくそのコードレビューにも時間が掛かるということもわかりました。
使い捨てに近いテストですので、テストを書くこと自体に対しての障壁があるということは、非常に大きな問題でした。
ほぼコードを書かない解決策
導入して見えてきたものは課題だけではありません。 いくつもの施策でテストを書いてきたことで、何をテストしたいかはおおむね見えてきました。
そこで、テストしたい内容ごとにコードを共通化しました。 ただしそれだけだと共通化したテストコード以外の部分のコードはまだ書かなくてはいけない。 なのでさらに踏み込んで、設定ファイルを読み込んで共通化したテストコードを実行できる様にしました。
const testCase = [ path, status: 200, specs: [ ... { type: 'hasStyle', title: 'ダイアログが表示されていないこと', selector: '.dialog[aria-hidden="true"]', styleValue: ['display', 'none'], }, { type: 'click', title: `ボタンをクリックする`, selector: 'button[data-target="xxx"]', }, { type: 'waitForResponses', title: `レスポンスが返ってくること`, waitForResponses: [ `https://${domain}/result/`, ], }, { type: 'hasElement', title: `ダイアログが表示されていること`, selector: '.dialog[aria-hidden="false"]', expected: true, }, ... ], ];
設定の一例は上記の通りで、テストタイプとセレクタや値などを記載していく様な感じです。 見ての通り、テストしたいことも明確になりましたし、何よりもテストを書くことが楽になりました。
そのほかにもテスト設定をテンプレート化し、headlessモード設定、Cookieの設定、assets読み込みオンオフなどを別に切り出した設定ファイルで管理しています。 サーバレスポンスのHTMLのみでテスト可能な場合には、assets読み込みオフで非常に高速にテストが実行できるなど、テストの実行速度も向上しました。
まとめ
自動テストに取り組み始めてから2年、テストコードの共通化を図ってから約1年が経ちました。 この1年もテストできることを増やしたり、安定して実行できる様にするなど改善を続けてきました。
その結果として、誰でも気軽に自動テストを書ける環境が整い、自動テストを活用した開発がチーム全体に広がったと感じています。 副次効果として、テストだけではなく事前調査での活用にもつながり、非常に効率的な開発が進められるようにもなってきました。
当然、デバイスやブラウザの違いが気になる様な実装に関しては手動テストも行います。 それでもそれらは最低限に抑え、できるものは自動テストで行うというスタンスを今は取っています。
自動テストの活用により以前より安心して開発ができる様になりました。 今後も改善を続けつつ、より安心した開発に向けても取り組んでいきたいと思います。
お知らせ
LIFULLではともに成長していける仲間を募集しています。よろしければこちらのページもご覧ください。