在 Playwright + testNG 中,我如何指定测试用例应使用 x 个用户角色运行,并为每个用户角色使用 y 数据运行?

问题描述 投票:0回答:1

我没有找到任何适合我的用例的方法。假设一个测试用例需要使用 2 个角色来执行,并且对于每个角色应该有 2 个使用不同数据的测试运行。

    @Test (dataProviderClass = roles.class, dataProvider = roles.SUPERADMIN_ADMIN)
    @Parameters({"data1", "data2"})
    public void myTestCase () {
    
        ...
    }

超级管理员和数据1、超级管理员和数据2、管理员和数据1、管理员和数据2

但这不起作用,因为参数应该在 xml 文件中设置,并且不支持多个 dataProvider。

任何有关如何解决此问题的高级帮助将不胜感激。

testng playwright
1个回答
0
投票

TestNG 不允许您将单个测试方法绑定到多个数据提供者。

话虽这么说,这里有一个示例,展示了如何使数据提供程序足够动态,以便它根据从套件文件传递的参数来修改自身。

public record Movie(String name) {}
public record Book(String name) {}
import org.testng.ITestNGMethod;
import org.testng.annotations.CustomAttribute;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlInclude;
import org.testng.xml.XmlTest;

import java.util.List;
import java.util.Map;
import java.util.Optional;

public class SampleTestCase {

    private static final Object[][] defaultData = new Object[][]{
            {true},
            {false}
    };

    private static final List<Object> books = List.of(
            new Book("Next Generation Java Testing"),
            new Book("Head First Java")
    );
    private static final List<Object> movies = List.of(
            new Movie("KungFu Panda"),
            new Movie("The Last Air Bender")
    );

    private static final Map<String, List<Object>> dataStore = Map.of(
            "data_set1", books,
            "data_set2", movies
    );

    @Test(attributes = {
            @CustomAttribute(name = "id1") // Hinting that this method is to get a parameter named "id1" from xml
    }, dataProvider = "dp")
    public void testMethod1(Book id) {
        System.err.println("testMethod1() Book = " + id);
    }

    @Test(attributes = {
            @CustomAttribute(name = "id2") // Hinting that this method is to get a parameter named "id2" from xml
    }, dataProvider = "dp")
    public void testMethod2(Movie id) {
        System.err.println("testMethod2() Movie = " + id);
    }

    @Test(dataProvider = "dp")
    public void testMethod3(boolean flag) {
        System.err.println("Flag = " + flag);
    }

    @DataProvider(name = "dp")
    public Object[][] getData(ITestNGMethod method) {
        CustomAttribute[] attributes = method.getAttributes();
        if (attributes.length == 0) {
            //No annotation was found. So send back default data provider values
            return defaultData;
        }

        //Now let's try to read the parameters that were set

        Map<String, String> localParams = extractParameters(method);

        for (CustomAttribute attribute : attributes) {
            boolean present = localParams.containsKey(attribute.name());
            if (!present) {
                continue;
            }
            String whichDataSet = localParams.get(attribute.name());
            List<Object> datum = Optional.ofNullable(dataStore.get(whichDataSet))
                    .orElseThrow(() -> new IllegalArgumentException("No data found for " + whichDataSet));
            return datum.stream()
                    .map(it -> new Object[]{it})
                    .toArray(size -> new Object[size][1]);
        }

        //if we are here, then send back another default data
        return defaultData;
    }

    private static Map<String, String> extractParameters(ITestNGMethod method) {
        Class<?> requiredClass = method.getRealClass();
        String requiredMethod = method.getMethodName();
        XmlTest currentTest = method.getXmlTest();
        XmlClass filter = new XmlClass(requiredClass);
        XmlInclude result = null;
        for (XmlClass each : currentTest.getXmlClasses()) {
            if (!each.equals(filter)) {
                //If the class name does not match, then skip to the next class in the suite file
                continue;
            }
            Optional<XmlInclude> found = each.getIncludedMethods().stream()
                    .filter(it -> it.getName().equalsIgnoreCase(requiredMethod))
                    .findFirst();
            if (found.isPresent()) {
                //if we found a method that matches the method we are searching for, then remember it
                // and break the loop
                result = found.get();
                break;
            }
        }
        //Now try to extract out the local parameters associated with the <include> tag
        //If there were none found, then error out with an exception
        return Optional.ofNullable(result)
                .map(XmlInclude::getLocalParameters)
                .orElseThrow(() -> new IllegalArgumentException(requiredClass.getName() + "." + requiredMethod + "() combo not found"));
    }
}

这是我们将要使用的套件文件

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="2980_suite" verbose="2">
    <test name="2980_test" verbose="2">
        <classes>
            <class name="com.rationaleemotions.so.qn78064092.SampleTestCase">
                <methods>
                    <include name="testMethod1">
                        <parameter name="id1" value="data_set1"/>
                    </include>
                </methods>
            </class>
            <class name="com.rationaleemotions.so.qn78064092.SampleTestCase">
                <methods>
                    <include name="testMethod2">
                        <parameter name="id2" value="data_set2"/>
                    </include>
                </methods>
            </class>
            <class name="com.rationaleemotions.so.qn78064092.SampleTestCase">
                <methods>
                    <include name="testMethod3"/>
                </methods>
            </class>
        </classes>
    </test>
</suite>

这是执行输出:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
...
... TestNG 7.9.0 by Cédric Beust ([email protected])
...

testMethod1() Book = Book[name=Next Generation Java Testing]
testMethod1() Book = Book[name=Head First Java]
testMethod2() Movie = Movie[name=KungFu Panda]
testMethod2() Movie = Movie[name=The Last Air Bender]
Flag = false
Flag = true
PASSED: com.rationaleemotions.so.qn78064092.SampleTestCase.testMethod2(Movie[name=KungFu Panda])
Test Attributes: <id2, []>

PASSED: com.rationaleemotions.so.qn78064092.SampleTestCase.testMethod2(Movie[name=The Last Air Bender])
Test Attributes: <id2, []>

PASSED: com.rationaleemotions.so.qn78064092.SampleTestCase.testMethod3(false)
PASSED: com.rationaleemotions.so.qn78064092.SampleTestCase.testMethod1(Book[name=Next Generation Java Testing])
Test Attributes: <id1, []>

PASSED: com.rationaleemotions.so.qn78064092.SampleTestCase.testMethod1(Book[name=Head First Java])
Test Attributes: <id1, []>

PASSED: com.rationaleemotions.so.qn78064092.SampleTestCase.testMethod3(true)

===============================================
    2980_test
    Tests run: 3, Failures: 0, Skips: 0
===============================================


===============================================
2980_suite
Total tests run: 6, Passes: 6, Failures: 0, Skips: 0
===============================================


Process finished with exit code 0
© www.soinside.com 2019 - 2024. All rights reserved.