java – 访问助手类中的实例变量

免责声明:我来自动态语言背景( Ruby),我正在努力提高我的Java技能.我担心我的问题在这里我在Ruby的背景下思考太多,并且会欣赏一些指针.

问题:

我想知道如何让helper类知道WebDriver实例的存在,而不必一直传递实例.我试图避免这种情况的原因是因为它会导致额外的方法参数和不那么流畅的测试编写.

语境:

我有一个测试用例(LoginIT.java),如下所示:

package com.testerstories.learning.symbiote;

import static com.testerstories.learning.helpers.Selenium.*;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

public class LoginIT {
  WebDriver driver;

  @BeforeTest
  public void startBrowser() {
    driver = new FirefoxDriver();
  }

  @AfterTest
  public void quitBrowser() {
    driver.quit();
  }

  @Test
  public void loginAsAdmin() {
    driver.get("http://localhost:9292");

    withElement("open").click();

    waitForPresence("username");

    withElement("username").sendKeys("admin");
    withElement("password").sendKeys("admin");
    withElement("login-button").submit();

    waitForPresence("notice");

    assertThat(withElement("notice", "className"), equalTo("You are now logged in as admin."));
  }
}

这里要注意的关键方法是对withElement和waitForPresence的调用.这些是在我创建的Selenium类上定义的,并通过顶部的静态导入引用.

这是包含该逻辑的Selenium.java:

package com.testerstories.learning.helpers;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class Selenium {
  public static WebElement withElement(String identifier, String locator) {
    switch (locator) {
        case "className":
            return driver.findElement(By.className(identifier));
        default:
            return withElement(identifier);
    }
  }

  public static WebElement withElement(String identifier) {
    return driver.findElement(By.id(identifier));
  }

  public static void waitForPresence(String identifier, String locator) {
    WebDriverWait wait = new WebDriverWait(driver, 10, 500);

    switch (locator) {
        case "className":
            wait.until(ExpectedConditions.visibilityOfElementLocated(By.className(identifier)));
        default:
            waitForPresence(identifier);
    }
  }

  public static void waitForPresence(String identifier) {
    WebDriverWait wait = new WebDriverWait(driver, 10, 500);
      wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(identifier)));

  }
}

这里的关键问题是引用驱动程序的行.在LoginIT.java中定义这些方法时,这不是问题,因为在驱动程序实例中定义了WebDriver.

我知道我的问题的一个答案是我可以将WebDriver实例传递给每个方法.因此,例如,我可以将此方法签名与withElement一起使用:

public static WebElement withElement(WebDriver driver, String identifier)

我正在添加另一个参数来传递WebDriver实例.但这意味着我的测试逻辑必须如下所示:

withElement(driver, "username").sendKeys("admin");
withElement(driver, "password").sendKeys("admin");
withElement(driver, "login-button").submit();

不是世界末日,但它不那么流利,似乎应该有更好的方式.

题:

有没有更好的办法?

或者我实际上是在正确的轨道上并且应该接受如果我希望帮助方法与测试分开,则必须传入驱动程序引用?从而接受稍微冗长的测试声明?

其他想法:

我能立即想到的另一件事就是我创建了一个仅代表WebDriver本身的第三个类.然后我的测试(LoginIt.java)和我的测试助手(Selenium.java)使用第三个类.我不确定如何最好地实现它,但我也不确定这条路是否有意义.

我这样说是因为看起来如果我这样做,我只是创建一个类来包装WebDriver实例的创建.所以我必须创建一个类,然后获取该类的实例,以便我可以创建WebDriver的实例.好像我在增加复杂性……但也许不是.因此我寻求指针.

最佳答案 另一种方法是允许初始化您的Selenium类.您可以在类构造函数中使用WebDriver引用,而不是使方法是静态的.

package com.testerstories.learning.helpers;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class Selenium {
    private final WebDriver driver;
    public Selenium(WebDriver webDriver) {
        this.driver = webDriver;
    }

    public WebElement withElement(String identifier, String locator) {
        switch (locator) {
            case "className":
                return driver.findElement(By.className(identifier));
            default:
                return withElement(identifier);
        }
    }

    public WebElement withElement(String identifier) {
        return driver.findElement(By.id(identifier));
    }

    public void waitForPresence(String identifier, String locator) {
        WebDriverWait wait = new WebDriverWait(driver, 10, 500);

        switch (locator) {
            case "className":
                wait.until(ExpectedConditions.visibilityOfElementLocated(By.className(identifier)));
            default:
                waitForPresence(identifier);
        }
    }

    public void waitForPresence(String identifier) {
        WebDriverWait wait = new WebDriverWait(driver, 10, 500);
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(identifier)));

    }
}

然后,您的LoginIT.java将使用@Before和驱动程序初始化引用,并将以前的静态调用更改为您站起来的实例:

package com.testerstories.learning.symbiote;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import com.testerstories.learning.helpers.Selenium;

public class LoginIT {
  WebDriver driver;
  Selenium selenium;

  @BeforeTest
  public void startBrowser() {
    driver = new FirefoxDriver();
    selenium = new Selenium(driver);
  }

  @AfterTest
  public void quitBrowser() {
    driver.quit();
  }

  @Test
  public void loginAsAdmin() {
    driver.get("http://localhost:9292");

    selenium.withElement("open").click();

    selenium.waitForPresence("username");

    selenium.withElement("username").sendKeys("admin");
    selenium.withElement("password").sendKeys("admin");
    selenium.withElement("login-button").submit();

    selenium.waitForPresence("notice");

    assertThat(selenium.withElement("notice", "className"), equalTo("You are now logged in as admin."));
  }
}
点赞