简体   繁体   中英

How do I run a testNG test multiple times, based on an internal logic?

I have gone through some solutions that tells about TestNg DataProvider and InvocationCount , but DataProvider or InvocationCount come in picture even before my @Test method starts. My requirement is, I have a DataReader class which reads data from excel file in the form of key-value pair (keys always in first row and there can be more than one row for values). Suppose if there are 2 rows of values available then I would have to run the same @Test with another set of data (It would be great if I can run @BeforeClass and @AfterClass methods for each iteration of @Test ).

Something Like This:

@BeforeClass
//Some Code Here that runs on each iteration of @Test

@Test
public void myTest() {

// make a decision here, based on number of rows of values, run the test multiple times
DataReader.LoadDataSheet("TestData.xlsx", "SheetName");

}

@AfterClass
//Some Code Here that runs on each iteration of @Test

What you need here is a Factory powered data provider.

The first data provider which is bound with the factory method, would provide data that would be used by the test methods for every instance to iterate as many times as required. The data that is first fed by the outer data provider, would be then used by the data provider that would be part of every instance, which would iterate the tests as many times as required.

The below sample should be able to clarify this.

import org.assertj.core.api.Assertions;
import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Factory;
import org.testng.annotations.Test;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class TestClassSample {
    private List<String> data;

    @Factory(dataProvider = "getDataForInstances")
    public TestClassSample(List<String> data) {
        this.data = data;
    }

    @BeforeMethod
    public void beforeMethod(Object[] parameters) {
        System.err.println("Printing Parameters before running test method " + Arrays.toString(parameters));
    }

    @Test(dataProvider = "getData")
    public void testMethod(String text) {
        System.err.println("Printing Parameters when running test method [" + text + "]");
        Assertions.assertThat(text).isNotEmpty();
    }

    @AfterMethod
    public void afterMethod(ITestResult result) {
        System.err.println("Printing Parameters after running test method " + Arrays.toString(result.getParameters()));
    }

    @DataProvider(name = "getData")
    public Object[][] getData() {
        //This data provider simulates the iterations that every test method has to go through based on
        //the outer data provider viz., "getDataForInstances()"
        Object[][] iterationData = new Object[data.size()][1];
        for (int i = 0; i < data.size(); i++) {
            iterationData[i] = new String[]{data.get(i)};
        }
        return iterationData;
    }

    @DataProvider(name = "getDataForInstances")
    public static Object[][] getDataForInstances() {
        //This data provider simulates data being read from excel, wherein it would return the number of
        //iterations that every test method should go through.
        return new Object[][]{
                {Collections.singletonList("Java")},
                {Arrays.asList("TestNG", "JUnit")},
                {Arrays.asList("Maven", "Gradle", "Ant")}
        };
    }
}

Here's the output:

Printing Parameters before running test method [Maven]
Printing Parameters when running test method [Maven]
Printing Parameters after running test method [Maven]

Printing Parameters before running test method [Gradle]
Printing Parameters when running test method [Gradle]
Printing Parameters after running test method [Gradle]

Printing Parameters before running test method [Ant]
Printing Parameters when running test method [Ant]
Printing Parameters after running test method [Ant]

Printing Parameters before running test method [TestNG]
Printing Parameters when running test method [TestNG]
Printing Parameters after running test method [TestNG]

Printing Parameters before running test method [JUnit]
Printing Parameters when running test method [JUnit]
Printing Parameters after running test method [JUnit]

Printing Parameters before running test method [Java]
Printing Parameters when running test method [Java]
Printing Parameters after running test method [Java]

===============================================
Default Suite
Total tests run: 6, Failures: 0, Skips: 0
===============================================

I'm not a fancy coder, but here is how i wanted it.

Test Class :

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class Test2 extends BaseTset {

    @Test(dataProvider = "dataprovider")
    public void test(DataReader2 reader) {
        for (int i = 1; i <= 10; i++) {
            System.out.println("Test : " + reader.getValue("Key_" + i));
        }
    }

    @DataProvider(name = "dataprovider")
    public DataReader2[] dataProvider() {
        String dataFileName = "TestData.xlsx";
        DataReader2 reader = new DataReader2(dataFileName);
        int rowCount = reader.getRowCount();
        DataReader2[] reader2 = new DataReader2[rowCount];
        for (int i = 0; i < rowCount; i++) {
            int j = i + 1;
            reader2[i] = DataReader2.getReader(dataFileName, j);
        }
        return reader2;
    }
}

Data Reader 2 Class :

import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class DataReader2 {
    private Map<String, String> dataSet = new HashMap<String, String>();
    private XSSFWorkbook ExcelWBook;
    private XSSFSheet ExcelWSheet;
    private FormulaEvaluator Evaluator;
    private XSSFCell Cell;
    private XSSFRow Row;
    private int rowCount;
    private int columnCount;

    public DataReader2(String FileName, int rowNum) {
        loadDataFile(FileName);
        dataSet = getDataSet(rowNum);
    }

    public DataReader2(String FileName) {
        loadDataFile(FileName);
    }

    public static DataReader2 getReader(String FileName, int rowNum) {
        DataReader2 dataReader = new DataReader2(FileName, rowNum);
        return dataReader;
    }

    private void loadDataFile(String FileName) {
        try {
            String FilePath = "./data/" + FileName;
            FileInputStream ExcelFile = new FileInputStream(FilePath);
            ExcelWBook = new XSSFWorkbook(ExcelFile);
            Evaluator = ExcelWBook.getCreationHelper().createFormulaEvaluator();
            ExcelWSheet = ExcelWBook.getSheetAt(0);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public int getRowCount() {
        rowCount = ExcelWSheet.getLastRowNum();
        return rowCount;
    }

    private Map<String, String> getDataSet(int rowNum) {
        DataFormatter formatter = new DataFormatter();
        Row = ExcelWSheet.getRow(rowNum);
        columnCount = Row.getLastCellNum();
        for (int i = 0; i < columnCount; i++) {
            Cell = ExcelWSheet.getRow(0).getCell(i);
            String key = formatter.formatCellValue(Cell, Evaluator);
            Cell = Row.getCell(i);
            String value = formatter.formatCellValue(Cell, Evaluator);
            dataSet.put(key, value);
        }
        return dataSet;
    }

    public String getValue(String key) {
        try {
            key = key.trim();
            String value = dataSet.get(key).trim();
            if (!value.isEmpty() && !value.equals(null)) {
                return value;
            } else {
                throw (new Exception("No key with name : " + key + " available in datasheet."));
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
}

Base Test Class :

import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;

public class BaseTset {

    @BeforeClass
    public void beforeClass() {
        System.out.println("Before class");
    }

    @BeforeMethod
    public void beforeMethod() {
        System.out.println("Before method");
    }

    @AfterMethod
    public void AfterMethod() {
        System.out.println("After method");
    }

    @AfterClass
    public void afterClass() {
        System.out.println("After Class");
    }
}

Output :

[RemoteTestNG] detected TestNG version 6.12.0
Before class
Before method
Test : Value_1
Test : Value_2
Test : Value_3
Test : Value_4
Test : Value_5
Test : Value_6
Test : Value_7
Test : Value_8
Test : Value_9
Test : Value_10
After method
Before method
Test : Value_11
Test : Value_12
Test : Value_13
Test : Value_14
Test : Value_15
Test : Value_16
Test : Value_17
Test : Value_18
Test : Value_19
Test : Value_20
After method
Before method
Test : Value_21
Test : Value_22
Test : Value_23
Test : Value_24
Test : Value_25
Test : Value_26
Test : Value_27
Test : Value_28
Test : Value_29
Test : Value_30
After method
Before method
Test : Value_31
Test : Value_32
Test : Value_33
Test : Value_34
Test : Value_35
Test : Value_36
Test : Value_37
Test : Value_38
Test : Value_39
Test : Value_40
After method
After Class
PASSED: test(datareader.DataReader2@186beff)
PASSED: test(datareader.DataReader2@78afa0)
PASSED: test(datareader.DataReader2@1c2959f)
PASSED: test(datareader.DataReader2@19982de)

===============================================
    Default test
    Tests run: 4, Failures: 0, Skips: 0
===============================================


===============================================
Default suite
Total tests run: 4, Failures: 0, Skips: 0
===============================================

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM