可以使用 Cucumber runner 执行 TestNG 跨浏览器测试吗?
Can a TestNG cross-browser test be executed with Cucumber runner?
我正在使用带有 Cucumber 的 Selenium Webdriver。使用该组合,我的测试按预期工作。为了实现跨浏览器测试,我加入了TestNG框架。为了验证我的跨浏览器测试是否运行良好,我 运行 只使用 TestNG,不使用 Cucumber。它 运行 在 Chrome 和 Firefox 浏览器中都完美无缺。
public class WebTest {
WebDriver driver = null;
BasePageWeb basePage;
public String browser;
@Parameters({ "Browser" })
public WebTest(String browser) {
this.browser = browser;
}
@BeforeClass
public void navigateToUrl() {
switch (browser) {
case "CHROME":
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
break;
case "FF":
WebDriverManager.firefoxdriver().setup();
driver = new FirefoxDriver();
break;
default:
driver = null;
break;
}
driver.get("https://demosite.executeautomation.com/Login.html");
}
@Test
public void loginToWebApp() {
basePage = new BasePageWeb(driver);
basePage.enterUsername("admin")
.enterPassword("admin")
.clickLoginButton();
driver.quit();
}
}
testng.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="tests" thread-count="5">
<test name="Chrome Test">
<parameter name="Browser" value="CHROME"/>
<classes>
<class name="tests.web.WebTest"/>
</classes>
</test>
<test name="Firefox Test">
<parameter name="Browser" value="FF"/>
<classes>
<class name="tests.web.WebTest"/>
</classes>
</test>
</suite>
我需要将 TestNG 测试与我的 Cucumber 设置集成,这样我就可以 运行 使用 Cucumber 进行整个测试。为此,我向 POM 添加了 cucumber-testng 依赖项,并创建了一个扩展 AbstractCucumberTestNG class 的 Cucumber 运行ner。我指定了特征文件的位置和步骤定义。步骤定义映射到 TestNG 测试。
黄瓜运行小人:
@CucumberOptions(
plugin = {"pretty", "html:target/surefire-reports/cucumber",
"json:target/surefire-reports/cucumberOriginal.json"},
glue = {"stepdefinitions"},
tags = "@web-1",
features = {"src/test/resources/features/web.feature"})
public class RunCucumberNGTest extends AbstractTestNGCucumberTests {
}
步骤定义:
public class WebAppStepDefinitions {
private final WebTest webTest = new WebTest("CHROME"); //create an object of the class holding the testng test. If I change the argument to FF, the test will run only on Firefox
static boolean prevScenarioFailed = false;
@Before
public void setUp() {
if (prevScenarioFailed) {
throw new IllegalStateException("Previous scenario failed!");
}
}
@After()
public void stopExecutionAfterFailure(Scenario scenario) throws Exception {
prevScenarioFailed = scenario.isFailed();
}
@Given("^I have navigated to the web url \"([^\"]*)\"$")
public void navigateToUrl(String url) { test
webTest.navigateToUrl(url); //calling the first method holding the testng
}
@When("^I log into my web account with valid credentials as specicified in (.*) and (.*)$")
public void logintoWebApp(String username, String password) {
webTest.loginToWebApp(username, password); //calling the second method holding the testng
}
}
在 运行 上 class,测试只在一个浏览器中执行 (Chrome)。不知何故,Firefox 在构建过程中迷失了方向。我怀疑我从另一个 class 错误地调用了参数化的 TestNG 方法。如何才能调用成功?
对于使用 Cucumber 的 运行 TestNG 测试,您必须在 testng.xml 中定义 Test 运行ner classes。 =18=]
你的 测试 运行ner class 是 RunCucumberNGTest
.
所以 xml 应该是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="tests" thread-count="5">
<test name="Chrome Test">
<parameter name="Browser" value="CHROME"/>
<classes>
<class name="some.package.name.RunCucumberNGTest"/>
</classes>
</test>
<test name="Firefox Test">
<parameter name="Browser" value="FF"/>
<classes>
<class name="some.package.name.RunCucumberNGTest"/>
</classes>
</test>
</suite>
由此xml我看到下一个要求:
运行相同的一组测试,但参数值不同。
这应该并行工作,所以这应该是 thread-safe。
1 为测试引入TestNG参数运行ner class
@CucumberOptions(
plugin = {"pretty", "html:target/surefire-reports/cucumber",
"json:target/surefire-reports/cucumberOriginal.json"},
glue = {"stepdefinitions"},
tags = "@web-1",
features = {"src/test/resources/features/web.feature"})
public class RunCucumberNGTest extends AbstractTestNGCucumberTests {
// static thread-safe container to keep the browser value
public final static ThreadLocal<String> BROWSER = new ThreadLocal<>();
@BeforeTest
@Parameters({"Browser"})
public void defineBrowser(String browser) {
//put browser value to thread-safe container
RunCucumberNGTest.BROWSER.set(browser);
System.out.println(browser);
}
}
2 使用步骤定义中的值 class
public class WebAppStepDefinitions {
private WebTest webTest;
static boolean prevScenarioFailed = false;
@Before
public void setUp() {
if (prevScenarioFailed) {
throw new IllegalStateException("Previous scenario failed!");
}
//get the browser value for current thread
String browser = RunCucumberNGTest.BROWSER.get();
System.out.println("WebAppStepDefinitions: " + browser);
//create an object of the class holding the testng test. If I change the argument to FF, the test will run only on Firefox
webTest = new WebTest(browser);
}
@After
public void stopExecutionAfterFailure(Scenario scenario) throws Exception {
prevScenarioFailed = scenario.isFailed();
}
@Given("^I have navigated to the web url \"([^\"]*)\"$")
public void navigateToUrl(String url) {
webTest.navigateToUrl(url); //calling the first method holding the testng
}
@When("^I log into my web account with valid credentials as specicified in (.*) and (.*)$")
public void logintoWebApp(String username, String password) {
webTest.loginToWebApp(username, password); //calling the second method holding the testng
}
}
注意: 应从 WebTest
class 中删除所有 TestNG 注释,它们将不起作用,也不是必需的。 WebTest
被 WebAppStepDefinitions
class 显式使用,所有显式调用的方法均未被 TestNG 调用。
因此,根据您的初始要求:
public class WebTest {
WebDriver driver = null;
BasePageWeb basePage;
public String browser;
public WebTest(String browser) {
this.browser = browser;
}
public void navigateToUrl(String url) {
switch (browser) {
case "CHROME":
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
break;
case "FF":
WebDriverManager.firefoxdriver().setup();
driver = new FirefoxDriver();
break;
default:
driver = null;
break;
}
driver.get(url);
}
public void loginToWebApp(String username, String password) {
basePage = new BasePageWeb(driver);
basePage.enterUsername(username)
.enterPassword(password)
.clickLoginButton();
driver.quit();
}
我正在使用带有 Cucumber 的 Selenium Webdriver。使用该组合,我的测试按预期工作。为了实现跨浏览器测试,我加入了TestNG框架。为了验证我的跨浏览器测试是否运行良好,我 运行 只使用 TestNG,不使用 Cucumber。它 运行 在 Chrome 和 Firefox 浏览器中都完美无缺。
public class WebTest {
WebDriver driver = null;
BasePageWeb basePage;
public String browser;
@Parameters({ "Browser" })
public WebTest(String browser) {
this.browser = browser;
}
@BeforeClass
public void navigateToUrl() {
switch (browser) {
case "CHROME":
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
break;
case "FF":
WebDriverManager.firefoxdriver().setup();
driver = new FirefoxDriver();
break;
default:
driver = null;
break;
}
driver.get("https://demosite.executeautomation.com/Login.html");
}
@Test
public void loginToWebApp() {
basePage = new BasePageWeb(driver);
basePage.enterUsername("admin")
.enterPassword("admin")
.clickLoginButton();
driver.quit();
}
}
testng.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="tests" thread-count="5">
<test name="Chrome Test">
<parameter name="Browser" value="CHROME"/>
<classes>
<class name="tests.web.WebTest"/>
</classes>
</test>
<test name="Firefox Test">
<parameter name="Browser" value="FF"/>
<classes>
<class name="tests.web.WebTest"/>
</classes>
</test>
</suite>
我需要将 TestNG 测试与我的 Cucumber 设置集成,这样我就可以 运行 使用 Cucumber 进行整个测试。为此,我向 POM 添加了 cucumber-testng 依赖项,并创建了一个扩展 AbstractCucumberTestNG class 的 Cucumber 运行ner。我指定了特征文件的位置和步骤定义。步骤定义映射到 TestNG 测试。
黄瓜运行小人:
@CucumberOptions(
plugin = {"pretty", "html:target/surefire-reports/cucumber",
"json:target/surefire-reports/cucumberOriginal.json"},
glue = {"stepdefinitions"},
tags = "@web-1",
features = {"src/test/resources/features/web.feature"})
public class RunCucumberNGTest extends AbstractTestNGCucumberTests {
}
步骤定义:
public class WebAppStepDefinitions {
private final WebTest webTest = new WebTest("CHROME"); //create an object of the class holding the testng test. If I change the argument to FF, the test will run only on Firefox
static boolean prevScenarioFailed = false;
@Before
public void setUp() {
if (prevScenarioFailed) {
throw new IllegalStateException("Previous scenario failed!");
}
}
@After()
public void stopExecutionAfterFailure(Scenario scenario) throws Exception {
prevScenarioFailed = scenario.isFailed();
}
@Given("^I have navigated to the web url \"([^\"]*)\"$")
public void navigateToUrl(String url) { test
webTest.navigateToUrl(url); //calling the first method holding the testng
}
@When("^I log into my web account with valid credentials as specicified in (.*) and (.*)$")
public void logintoWebApp(String username, String password) {
webTest.loginToWebApp(username, password); //calling the second method holding the testng
}
}
在 运行 上 class,测试只在一个浏览器中执行 (Chrome)。不知何故,Firefox 在构建过程中迷失了方向。我怀疑我从另一个 class 错误地调用了参数化的 TestNG 方法。如何才能调用成功?
对于使用 Cucumber 的 运行 TestNG 测试,您必须在 testng.xml 中定义 Test 运行ner classes。 =18=]
你的 测试 运行ner class 是 RunCucumberNGTest
.
所以 xml 应该是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="tests" thread-count="5">
<test name="Chrome Test">
<parameter name="Browser" value="CHROME"/>
<classes>
<class name="some.package.name.RunCucumberNGTest"/>
</classes>
</test>
<test name="Firefox Test">
<parameter name="Browser" value="FF"/>
<classes>
<class name="some.package.name.RunCucumberNGTest"/>
</classes>
</test>
</suite>
由此xml我看到下一个要求:
运行相同的一组测试,但参数值不同。
这应该并行工作,所以这应该是 thread-safe。
1 为测试引入TestNG参数运行ner class
@CucumberOptions(
plugin = {"pretty", "html:target/surefire-reports/cucumber",
"json:target/surefire-reports/cucumberOriginal.json"},
glue = {"stepdefinitions"},
tags = "@web-1",
features = {"src/test/resources/features/web.feature"})
public class RunCucumberNGTest extends AbstractTestNGCucumberTests {
// static thread-safe container to keep the browser value
public final static ThreadLocal<String> BROWSER = new ThreadLocal<>();
@BeforeTest
@Parameters({"Browser"})
public void defineBrowser(String browser) {
//put browser value to thread-safe container
RunCucumberNGTest.BROWSER.set(browser);
System.out.println(browser);
}
}
2 使用步骤定义中的值 class
public class WebAppStepDefinitions {
private WebTest webTest;
static boolean prevScenarioFailed = false;
@Before
public void setUp() {
if (prevScenarioFailed) {
throw new IllegalStateException("Previous scenario failed!");
}
//get the browser value for current thread
String browser = RunCucumberNGTest.BROWSER.get();
System.out.println("WebAppStepDefinitions: " + browser);
//create an object of the class holding the testng test. If I change the argument to FF, the test will run only on Firefox
webTest = new WebTest(browser);
}
@After
public void stopExecutionAfterFailure(Scenario scenario) throws Exception {
prevScenarioFailed = scenario.isFailed();
}
@Given("^I have navigated to the web url \"([^\"]*)\"$")
public void navigateToUrl(String url) {
webTest.navigateToUrl(url); //calling the first method holding the testng
}
@When("^I log into my web account with valid credentials as specicified in (.*) and (.*)$")
public void logintoWebApp(String username, String password) {
webTest.loginToWebApp(username, password); //calling the second method holding the testng
}
}
注意: 应从 WebTest
class 中删除所有 TestNG 注释,它们将不起作用,也不是必需的。 WebTest
被 WebAppStepDefinitions
class 显式使用,所有显式调用的方法均未被 TestNG 调用。
因此,根据您的初始要求:
public class WebTest {
WebDriver driver = null;
BasePageWeb basePage;
public String browser;
public WebTest(String browser) {
this.browser = browser;
}
public void navigateToUrl(String url) {
switch (browser) {
case "CHROME":
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
break;
case "FF":
WebDriverManager.firefoxdriver().setup();
driver = new FirefoxDriver();
break;
default:
driver = null;
break;
}
driver.get(url);
}
public void loginToWebApp(String username, String password) {
basePage = new BasePageWeb(driver);
basePage.enterUsername(username)
.enterPassword(password)
.clickLoginButton();
driver.quit();
}