我试图使用Page Factory Model和Cucumber自动化一些示例测试方案,但是当我尝试运行一个测试用例时,似乎不明白为什么要使用多个驱动程序实例。
当我尝试仅通过Runner.java文件运行测试用例1
package execution;
import java.io.File;
import org.junit.AfterClass;
import org.junit.runner.RunWith;
import com.cucumber.listener.Reporter;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
@RunWith(Cucumber.class)
@CucumberOptions(features = "D:\\Eclipse Wokspace\\EcommerceProject\\Features\\Test1.feature",
glue = { "stepDefinition" },
plugin = { "html:target/cucumber-html-report",
"pretty:target/cucumber-pretty.txt", "usage:target/cucumber-usage.json",
"junit:target/cucumber-results.xml","com.cucumber.listener.ExtentCucumberFormatter:target/cucumber-reports/report.html" },
dryRun = false,
monochrome = true,
strict = true)
public class Runner {
@AfterClass
public static void writeExtentReport() {
Reporter.loadXMLConfig(
new File("D:\\Eclipse Wokspace\\EcommerceProject\\src\\test\\resources\\extent-config.xml"));
Reporter.setSystemInfo("User Name", System.getProperty("user.name"));
Reporter.setSystemInfo("Time Zone", System.getProperty("user.timezone"));
Reporter.setSystemInfo("Machine", "Windows 10 " + "64 Bit");
Reporter.setSystemInfo("Selenium", "3.7.0");
Reporter.setSystemInfo("Maven", "3.5.2");
Reporter.setSystemInfo("Java Version", "1.8.0_151");
}
}
从下面的日志中可见,另外两个步骤定义类的@Before和@After也似乎被调用
2018-08-05 14:16:16,358 INFO [main] SameCostSteps:25 - ************* Test Case 2 Begin ***************
2018-08-05 14:16:31,264 INFO [main] HomePage:17 - PageFactory setup of HomePage
2018-08-05 14:16:31,321 DEBUG [main] HomePage:22 - Click on Mobile Link
2018-08-05 14:16:33,077 INFO [main] HomePage:24 - Navigating to Mobile Page
2018-08-05 14:16:33,083 INFO [main] MobilePage:35 - PageFactory setup of MobilePage
2018-08-05 14:16:33,123 INFO [main] CartLimitSteps:26 - ***************************************************************
2018-08-05 14:16:33,126 INFO [main] CartLimitSteps:27 - ******************** Test Case 3 Begin ************************
2018-08-05 14:16:33,127 INFO [main] CartLimitSteps:28 - ***************************************************************
2018-08-05 14:16:47,370 INFO [main] HomePage:17 - PageFactory setup of HomePage
2018-08-05 14:16:47,371 DEBUG [main] HomePage:22 - Click on Mobile Link
2018-08-05 14:16:48,771 INFO [main] HomePage:24 - Navigating to Mobile Page
2018-08-05 14:16:48,773 INFO [main] MobilePage:35 - PageFactory setup of MobilePage
2018-08-05 14:16:48,777 INFO [main] SortByNameSteps:24 - ************* Test Case 1 Begin ***************
2018-08-05 14:17:01,832 INFO [main] HomePage:17 - PageFactory setup of HomePage
2018-08-05 14:17:01,833 DEBUG [main] HomePage:22 - Click on Mobile Link
2018-08-05 14:17:03,563 INFO [main] HomePage:24 - Navigating to Mobile Page
2018-08-05 14:17:03,567 INFO [main] MobilePage:35 - PageFactory setup of MobilePage
2018-08-05 14:17:04,411 INFO [main] SortByNameSteps:40 - Retrieving initial unsorted product list
2018-08-05 14:17:04,411 INFO [main] MobilePage:47 - Collecting a list of Products
2018-08-05 14:17:04,872 INFO [main] MobilePage:41 - Selecting value from the dropdown list
2018-08-05 14:17:06,332 INFO [main] SortByNameSteps:48 - Retrieving final sorted list
2018-08-05 14:17:06,333 INFO [main] MobilePage:47 - Collecting a list of Products
2018-08-05 14:17:06,453 INFO [main] SortByNameSteps:51 - Sorting the unsorted array string by Name
2018-08-05 14:17:06,454 INFO [main] SortByNameSteps:53 - Verifying that the products have been sorted by Name
2018-08-05 14:17:06,454 INFO [main] MobilePage:58 - Verifying that the products have been sorted by Name
2018-08-05 14:17:06,459 INFO [main] SortByNameSteps:57 - ############# Test Case 1 Passed ###########
2018-08-05 14:17:06,463 INFO [main] SameCostSteps:33 - ************* Test Case 2 End ******************
2018-08-05 14:17:09,747 INFO [main] CartLimitSteps:37 - ***************************************************************
2018-08-05 14:17:09,749 INFO [main] CartLimitSteps:38 - ******************** Test Case 3 End ************************
2018-08-05 14:17:09,750 INFO [main] CartLimitSteps:39 - ***************************************************************
2018-08-05 14:17:09,770 INFO [main] SortByNameSteps:33 - ************* Test Case 1 End ***************
从@Before和@After上方的日志中可以看到,所有步骤定义类都在执行,甚至我只运行Test1.feature文件。
我似乎不明白为什么会这样,因为它导致不必要地打开许多浏览器实例。
其他类的代码如下:
页面工厂类:
A) HomePage.java
package pageFactory;
import org.apache.log4j.Logger;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import Util.BasePage;
public class HomePage extends BasePage{
Logger log = Logger.getLogger(HomePage.class);
@FindBy(xpath="//*[@id=\"nav\"]/ol/li[1]/a")
WebElement mobileLink;
public HomePage() {
log.info("PageFactory setup of HomePage");
PageFactory.initElements(driver,this);
}
public MobilePage clickMobile() {
log.debug("Click on Mobile Link");
mobileLink.click();
log.info("Navigating to Mobile Page");
return new MobilePage();
}
}
B) MobilePage.java
package pageFactory;
import java.util.Arrays;
import java.util.List;
import org.apache.log4j.Logger;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.Select;
import org.testng.Assert;
import Util.BasePage;
public class MobilePage extends BasePage {
Logger log = Logger.getLogger(MobilePage.class);
@FindBy(xpath = "//*[@id=\"top\"]/body/div/div/div[2]/div/div[2]/div[1]/div[3]/div[1]/div[1]/div/select")
WebElement SortBy;
@FindBy(xpath = "//h2[@class='product-name']/a")
List<WebElement> products;
@FindBy(xpath = "//*[@id=\"product-price-1\"]/span")
WebElement xperiaPrice;
@FindBy(id="product-collection-image-1")
WebElement xperiaImg;
@FindBy(xpath = "//*[@id=\"top\"]/body/div/div/div[2]/div/div[2]/div[1]/div[3]/ul/li[1]/div/div[3]/button")
WebElement addToCartBtn;
public MobilePage() {
log.info("PageFactory setup of MobilePage");
PageFactory.initElements(driver, this);
}
public void sortByIndex(int val) {
Select dlSort = new Select(SortBy);
log.info("Selecting value from the dropdown list");
dlSort.selectByIndex(val);
}
public String[] retrieveProductNames() {
log.info("Collecting a list of Products");
String[] productList = new String[3];
int i = 0;
for (WebElement el : products) {
productList[i] = el.getText();
i++;
}
return productList;
}
public void verifySorting(String[] array1, String[] array2) {
log.info("Verifying that the products have been sorted by Name");
Assert.assertTrue(Arrays.equals(array1, array2), "The products have not been sorted proerly");
}
public String getXperiaPrice() {
return xperiaPrice.getText();
}
public XperiaPage clickOnXperia() {
xperiaImg.click();
return new XperiaPage();
}
public ShoppingCartPage addToCart() {
addToCartBtn.click();
return new ShoppingCartPage();
}
}
C)XperiaPage.java
package pageFactory;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import Util.BasePage;
public class XperiaPage extends BasePage{
@FindBy(xpath = "//*[@id=\"product-price-1\"]/span")
WebElement xperiaPrice;
public XperiaPage() {
PageFactory.initElements(driver,this);
}
public String getXperiaPrice() {
return xperiaPrice.getText();
}
}
步骤定义文件
A)测试案例1
package stepDefinition;
import java.util.Arrays;
import org.apache.log4j.Logger;
import Util.BasePage;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import pageFactory.HomePage;
import pageFactory.MobilePage;
public class SortByNameSteps {
public HomePage objHomePage;
public MobilePage objMobilePage;
public Logger log = Logger.getLogger(SortByNameSteps.class);
public String[] unsorted;
public String[] sorted;
@Before
public void setup() {
log.info("************* Test Case 1 Begin ***************");
BasePage.initialization();
objHomePage = new HomePage();
objMobilePage = objHomePage.clickMobile();
}
@After
public void tearDown() {
log.info("************* Test Case 1 End ***************");
BasePage.closeSession();
}
@When("^Select Name from the DropDownList$")
public void select_Name_from_the_DropDownList() throws Throwable {
// Write code here that turns the phrase above into concrete actions
log.info("Retrieving initial unsorted product list");
unsorted = objMobilePage.retrieveProductNames();
objMobilePage.sortByIndex(1);
}
@Then("^Verify that the Products have been sorted by Name$")
public void verify_that_the_Products_have_been_sorted_by_Name() throws Throwable {
// Write code here that turns the phrase above into concrete actions
log.info("Retrieving final sorted list");
sorted = objMobilePage.retrieveProductNames();
log.info("Sorting the unsorted array string by Name");
Arrays.sort(unsorted);
log.info("Verifying that the products have been sorted by Name");
try {
objMobilePage.verifySorting(unsorted, sorted);
log.info("############# Test Case 1 Passed ###########");
}
catch (Exception ex) {
log.info("############# Test Case 1 Failed ###########");
}
}
}
B)测试案例2
package stepDefinition;
import org.apache.log4j.Logger;
import org.testng.Assert;
import Util.BasePage;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import pageFactory.HomePage;
import pageFactory.MobilePage;
import pageFactory.XperiaPage;
public class SameCostSteps {
public HomePage home;
public MobilePage mobile;
public XperiaPage xperia;
public String detailCost;
public String listCost;
public Logger log = Logger.getLogger(SameCostSteps.class);
@Before
public void tearUp() {
log.info("************* Test Case 2 Begin ***************");
BasePage.initialization();
home = new HomePage();
mobile = home.clickMobile();
}
@After
public void tearDown() {
log.info("************* Test Case 2 End ******************");
BasePage.closeSession();
}
@When("^Read the cost of Sony Xperia$")
public void read_the_cost_of_Sony_Xperia() throws Throwable {
// Write code here that turns the phrase above into concrete actions
log.info("Fetching cost of product on List Page");
listCost = mobile.getXperiaPrice();
}
@When("^Click on Sony Xperia Mobile$")
public void click_on_Sony_Xperia_Mobile() throws Throwable {
// Write code here that turns the phrase above into concrete actions
log.info("Clicking on Xperia");
xperia = mobile.clickOnXperia();
}
@When("^Read Sony Xperia Cost on Details Page$")
public void read_Sony_Xperia_Cost_on_Details_Page() throws Throwable {
// Write code here that turns the phrase above into concrete actions
log.info("Fetching cost of product on Details Page");
detailCost = xperia.getXperiaPrice();
}
@Then("^Verify That both the prices are same$")
public void verify_That_both_the_prices_are_same() throws Throwable {
// Write code here that turns the phrase above into concrete actions
log.info("Verifying that the cost of products on both pages is same");
try {
Assert.assertEquals(detailCost, listCost);
log.info("############# Test Case 2 Passed ###########");
}
catch (Exception ex) {
log.info("Price of Xperia in List and Details Page is not same");
log.info("############# Test Case 2 Failed ###########");
}
}
}
基本页面类
package Util;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class BasePage {
public static WebDriver driver = null;
public static Properties prop;
public static void initialization() {
System.setProperty("webdriver.gecko.driver", util.FFDRIVER_PATH);
driver = new FirefoxDriver();
driver.manage().deleteAllCookies();
driver.manage().timeouts().pageLoadTimeout(util.PAGELOAD_TIME, TimeUnit.SECONDS);
driver.manage().timeouts().implicitlyWait(util.IMPICIT_WAIT, TimeUnit.SECONDS);
driver.get(util.URL);
}
public static void closeSession() {
driver.quit();
}
}
答案 0 :(得分:0)
如评论中所述,问题在于Cucumber正在执行在@Before
包的各个类中定义的所有@After
和stepDefinition
方法。这也是预期的情况,因为除非您专门告诉黄瓜,否则黄瓜不知道该执行哪种方法。
一个简单的解决方案是为每个测试用例创建不同的包以容纳不同的类,但是正如OP正确指出的那样,对于100个案例来说这不是一个可行的解决方案,并且这种方法将限制用户不能够从单个运行器类执行所有功能文件。
解决方案-
1)对于这种特殊情况,请使用@BeforeClass
和@AfterClass
Junit注释,而不是@Before
和@After
黄瓜注释。由于每个测试用例Step Def都有自己的类,因此它应该适合您的用例。
2)您也可以使用Tagged Hooks。它基本上是在场景中的名称上附加一个钩子。例如-
功能文件-
@Test1
Scenario: blah blah
@Test2
Scenario: blah blah 2
步骤定义-
@Before("@Test1")
public void beforeFirst(){
//This will run only before the Scenario Test1
}
@Before("@Test2")
public void beforeSecond(){
//This will run only before the Scenario Test2
}