黄瓜不是浏览器自动化工具,但它与以下浏览器自动化工具配合得很好。

Selenium WebDriver

WebDriver 旨在提供比其他一些工具更简单、更简洁的编程接口。Selenium WebDriver 更好地支持动态网页,其中页面的元素可能会发生变化,而页面本身不会重新加载。WebDriver 的目标是提供一个精心设计的面向对象 API,以改进对现代高级 Web 应用程序测试问题的支持。

Selenium-WebDriver 可用于多种编程语言,包括 Java、JavaScript、Ruby 和 Kotlin。

让我们通过将 Selenium WebDriver 入门 转换为 UI 测试示例,来看看使用 Selenium WebDriver 的黄瓜示例。

我们可以将示例表达为以下场景

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

适用于 Ruby 的浏览器自动化工具

Watir

Capybara

提示和技巧

失败时截屏

在场景失败时截取屏幕截图,可能有助于您找出问题所在。要在失败时截取屏幕截图,您可以配置 after 钩子

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");
            }
        });
    }
});
# 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

多个浏览器

黄瓜可以在运行时加载的配置属性的基础上,使用不同的浏览器运行您的场景

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

然后,在运行黄瓜时定义 browser 属性:

browser=chrome cucumber

您可以帮助我们改进此文档。 编辑此页面