Cucumber はブラウザ自動化ツールではありませんが、以下のブラウザ自動化ツールと連携して動作します。
Selenium WebDriver
WebDriver は、他のツールよりもシンプルで簡潔なプログラミングインターフェースを提供するように設計されています。Selenium WebDriver は、ページ自体がリロードされることなくページの要素が変更される可能性のある動的な Web ページをより適切にサポートします。WebDriver の目標は、最新の高度な Web アプリケーションテストの問題に対するサポートが向上した、適切に設計されたオブジェクト指向 API を提供することです。
Selenium-WebDriver は、Java、JavaScript、Ruby、Kotlin など、複数のプログラミング言語で使用できます。
Selenium WebDriver はじめを変換することで、UI テストで Selenium WebDriver を使用する Cucumber の例を見てみましょう。
この例は、次のシナリオとして表すことができます。
Scenario: Finding some cheese
Given I am on the Google search page
When I search for "Cheese!"
Then the page title should start with "cheese"
package com.example;
import io.cucumber.java.After;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
public class ExampleSteps {
private final WebDriver driver = new FirefoxDriver();
@Given("I am on the Google search page")
public void I_visit_google() {
driver.get("https://www.google.com");
}
@When("I search for {string}")
public void search_for(String query) {
WebElement element = driver.findElement(By.name("q"));
// Enter something to search for
element.sendKeys(query);
// Now submit the form. WebDriver will find the form for us from the element
element.submit();
}
@Then("the page title should start with {string}")
public void checkTitle(String titleStartsWith) {
// Google's search is rendered dynamically with JavaScript
// Wait for the page to load timeout after ten seconds
new WebDriverWait(driver,10L).until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
return d.getTitle().toLowerCase().startsWith(titleStartsWith);
}
});
}
@After()
public void closeBrowser() {
driver.quit();
}
}
package com.example
import io.cucumber.java8.Scenario
import io.cucumber.java8.En
import org.openqa.selenium.By
import org.openqa.selenium.WebDriver
import org.openqa.selenium.WebElement
import org.openqa.selenium.support.ui.WebDriverWait
class ExampleSteps: En {
lateinit var driver: WebDriver
init {
Given("I am on the Google search page") {
driver.get("https:\\www.google.com")
}
When("I search for {string}") { query: String ->
val element: WebElement = driver.findElement(By.name("q"))
// Enter something to search for
element.sendKeys(query)
// Now submit the form. WebDriver will find the form for us from the element
element.submit()
}
Then("the page title should start with {string}") { titleStartsWith: String ->
// Google's search is rendered dynamically with JavaScript
// Wait for the page to load timeout after ten seconds
WebDriverWait(driver, 10L).until { d ->
d.title.toLowerCase().startsWith(titleStartsWith)
}
}
After { scenario: Scenario ->
driver.quit()
}
}
}
const { Given, When, Then, AfterAll } = require('cucumber');
const { Builder, By, Capabilities, Key } = require('selenium-webdriver');
const { expect } = require('chai');
require("chromedriver");
// driver setup
const capabilities = Capabilities.chrome();
capabilities.set('chromeOptions', { "w3c": false });
const driver = new Builder().withCapabilities(capabilities).build();
Given('I am on the Google search page', async function () {
await driver.get('http://www.google.com');
});
When('I search for {string}', async function (searchTerm) {
const element = await driver.findElement(By.name('q'));
element.sendKeys(searchTerm, Key.RETURN);
element.submit();
});
Then('the page title should start with {string}', {timeout: 60 * 1000}, async function (searchTerm) {
const title = await driver.getTitle();
const isTitleStartWithCheese = title.toLowerCase().lastIndexOf(`${searchTerm}`, 0) === 0;
expect(isTitleStartWithCheese).to.equal(true);
});
AfterAll(async function(){
await driver.quit();
});
require 'rubygems'
require 'selenium-webdriver'
Given(/^I am on the Google search page$/) do
driver = Selenium::WebDriver.for :firefox
driver.get "http://google.com"
end
When(/^I search for "([^"]*)"$/) do
element = driver.find_element(name: "q")
element.send_keys "Cheese!"
element.submit
end
Then(/^the page title should start with "([^"]*)"$/) do
wait = Selenium::WebDriver::Wait.new(timeout: 10)
wait.until { driver.title.downcase.start_with? "cheese!" }
puts "Page title is #{driver.title}"
browser.close
end
Selenium Webdriver の詳細情報はこちらをご覧ください。
JVM向けブラウザ自動化ツール
Serenity BDD
Serenity BDD は、より構造化され、保守しやすい自動受け入れ基準を作成するのに役立つオープンソースのレポートライブラリです。Serenity は、テスト結果だけでなく、テストされた機能もレポートする、リッチで意味のあるテストレポート(または「リビングドキュメント」)も生成します。
Cucumber-JVM と Serenity を使用した詳細なチュートリアルはこちらにあり、Serenity の詳細情報は公式 Web サイトにあります。
Serenity BDD は、より構造化され、保守しやすい自動受け入れ基準を作成するのに役立つオープンソースのレポートライブラリです。Serenity は、テスト結果だけでなく、テストされた機能もレポートする、リッチで意味のあるテストレポート(または「リビングドキュメント」)も生成します。
Cucumber-JVM と Serenity を使用した詳細なチュートリアルはこちらにあり、Serenity の詳細情報は公式 Web サイトにあります。
Serenity は JVM 言語でのみ動作します。Serenity は JVM 言語でのみ動作します。Ruby向けブラウザ自動化ツール
Watir
Watir(「ウォーター」と発音)は、Web ブラウザを自動化するためのオープンソース(BSD)の Ruby ライブラリファミリです。読みやすく、保守しやすいテストを作成できます。シンプルで柔軟性があります。
Watir は、人が行うのと同じ方法でブラウザを操作します。リンクをクリックし、フォームに入力し、ボタンを押します。Watir は、期待されるテキストがページに表示されるかどうかなど、結果もチェックします。
Watir は Ruby ライブラリファミリですが、開発に使用されているテクノロジーに関係なく、アプリケーションをサポートします。Watir は Windows 上の Internet Explorer のみをサポートしますが、Watir-WebDriver は単一ブラウザテストの問題を解決し、Chrome、Firefox、Internet Explorer、Opera をサポートし、ヘッドレスモード(HTMLUnit)でも実行できます。
それでは、Watir を使用したサンプル UI テストプログラムを見てみましょう。
require "rubygems" require "rspec" require "watir" describe "google.com" do let(:browser) { @browser ||= Watir::Browser.new :firefox } before { browser.goto "http://google.com" } browser.text_field(name: "q").set "watir" browser.button.click browser.div(id: "resultStats").wait_until browser.title.should == "watir - Google Search" after { browser.close } end
それでは、このテストに Cucumber を組み込んでみましょう。
機能: 検索 Google を使用するには、ユーザーがコンテンツを検索できる必要があります シナリオ: 用語の検索 前提条件: クエリに「watir」と入力しました 操作: 「検索」をクリックします 確認: 結果が表示されます
require "watir" require "rspec/expectations" 前提条件(/^クエリに「([^"]*)」と入力しました$/) do |term| @browser ||= Watir::Browser.new :firefox @browser.goto "google.com" @browser.text_field(name: "q").set term end 操作(/^「([^"]*)」をクリックします$/) do @browser.button.click end 確認(/^結果が表示されます$/) do @browser.div(id: "resultStats").wait_until_present @browser.close end
Watir の詳細情報はこちらをご覧ください。
Watir は Ruby でのみ動作します。Watir は Ruby でのみ動作します。Watir は Ruby でのみ動作します。Capybara
Cucumber-Rails は、Capybara(script/generate cucumber --capybara
)を使用したビュー統合テストのサポートが事前に設定されています。
特に指示がない限り、Cucumber-Rails インストールジェネレーターは Capybara に必要なサポートファイルを設定します。
Capybara は cucumber-rails での HTML ビューのテスト方法として推奨されていますが、Rails 独自の組み込み MiniTest/Test::Unit
とはうまく連携しません。特に、Capybara が Cucumber World に必要な場合は常に、Rails Test::Unit
の response.body
メソッドが削除されます。Capybara は Nokogiri に依存しており、Nokogiri は CSS タグではなく XML を優先します。この動作は ./features/support/env.rb
でオーバーライドできます。
Capybara の詳細情報はこちらをご覧ください。
Capybara は Ruby でのみ動作します。Capybara は Ruby でのみ動作します。Capybara は Ruby でのみ動作します。ヒントとコツ
失敗時のスクリーンショット
シナリオが失敗したときにスクリーンショットを撮ると、何が問題だったのかを把握するのに役立つ場合があります。失敗時にスクリーンショットを撮るには、after フックを設定できます。
以下は、失敗したシナリオのWebDriverでスクリーンショットを撮り、Cucumber のレポートに埋め込む方法の例です。
以下は、失敗したシナリオのWebDriverでスクリーンショットを撮り、Cucumber のレポートに埋め込む方法の例です。
以下は、失敗したシナリオのWebDriverでスクリーンショットを撮り、Cucumber のレポートに埋め込む方法の例です。
if (scenario.isFailed()) {
byte[] screenshot = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.BYTES);
scenario.attach(screenshot, "image/png", "name");
}
if (scenario.isFailed()) {
val screenshot = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.BYTES)
scenario.attach(screenshot, "image/png", "name")
}
After(function (scenario) {
if (scenario.result.status === Status.FAILED) {
var world = this;
return webDriver.takeScreenshot().then(function(screenShot, error) {
if (!error) {
world.attach(screenShot, "image/png");
}
});
}
});
以下は、失敗したシナリオのCapybaraでスクリーンショットを撮り、Cucumber のレポートに埋め込む方法の例です。
# Available scenario methods: #failed?, #passed?, and #exception
if scenario.failed?
path = "html-report/#{scenario.__id__}.html"
page.driver.browser.save_screenshot(path)
attach(path, "image/png")
end
複数のブラウザ
Cucumber は、実行時にロードされる構成プロパティに基づいて、さまざまなブラウザでシナリオを実行できます。
Capybara.register_driver :selenium do |app|
browser = (ENV['browser'] || 'firefox').to_sym
Capybara::Selenium::Driver.new(app, browser: browser)
end
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class WebDriverFactory {
public static WebDriver createWebDriver() {
String webdriver = System.getProperty("browser", "firefox");
switch(webdriver) {
case "firefox":
return new FirefoxDriver();
case "chrome":
return new ChromeDriver();
default:
throw new RuntimeException("Unsupported webdriver: " + webdriver);
}
}
}
// TODO: Convert Java example to Kotlin
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class WebDriverFactory {
public static WebDriver createWebDriver() {
String webdriver = System.getProperty("browser", "firefox");
switch(webdriver) {
case "firefox":
return new FirefoxDriver();
case "chrome":
return new ChromeDriver();
default:
throw new RuntimeException("Unsupported webdriver: " + webdriver);
}
}
}
// TODO
次に、Cucumber を実行するときに `browser` プロパティを定義します:
browser=chrome cucumber
mvn test -Dbrowser=chrome
Serenity を使用している場合は、`driver` システムプロパティを渡します(追加のコーディングは不要です)。
mvn test -Ddriver=chrome
mvn test -Dbrowser=chrome
Serenity を使用している場合は、`driver` システムプロパティを渡します(追加のコーディングは不要です)。
mvn test -Ddriver=chrome
// TODO: JavaScript で引数を渡す方法