Slide 1

Slide 1 text

Selenide + Cucumber で実現する UI テスト自動化 + BDD #jjug #jjug_ccc 髙市 智章 (Tomoaki Takaichi) Nov, 7, 2020 JJUG CCC 2020 Fall

Slide 2

Slide 2 text

自己紹介 @Takaichi00 tomoaki.takaichi.5 ・髙市 智章(タカイチ トモアキ) ・Java / Node でのシステム開発 ・CI / CD ・Container / k8s ・アジャイル開発実践 共著: クリーンなコードへの SonarQube即効活用術 http://u0u0.net/RSvx

Slide 3

Slide 3 text

❏ Selenide と Cucumber の概要を知る ❏ Selenide と Cucumber を使った開発イメージを掴む ❏ テストを運用するときの Tips ❏ 1シナリオを実装するデモ 本日お話すること

Slide 4

Slide 4 text

Selenide のご紹介

Slide 5

Slide 5 text

❏ Selenideは、Selenium WebDriver(後述) を利用した UI / 受け入れテスト自動化のためのフレームワーク ❏ 自動 UI テスト実装の際、 Selenium WebDriver では冗長な 記述になりがちだった処理を Selenide はラッピングしてい る。よってよりビジネスロジックに集中したテストを実装で きるということを特徴としている ❏ Java 言語でのみ記述できる Selenide 概要

Slide 6

Slide 6 text

❏ Selenium WebDriver とは、ブラウザ操作を自動化する ツール ❏ ThoughtWorks 社によって開発され、UI テスト自動化や Web サイトのクローリングにも利用される ❏ Java 言語以外でも記述することができる Selenium WebDriver 概要

Slide 7

Slide 7 text

❏ Selenide は Selenium をラッパーするアーキテクチャと なっている Selenide の動作概要 出典: https://hackr.io/blog/what-is-selenium-webdriver/thumbnail/large Wrapper

Slide 8

Slide 8 text

❏ Selenium は WebDriver を直接操作するため、低レイヤーで詳 細な操作を実行することができる ❏ しかし単にブラウザテストをするには冗長な記述をしないといけない ことも ❏ Selenide ではより UI と受け入れテストを実装しやすいように 設計されている ❏ WebDriver を直接操作することなく実装できる ❏ Selenium と比較してコンパクトにテスト実装が可能 Selenium と Selenide の比較

Slide 9

Slide 9 text

❏ ブラウザを開く処理の違い (https://github.com/selenide/selenide/wiki/Selenide-vs-Selenium) Selenium と Selenide の比較 Selenium DesiredCapabilities desiredCapabilities = DesiredCapabilities.htmlUnit(); desiredCapabilities.setCapability(HtmlUnitDriver.INVALIDSELECTIONERROR, true); desiredCapabilities.setCapability(HtmlUnitDriver.INVALIDXPATHERROR, false); desiredCapabilities.setJavascriptEnabled(true); WebDriver driver = new HtmlUnitDriver(desiredCapabilities); Selenide open("/my-application/login");

Slide 10

Slide 10 text

❏ Ajax 処理の結果をアサーションするときの違い (https://github.com/selenide/selenide/wiki/Selenide-vs-Selenium) Selenium と Selenide の比較 Selenium FluentWait fluentWait = new FluentWait(By.tagName("TEXTAREA")); fluentWait.pollingEvery(100, TimeUnit.MILLISECONDS); fluentWait.withTimeout(1000, TimeUnit.MILLISECONDS); fluentWait.until(new Predicate() { public boolean apply(By by) { try { return browser.findElement(by).isDisplayed(); } catch (NoSuchElementException ex) { return false; } } }); assertEquals("John", browser.findElement(By.tagName("TEXTAREA")).getAttribute("value")); Selenide $("TEXTAREA").shouldHave(value("John"));

Slide 11

Slide 11 text

Selenide のセットアップ ❏ 依存関係に “com.codeborne.selenide” を追加する ❏ ブラウザを操作するために必要な WebDriver をダウン ロードする (http://chromedriver.storage.googleapis.com/index.html) ❏ 手動でダウンロードするか、”webdriverextensions-maven-plugin” を利用 することで自動でダウンロードしてくれる (https://su-kun1899.hatenablog.com/entry/2017/11/14/220000) ❏ “mvn generate-sources” コマンドで${basedir}/drivers に WebDriver がダウンロードされる ❏ バイナリをバージョン管理しなくてよくなる

Slide 12

Slide 12 text

ブラウザでページを開く Selenide を使った UI テストのサンプル id が “header” の文字列 をアサーションする id が “search-bar” のフィー ルドにテキストを入力する ❏ jQuery のような記述で要素を取得したり、アサーション をすることが可能

Slide 13

Slide 13 text

要素をクリックする Selenide を使った UI テストのサンプル ❏ 画面をクリックする、スクロールするなどの挙動も表現できる 要素までスクロールする ドラックアンドドロップする この他にも様々なことができるので実装の際は公式ドキュメントをご参考に! (https://selenide.org/documentation.html)

Slide 14

Slide 14 text

❏ 例えば複数のテストケースから

タグのタイトルをアサー ションしていた場合、

タグから

に変えただけで複 数のテストケースを修正しないといけないためメンテナンスが 大変になる Page Object パターン

hoge

$(“h1”).shouldHave(“...”) $(“h1”).hover(“...”) $(“h1”)..shouldNotBe(“...”)

hoge

$(“h2”).shouldHave(“...”) $(“h2”).hover(“...”) $(“h2”)..shouldNotBe(“...”) .html テストケース ... .html ... テストケース

Slide 15

Slide 15 text

❏ テストケースでは Page Object を参照するようにし、Page Object が

などの要素を取得するようにすれば、

に変わっても Page Object だけを変更するだけでテストケースを修正せずに済む Page Object パターン

hoge

getHeading.shouldHave(“...”) getHeading.hover(“...”) getHeading.shouldNotBe(“...”) public SelenideElement getHeading() { return $(“h1”); → return $(“h2”); }

hoge

.html Page Object テストケース ...

Slide 16

Slide 16 text

Selenide のデモ

Slide 17

Slide 17 text

Cucumber のご紹介

Slide 18

Slide 18 text

❏ Gherkin 記法を用いてテストケースを記述し、実行できる ツール ❏ ビジネスサイドとのギャップを埋めたり、 BDD をサポー トするツールと銘打っている ❏ 自然言語を用いてテストケースを記載できるという点が一 番の特徴 ❏ 日本語でテストケースを書くことも可能 Cucumber の概要

Slide 19

Slide 19 text

❏ feature ファイルにテストケースを記述し、steps ファイ ルにそのテストを実装する Cucumber の構成要素 feature ファイル steps ファイル

Slide 20

Slide 20 text

❏ Gherkin 記法の概要は以下 Gherkin 記法 参考: https://blog.eiel.info/blog/2013/02/12/gherkin/ 使用するキーワードの言語を指定 タグは機能やシナリオに指定可能 背景ではシナリオの前に実行したいステップを定義 できる ステップは 前提/もし/ならば/かつ/ などがある シナリオはテストケースを表し、ステップを複数持つ 機能ではこのファイルが表す機能名を記載する

Slide 21

Slide 21 text

❏ Data Table… テーブルなど複雑なデータ構造を表したい 場合に利用する ❏ Scenario Outline… いつくかの違う値で同じシナリオを テストしたい場合に利用する Data Table と Scenario Outline Data Table Scenario Outline

Slide 22

Slide 22 text

❏ Cucumber で Java のテストを実装するには ”io.cucumber” の “cucumber-java” と “cucumber-junit” を依存関係に追加する ❏ JUnit5 はまだ対応していないらしく、Junit5 のテストと 共存させるには “junit-vintage-engine” の依存を追加す る必要がある (https://github.com/cucumber/cucumber-jvm/issues/1149) Cucumber のセットアップ

Slide 23

Slide 23 text

❏ steps ファイルに Selenide を用いた画面テストを実装する Selenide + Cucumber でテストを実装する steps ファイル

Slide 24

Slide 24 text

Selenide + Cucumber のデモ

Slide 25

Slide 25 text

シナリオテスト実装の Tips

Slide 26

Slide 26 text

❏ feature ファイルと steps ファイルを 1対1 で対応させるのは直感的 だがアンチパターンとされている ❏ シナリオ間で steps の共有ができないため、似たような処理をする steps ファイルが乱立してしまう ❏ feature ごとに steps ファイルを作成するのではなく、ドメインの単 位で作成することが推奨されている Cucumber アンチパターン .feature A .feature B .feature C steps A steps B steps C .feature A .feature B .feature C Domain A steps Domain B steps step ファイ ルの乱立

Slide 27

Slide 27 text

❏ かつては Cucumber のテストは “.story” が使われていた ❏ しかし例えばユーザーストーリー単位でシナリオを書いた場合、開発 が進むにつれて以前のストーリーと矛盾するといったことが発生する ❏ ドキュメントとして機能しなくなってしまう ❏ 1つのユーザーストーリーでも複数の機能に変更がかかる場合はストー リーとフィーチャーを 1対1 で作成するのは難しい ❏ よって機能 (feature) ごとにファイルを分けるように変更された なぜ .story ではなく .feature なのか

Slide 28

Slide 28 text

❏ 「BDD とは、ステークホルダーの視点に立って振る舞いを説明するこ とにより、アプリケーションを実装するための手法」(The RSpec Book p121) ❏ BDD のプロセスは外側のループ (Cucumber によるシナリオテスト /ATDD) と内側のループ (JUnit などで実装するユニットテスト/TDD) から構成される BDD (Behavior Driven Development) 出典: https://i.stack.imgur.com/i9Uej.png

Slide 29

Slide 29 text

❏ Cucumber + Selenide を使うことで、画面があるシステ ムを「失敗する受け入れテスト」→ 「TDD」 →「受け入 れテスト成功」の開発サイクルを実現できる BDD のサイクル例 (CSD, 実践テスト駆動) スプリント バックログ 失敗する受け入れテスト を実装 (Cucumber) 受け入れテストが通るよ うに内側の機能の実装 (TDD / Unit Test) 受け入れテスト成功 (Cucumber) レビュー ...

Slide 30

Slide 30 text

BDD サイクルのデモ

Slide 31

Slide 31 text

デモプロジェクト概要 ❏ 図書管理システムを作成する ❏ 図書の情報を DB に保存し、本の一覧確認/貸出/返却 など をシステムでできるようにしたい ❏ 現在は管理している本のタイトルだけが表示できるように なっている Spring Boot Thymeleaf DB

Slide 32

Slide 32 text

❏ 顧客の方と一緒に .feature ファイルを作成する ❏ 失敗する Cucumber の受け入れテストを実装する ❏ DB 取得処理をモックにして画面とController の実装をする ❏ DB 取得処理を実装する ❏ 今回は Spring JPA を利用するためスキップ ❏ Cucumber の受け入れテストが成功する デモ概要

Slide 33

Slide 33 text

❏ BDD ではエンドユーザ要件を扱う受け入れテストを自動化し、そ のテストを通すことを目標として開発を進める ❏ 後続の実装がないところはモックオブジェクトを作成することで実 装を始めることができる 創発的設計 UserInterface 実装を進める流れ

Slide 34

Slide 34 text

❏ テーブル設計や IF の設計を事前に行うと、不必要なもの を作るリスクや、機能を作り終わってから設計に不備があ ることに気づくため手戻りコストのリスクが高い 創発的設計 実装を進める流れ UserInterface

Slide 35

Slide 35 text

❏ BDD では実際のユーザーの要件に近いところから開発を進 めることで、事前にすべてを設計する必要がなくなり、不 必要なものを作るというリスクを減らすことができる ❏ → Big Design Up Front (BDUF) を避ける 創発的設計 「最初からすべてを理解するのではなく、要件対する議論と理解を 目の前の要件に絞り、見えている要件を単位として外側の界面から ソフトウェアの内側に向かって必要最低限の範囲で開発を進められ るようになったのです(ウォーキングスケルトン)」 (テスト駆動開発 付録C p.292 より)

Slide 36

Slide 36 text

まとめ

Slide 37

Slide 37 text

❏ Selenide は Java 言語で画面自動テストを実装できる ❏ Cucumber は自然言語でテストケースを記述できる ❏ ビジネス側との協働 ❏ Selenide + Cucumber を組み合わせた自動テスト ❏ BDD の実現 ❏ 創発的設計の実現 まとめ

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

❏ Kent Beck (2017) 『テスト駆動開発』 (和田 卓人 訳) オーム社 ❏ Steve Freeman, Nat Pryce (2012) 『実践テスト駆動開発』 (和智 右桂、 高木 正弘 訳) 翔泳社 ❏ サンプルコード (https://github.com/Takaichi00/selenide-cucumber-sample) ❏ Selenide入門 ❏ Selenideノウハウ ❏ Selenide~Javaで超簡単・簡潔にUIテストを書く~ ❏ Selenideを活用したい人に向けて ❏ Javaで簡単にUIテストを書けるSelenideを使おう~Selenideの概要とテストの保守性を上げるPage Objectパターンの紹介 ❏ MavenでWebDriverの管理にはwebdriverextensionsが便利そう ❏ Cucumber のフィーチャの文法 - Gherkin ❏ Page Object Patternで保守性の高いUIテストコードを書こう!【Selenide】 ❏ Anti-patterns (Cucumber official) ❏ Selenide vs Selenium ❏ Selenide Java Library:簡単なことは簡単に,Web UI テスト自動化の敷居を下げ,生産性をあげる 魔法の Wrapper ❏ オープンソースの自動テストツール/Selenideとは ❏ Cucumber Hooks 参考文献