概述

本文是一篇关于使用SeliniumJUnitTestNG编写测试的实践指南。

2. Selenium集成

在这个部分,我们将从一个简单的场景开始:打开浏览器窗口,导航到指定的URL,并在页面上查找期望的内容。

2.1. Maven依赖

pom.xml文件中添加以下依赖:

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.4.0</version>
</dependency>

最新版本可以在Maven中央仓库找到。

2.2. Selenium配置

首先,创建一个新的Java类文件,名为SeleniumConfig

public class SeleniumConfig {

    private WebDriver driver;

    //...

}

由于我们使用的是Selinium 3.x版本,我们需要通过系统属性webdriver.gecko.driver指定可执行的GeckoDriver文件路径(根据您的操作系统)。可以从Geckodriver Github 发布获取最新版本的GeckoDriver。

现在,在构造函数中初始化WebDriver,并设置一个5秒的超时时间,用于等待页面上的元素出现:

public SeleniumConfig() {
    Capabilities capabilities = DesiredCapabilities.firefox();
    driver = new FirefoxDriver(capabilities);
    driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
}

static {
    System.setProperty("webdriver.gecko.driver", findFile("geckodriver.mac"));
}

static private String findFile(String filename) {
   String paths[] = {"", "bin/", "target/classes"};
   for (String path : paths) {
      if (new File(path + filename).exists())
          return path + filename;
   }
   return "";
}

这个配置类包含一些我们现在可以忽略的方法,但在本系列的第二部分我们将更深入地了解它们。

接下来,我们需要实现一个SeleniumExample类:

public class SeleniumExample {

    private SeleniumConfig config;
    private String url = "http://www.baeldung.com/";

    public SeleniumExample() {
        config = new SeleniumConfig();
        config.getDriver().get(url);
    }

    // ...
}

在这里,我们将初始化SeleniumConfig,并设置要导航的目标URL。同样,我们将实现一个简单的API来关闭浏览器和获取页面标题:

public void closeWindow() {
    this.config.getDriver().close();
}

public String getTitle() {
    return this.config.getDriver().getTitle();
}

为了导航到baeldung.com的"关于"部分,我们需要创建一个closeOverlay()方法,检查并关闭主页加载时的弹出层。然后,我们使用getAboutBaeldungPage()方法导航到"关于Baeldung"页面:

public void getAboutBaeldungPage() {
    closeOverlay();
    clickAboutLink();
    clickAboutUsLink();
}

private void closeOverlay() {
    List<WebElement> webElementList = this.config.getDriver()
      .findElements(By.tagName("a"));
    if (webElementList != null) {
       webElementList.stream()
         .filter(webElement -> "Close".equalsIgnoreCase(webElement.getAttribute("title")))
         .filter(WebElement::isDisplayed)
         .findAny()
         .ifPresent(WebElement::click);
    }
}

private void clickAboutLink() {
    Actions actions = new Actions(config.getDriver());
    WebElement aboutElement = this.config.getDriver()
        .findElement(By.id("menu-item-6138"));
        
    actions.moveToElement(aboutElement).perform();
}

private void clickAboutUsLink() {
    WebElement element = this.config.getDriver()
        .findElement(By.partialLinkText("About Baeldung."));
    element.click();
}

我们可以检查显示页面上是否包含所需的信息:

public boolean isAuthorInformationAvailable() {
    return this.config.getDriver()
        .getPageSource()
        .contains("Hey ! I'm Eugen");
}

接下来,我们将用JUnit和TestNG来测试这个类。

3. 使用JUnit

创建一个新的测试类,命名为SeleniumWithJUnitLiveTest:

public class SeleniumWithJUnitLiveTest {

    private static SeleniumExample seleniumExample;
    private String expectedTitle = "About Baeldung | Baeldung";

    // more code goes here...

}

我们将使用org.junit.BeforeClass@BeforeClass注解来进行初始设置。在setUp()方法中,我们将初始化SeleniumExample对象:

@BeforeClass
public static void setUp() {
    seleniumExample = new SeleniumExample();
}

同样,当我们的测试用例完成后,我们应该关闭新打开的浏览器。我们将使用@AfterClass注解来完成清理,当测试用例执行完毕时:

@AfterClass
public static void tearDown() {
    seleniumExample.closeWindow();
}

请注意,我们的SeleniumExample成员变量上带有static修饰符,因为我们需要在setUp()tearDown()静态方法中使用它。@BeforeClass@AfterClass只能在静态方法上被调用。

最后,我们可以创建完整的测试:

@Test
public void whenAboutBaeldungIsLoaded_thenAboutEugenIsMentionedOnPage() {
    seleniumExample.getAboutBaeldungPage();
    String actualTitle = seleniumExample.getTitle();
 
    assertNotNull(actualTitle);
    assertEquals(expectedTitle, actualTitle);
    assertTrue(seleniumExample.isAuthorInformationAvailable());
}

这个测试方法断言网页标题不为null且设置为预期值。此外,我们还会检查页面上包含预期的信息。

当测试运行时,它会在Firefox中打开URL,然后在验证完网页标题和内容后关闭它。

4. 使用TestNG

现在,让我们使用TestNG来运行我们的测试用例或测试套件。

如果你使用的是Eclipse,可以从Eclipse Marketplace下载并安装TestNG插件。

首先,创建一个新的测试类:

public class SeleniumWithTestNGLiveTest {

    private SeleniumExample seleniumExample;
    private String expectedTitle = "About Baeldung | Baeldung";

    // more code goes here...

}

我们将使用org.testng.annotations.BeforeSuite@BeforeSuite注解来实例化我们的SeleniumExample类。setUp()方法将在测试套件激活前运行:

@BeforeSuite
public void setUp() {
    seleniumExample = new SeleniumExample();
}

同样,我们将使用org.testng.annotations.AfterSuite@AfterSuite注解在测试套件完成后关闭我们打开的浏览器:

@AfterSuite
public void tearDown() {
    seleniumExample.closeWindow();
}

最后,让我们实现测试:

@Test
public void whenAboutBaeldungIsLoaded_thenAboutEugenIsMentionedOnPage() {
    seleniumExample.getAboutBaeldungPage();
    String actualTitle = seleniumExample.getTitle();
 
    assertNotNull(actualTitle);
    assertEquals(expectedTitle, actualTitle);
    assertTrue(seleniumExample.isAuthorInformationAvailable());
}

测试套件成功完成后,我们在项目test-output文件夹中会找到HTML和XML报告。这些报告汇总了测试结果。

5. 结论

在这篇简短的文章中,我们专注于使用JUnit和TestNG快速编写Selinium 3的测试。如往常一样,文章的源代码可在GitHub上获取。