2016-01-20 271 views
1

這是我在SO的第一篇文章;我是一名新手,擁有初學Java技能的Selenium用戶。使用Selenium WebDriver,Selenium Grid和testNG運行並行測試

給你我們工作的背景;我們正在使用頁面對象模型。我們所有的測試都使用一個單一的DataProvider方法,該方法根據調用/使用DataProvider的測試用例名稱從「.xlsx」文件中提取數據。

但是我們不確定如果我們已經宣佈我們的ThreadLocal它應該是。而且,我們不確定我們的getDriver()方法的聲明是否正確。另一個問題是,我們不確定我們是否應該對我們的設置拆卸方法來使用「@BeforeTest」 /「@ AfterTest」「@BeforeClass」 /「@課餘」。正在遇到

以下問題:

  1. 一個測試失敗,後面的測試也失敗。
  2. 有時候測試數據被提取是不準確的(拋出的列數據比預期的多)。


這裏是我們的CONFIGTESTBASE類:

public class ConfigTestBase { 

    private static ThreadLocal<RemoteWebDriver> threadedDriver = null; 
    private static XSSFSheet ExcelWSheet; 
    private static XSSFWorkbook ExcelWBook; 
    private static XSSFCell Cell; 
    private static XSSFRow Row; 
    private static final String Path_TestData = GlobalConstants.testDataFilePath; 
    private static final String File_TestData = GlobalConstants.testDataFileName; 

    @Parameters({"objectMapperFile"}) 
    @BeforeSuite 
    public void setupSuite(String objectMapperFile) throws Exception { 
     GlobalConstants.objectMapperDefPath = new File(objectMapperFile).getAbsolutePath(); 
     new Common().OverrideSSLHandshakeException(); 
    } 

    @Parameters({"browserName"}) 
    @BeforeClass 
    public void setup(String browserName) throws Exception { 

     threadedDriver = new ThreadLocal<>(); 

     DesiredCapabilities capabilities = new DesiredCapabilities(); 

     if (browserName.toLowerCase().contains("firefox")) { 
      capabilities = DesiredCapabilities.firefox(); 
      capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true); 
      capabilities.setBrowserName("firefox"); 
      capabilities.setPlatform(Platform.WINDOWS); 
     } 

     if (browserName.toLowerCase().contains("ie")) { 
      System.setProperty("webdriver.ie.driver","C:\\selenium\\IEDriverServer.exe"); 
      capabilities = DesiredCapabilities.internetExplorer(); 
      capabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true); 
      capabilities.setCapability(InternetExplorerDriver.FORCE_CREATE_PROCESS, false); 
      capabilities.setBrowserName("internet explorer"); 
      capabilities.setPlatform(Platform.WINDOWS); 
     } 

     if (browserName.toLowerCase().contains("chrome")) { 
      System.setProperty("webdriver.chrome.driver","C:\\selenium\\chromedriver.exe"); 
      capabilities = DesiredCapabilities.chrome(); 
      capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true); 
      capabilities.setBrowserName("chrome"); 
      capabilities.setPlatform(Platform.WINDOWS); 
     } 

     if (browserName.toLowerCase().contains("safari")) { 
      SafariOptions options = new SafariOptions(); 
      options.setUseCleanSession(true); 
      capabilities = DesiredCapabilities.safari(); 
      capabilities.setCapability(SafariOptions.CAPABILITY, options); 
      capabilities.setBrowserName("safari"); 
      capabilities.setPlatform(Platform.WINDOWS); 
     } 

     threadedDriver.set(new RemoteWebDriver(new URL(GlobalConstants.GRIDHUB), capabilities)); 

    } 

    protected static RemoteWebDriver getDriver(){ 
     RemoteWebDriver driver = null; 

     try { 
      driver = threadedDriver.get(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return driver; 
    } 

    @AfterClass 
    public void tearDown() throws Exception { 
     getDriver().quit(); 
    } 

    //This method is to set the File path and to open the Excel file, Pass Excel Path and Sheetname as Arguments to this method 
    public void setExcelFile(String Path,String SheetName) throws Exception { 
     try { 
      // Open the Excel file 
      FileInputStream ExcelFile = new FileInputStream(Path); 

      // Access the required test data sheet 
      ExcelWBook = new XSSFWorkbook(ExcelFile); 
      ExcelWSheet = ExcelWBook.getSheet(SheetName); 
     } catch (Exception e) { 
      throw (e); 
     } 
    } 

    //This method is to read the test data from the Excel cell, in this we are passing parameters as Row num and Col num 
    @SuppressWarnings("static-access") 
    public String getCellData(int RowNum, int ColNum) throws Exception{ 
     try{ 
      Cell = null; 
      Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum); 
      Cell.setCellType(Cell.CELL_TYPE_STRING); 
      return Cell.getStringCellValue(); 
     } catch (Exception e) { 
      return ""; 
     } 
    } 

    //This method is to write in the Excel cell, Row num and Col num are the parameters 
    @SuppressWarnings("static-access") 
    public void setCellData(String textValue, int RowNum, int ColNum) throws Exception { 
     try{ 
      Row = ExcelWSheet.getRow(RowNum); 
      Cell = Row.getCell(ColNum, Row.RETURN_BLANK_AS_NULL); 
      if (Cell == null) { 
       Cell = Row.createCell(ColNum); 
       Cell.setCellValue(textValue); 
      } else { 
       Cell.setCellValue(textValue); 
      } 

      // Constant variables Test Data path and Test Data file name 
      FileOutputStream fileOut = new FileOutputStream(Path_TestData + File_TestData); 
      ExcelWBook.write(fileOut); 
      fileOut.flush(); 
      fileOut.close(); 
     } catch (Exception e) { 
      throw (e); 
     } 
    } 

    @DataProvider(name="getDataFromFile") 
    public Object[][] getDataFromFile(Method testMethod, ITestContext context) throws Exception { 

     String[][] tabArray; 
     int intCounter; 
     int intRowCount = 0; 
     int intRowCounter = 0; 
     int intColCount = 0; 
     int intColCounter; 
     int intColDataCount = 0; 
     int intColDataCounter = 0; 
     String temp; 

     String testName = testMethod.getName(); 
     String banner = context.getCurrentXmlTest().getParameter("banner"); 
     setExcelFile(Path_TestData + File_TestData, banner); 

     //get number of data to be returned 
     for(intCounter=0;intCounter<ExcelWSheet.getLastRowNum()+1;intCounter++){ 
      if(getCellData(intCounter, 1).equals(testName)) { 
       if (intColCount == 0) { 
        intColCount = ExcelWSheet.getRow(intCounter).getLastCellNum() - 2; 
       } 
       intRowCount++; 
      } 
     } 

     if(intRowCount == 0){ 
      System.out.println("\n*** Data for '" + testName + "' was not found."); 
      throw new AssertionError("Data for '" + testName + "' was not found."); 
     } 

     for(intCounter=0;intCounter<ExcelWSheet.getLastRowNum()+1;intCounter++){ 
      if(getCellData(intCounter, 1).equals(testName)) { 
       for(intColCounter=2;intColCounter<intColCount+2;intColCounter++) { 
        temp = getCellData(intCounter,intColCounter); 
        if(temp != null && !temp.isEmpty()){ 
         intColDataCount++; 
        } 
       } 
       //to exit FOR loop 
       intCounter = ExcelWSheet.getLastRowNum()+1; 
      } 
     } 

     //set data array dimension 
     tabArray = new String[intRowCount][intColDataCount]; 

     for(intCounter=0;intCounter<ExcelWSheet.getLastRowNum()+1;intCounter++){ 
      if(getCellData(intCounter, 1).equals(testName)) { 
       intRowCounter++; 
       for(intColCounter=2;intColCounter<intColCount+2;intColCounter++) { 
        temp = getCellData(intCounter,intColCounter); 
        if(temp != null && !temp.isEmpty()){ 
         tabArray[intRowCounter-1][intColDataCounter] = getCellData(intCounter,intColCounter); 
         intColDataCounter++; 
        } 
       } 
      } 
     } 

     return tabArray; 

    } 

} 


下面是一個簡單的測試類,我們有;擴展CONFIGTESTBASE類...每次測試一個類:

public class Google6 extends ConfigTestBase { 

    private Generic generic = null; 
    private HomePage homePage = null; 

    @BeforeMethod 
    public void MethodInit(ITestResult result) throws Exception { 
     generic = new Generic(getDriver()); 
     homePage = new HomePage(getDriver()); 
    } 

    @Test(dataProvider="getDataFromFile") 
    public void Google6(String execute, String url, String searchString) throws Exception { 

     if(execute.toUpperCase().equals("YES")) { 

      //navigate to application page 
      generic.navigateToURL(url); 

      //search 
      homePage.search(searchString); 

     } else { 
      generic.log("Execute variable <> 'YES'. Skipping execution..."); 
      throw new SkipException("Execute variable <> 'YES'. Skipping execution..."); 
     } 

    } 
} 


這裏是我們的套件文件; 「旗幟」參數用於查找的「的.xlsx」文件中的特定表:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> 

<suite name="Full Test Suite - Firefox" parallel="classes" thread-count="5" verbose="1"> 
    <parameter name="objectMapperFile" value="mom.objectdef.properties" /> 

    <test name="Regression - Firefox"> 
     <parameter name="browserName" value="firefox" /> 
     <parameter name="banner" value="SAMPLE" /> 
     <classes> 
      <class name="com.company.automation.web.app.testsuites.Google1" /> 
      <class name="com.company.automation.web.app.testsuites.Google2" /> 
      <class name="com.company.automation.web.app.testsuites.Google3" /> 
      <class name="com.company.automation.web.app.testsuites.Google4" /> 
      <class name="com.company.automation.web.app.testsuites.Google5" /> 
      <class name="com.company.automation.web.app.testsuites.Google6" /> 
     </classes> 
    </test> 

</suite> 


上,我們怎麼能讓它的工作有什麼建議?

+0

'''threadedDriver.set(新RemoteWebDriver(新URL(GlobalConstants.GRIDHUB),能力));''' – thomas77

+0

在什麼地方GlobalConstant.GRIDHUB從何而來。我試圖在一個硒輪轂碼頭集裝箱上平行運行黃瓜測試,但我似乎是我的遠程總是打一個正在運行的集裝箱。 threadedDriver.set(新的RemoteWebDriver(新的URL(GlobalConstants.GRIDHUB),功能)); – thomas77

回答

2

1)你實例化一個新的ThreadLocal爲每個測試類,因爲它在BeforeClass註解。你應該同時聲明和實例化ThreadLocal:

private static ThreadLocal<RemoteWebDriver> threadedDriver = new ThreadLocal<>(); 

2)該Excel解析邏輯是瘋了。至少,你需要把它分成它自己的類。如果可能,請使用.csv文件而不是.xlsx文件,並使用類似opencsv的文件來解析文件;它會搖動你的世界。解析後,您可以將其轉換爲TestNG的DataProvider所期望的。事情是這樣的:

public class CSVDataReader { 
    private static final char DELIMITER = ','; 
    private static final char QUOTE_CHAR = '\"'; 
    private static final char ESCAPE_CHAR = '\\'; 

    private static List<String[]> read(String filePath, boolean hasHeader) throws IOException { 
     CSVReader reader; 

     if (hasHeader) { 
      // If file has a header, skip the header (line 1) 
      reader = new CSVReader(new FileReader(filePath), DELIMITER, QUOTE_CHAR, ESCAPE_CHAR, 1); 
     } else { 
      reader = new CSVReader(new FileReader(filePath), DELIMITER, QUOTE_CHAR, ESCAPE_CHAR); 
     } 

     List<String[]> rows = reader.readAll(); 
     reader.close(); 

     return rows; 
    } 

    public static String [][] readCSVFileToString2DArray(String filePath, boolean hasHeader) throws IOException { 
     List<String[]> rows = read(filePath, hasHeader); 

     // Store all rows/columns in a two-dimensional String array, then return it 
     String [][] csvData = new String[rows.size()][]; 

     int r = 0; 
     for (String[] row : rows) { 
      csvData[r++] = row; 
     } 

     return csvData; 
    } 
} 
+0

謝謝@Shane。現在我只需要擔心解析Excel中的數據。不確定CSV是否適合我們。 – MarkM

0

一件事情time..I相信你已經交給該代碼由someone..please支票如何初始化ThreadLocal的第一here

嘗試在小時間您的問題一個縮小了解根本原因的代碼片段

+0

此代碼來自我們的移動測試自動化團隊。我修改了** setup()**方法以使用** RemoteWebDriver **替代它們的** AppiumDriver **。我通過設置** RemoteWebDriver **(_not browser specific drivers_)來初始化我的ThreadLocal變量** threadedDriver **。 - 每個測試有1個類,這些類中有** @ Test **方法。 - 在我們的套件文件中,我們使用** thread-count =「5」**設置** parallel =「classes」**。 -我們還使用** @ BeforeClass **作爲** setup()**和** tearDown()**。 – MarkM

+0

我還爲DataProvider創建了一個單獨的類,並在我們的@Test方法中使用/表示了dataProviderClass屬性。 – MarkM

0

幾個建議。

  1. 嘗試分離您邏輯上分離的任務。例如。初始化驅動程序和數據提供者是兩個獨立的任務。您可以在單獨的類中創建數據提供者,並在任何測試中引用該數據提供者,例如。「By default, the data provider will be looked for in the current test class or one of its base classes. If you want to put your data provider in a different class, it needs to be a static method and you specify the class where it can be found in the dataProviderClass attribute:

  2. 你的驅動程序安裝可以是一個單獨的類,因爲它是所有靜態的。 threadlocal的實例化應該在聲明的位置。值的設置應該在線程中。因此,將新的ThreadLocal移動到您的聲明中。

    1. beforetest或class的選擇取決於您打算如何平行運行測試。如果你打算在你的類的所有方法中使用相同的驅動程序實例,那麼應該使用beforeclass。如果您打算在xml中平行運行測試作爲testtags,則應使用beforetest。
      由於您正在使用parallel = classes,所以beforeclass的選擇似乎是正確的。
+0

謝謝@niharika_new。另一個問題,如果我將基礎類的驅動程序實例化(_my tests extends_ *** ConfigTestBase ***),可以嗎? – MarkM

相關問題