1

これは、SO での最初の投稿です。私はJavaの初心者スキルを持つ初心者のSeleniumユーザーです。

私たちの仕事の背景を説明します。Page Object Modelを使用しています。すべてのテストは、DataProviderを呼び出し/使用するテスト ケース名に基づいて、".xlsx" ファイルからデータを取得する単一のDataProviderメソッドを使用します。

ただし、 ThreadLocalを宣言したかどうかは不明です。また、getDriver()メソッドの宣言が正しいかどうかもわかりません。もう 1 つの問題は、setupメソッドとtearDownメソッドで"@BeforeTest"/"@AfterTest"または"@BeforeClass"/"@AfterClass"を使用する必要があるかどうかわからないことです。

次の問題が発生しています。

  1. 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 クラスを拡張します... テストごとに 1 つのクラス:

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...");
        }

    }
}


これがスイート ファイルです。「banner」パラメーターは、「.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>


それを機能させる方法について何か提案はありますか?

4

3 に答える 3

2

1) テスト クラスごとに新しい ThreadLocal をインスタンス化しています。これは、BeforeClass アノテーションにあるためです。ThreadLocal の宣言とインスタンス化を同時に行う必要があります。

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

2) その Excel の解析ロジックは正気ではありません。少なくとも、それを独自のクラスに分離する必要があります。可能であれば、.xlsx ファイルの代わりに .csv ファイルを使用し、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;
    }
}
于 2016-01-21T19:55:59.123 に答える
0

いくつかの提案。

  1. 論理的にタスクを分離するものを分離してみてください。たとえば。ドライバーとデータプロバイダーの初期化は、2 つの別個のタスクです。別のクラスで dataprovider を作成し、それを任意のテスト内で参照できます。"デフォルトでは、データ プロバイダーは現在のテスト クラスまたはその基本クラスの 1 つで検索されます。データ プロバイダーを別のクラスに配置する場合は、静的メソッドである必要があり、そのクラスを指定します。 dataProviderClass 属性で見つけることができます: "

  2. ドライバーのインスタンス化は、すべて静的であるため、個別のクラスにすることができます。スレッドローカルのインスタンス化は、宣言の時点で行う必要があります。値の設定はスレッドで行う必要があります。したがって、新しい ThreadLocal を宣言に移動します。

    1. beforetest と class のどちらを選択するかは、テストをどのように並行して実行する予定かによって異なります。クラスのすべてのメソッドで同じドライバー インスタンスを使用する場合は、beforeclass を使用する必要があります。xml で testtags としてテストを並行して実行する場合は、beforetest を使用する必要があります。
      parallel=クラスを使っているので、beforeclassの選択は正しいようです。
于 2016-01-21T09:19:25.667 に答える