将Testng参数设置为另一个参数的值

时间:2018-04-14 21:09:29

标签: java testng

我使用Testng xml为我的测试配置参数。

不同的用户可能在x​​ml文件中有不同的参数,我希望避免重复xml代码。

这个想法是每个用户定义一个包含所需参数的套件:

<suite name="Patrick's test file">

 <parameter name="favoriteApple" value="gala"/>
 <parameter name="favoriteGrape" value="red"/>

 <suite-file>
   <suite-file path="test.xml"/>
 </suite-file>

</suite>

请注意,其他用户可能拥有不同的测试文件,其中包含favoriteApple和favoriteGrape的不同值。 test.xml看起来像这样:

<suite name="test">

 <test>
   <parameter name="fruit" value="VALUE OF favoriteApple PARAMETER"/>
   <packages>
     <package name="apple fruit test"/>
   </packages>
 </test>

 <test>
   <parameter name="fruit" value="VALUE OF favoriteGrape PARAMETER"/>
   <packages>
     <package name="grape fruit test"/>
   </packages>
 </test>

</suite>

测试结构的动机是每个包都有一个扩展抽象类的类。抽象类有一个设置方法@BeforeTest,它将参数接收到受保护的成员中。

我还没有找到一种方法来将参数值设置为另一个参数的值。

现在每个人都需要一个带有重复代码的xml文件进行测试。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

除了另一个答案中提供的侦听器之外,还有另一种实现侦听器的方法。

import java.util.Map;
import org.testng.Assert;
import org.testng.ITestContext;
import org.testng.TestListenerAdapter;
import org.testng.xml.XmlTest;

public class CustomListen3 extends TestListenerAdapter {
    /**
     * Invoked after test class in initialized and before all the getters and
     * setters are called.
     */
    @Override
    public void onStart(ITestContext context) {
        // Get the current test
        XmlTest currentTest = context.getCurrentXmlTest();
        // Get all the parameters Global and local
        Map<String, String> parameters = currentTest.getAllParameters();
        for (String key : parameters.keySet()) {
            String parameterValue = parameters.get(key);
            // If parameter value starts with $, replace with the global parameter value
            if (parameterValue.startsWith("$")) {
                String newValue = currentTest.getParameter(parameterValue.substring(1));
                Assert.assertNotNull(newValue, "Global parameter value, " + parameterValue.substring(1));
                parameters.put(key, newValue);
            }
        }
        // Update the new parameters
        currentTest.setParameters(parameters);
        super.onStart(context);
    }
}
  • 这需要较少的代码
  • 不需要再次调用@BeforeTest方法

唯一的小问题是本地参数值被全局参数值覆盖。

答案 1 :(得分:0)

这可以通过以下步骤来实现

  • 介绍global_suite.xml文件中提供的全局参数概念。
  • 然后,应使用$等字符在各个测试文件中提供对这些全局参数的引用。
  • 如果参数值以$开头,则testNG应查找全局参数。此实施应在custom listener
  • 中进行
  • 如果未使用$ symobol,则将按原样使用参数值。这样就可以灵活地运行test.xml而无需使用全局套件文件

<强> global_suite.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Sighil's test file">
    <parameter name="favoriteApple" value="gala" />
    <parameter name="favoriteGrape" value="red" />
    <listeners>
        <listener class-name="path to CustomListen"></listener>
    </listeners>
    <suite-files>
        <suite-file path="testng_3.xml" />
    </suite-files>
</suite>

<强>的test.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="test" parallel="none">
    <test verbose="2" name="AppleTest" enabled="true">
        <parameter name="fruit" value="$favoriteApple" />
        <classes>
            <class name="com.project.ppp.AppleTest" />
        </classes>
    </test>

    <test verbose="2" name="GrapeTest" enabled="true">
        <parameter name="fruit" value="$favoriteGrape" />
        <classes>
            <class name="com.project.ppp.GrapeTest" />
        </classes>
    </test>
</suite>

<强> CustomListen.java

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.testng.Assert;
import org.testng.IInvokedMethod;
import org.testng.IInvokedMethodListener2;
import org.testng.ITestContext;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;
import org.testng.annotations.Parameters;
import org.testng.xml.XmlTest;

public class CustomListen implements IInvokedMethodListener2 {
    @Override public void beforeInvocation(IInvokedMethod invokedMethod, ITestResult testResult) {}
    @Override public void afterInvocation(IInvokedMethod invokedMethod, ITestResult testResult) {}
    @Override public void beforeInvocation(IInvokedMethod invokedMethod, ITestResult testResult, ITestContext context) {}

    @Override
    public void afterInvocation(IInvokedMethod invokedMethod, ITestResult testResult, ITestContext context) {
        ITestNGMethod testNGMethod = invokedMethod.getTestMethod();
        XmlTest currentTest = context.getCurrentXmlTest();
        // if method invoked is setFruit
        if (testNGMethod.isBeforeTestConfiguration() && testNGMethod.getMethodName().equals("setFruit")) {
            // find the java.lang.reflect method
            Method method = testNGMethod.getConstructorOrMethod().getMethod();
            // Get the parameters defined setFruit
            Parameters parameter = method.getAnnotation(Parameters.class);
            if (parameter != null) {
                // get the parameter names
                String[] parameterNames = parameter.value();
                // initiate a String array to hold the parameter values
                String[] parameterValues = new String[parameterNames.length];
                boolean setNewParameterValue = false;
                // loop the parameter names to get their corresponding parameter values
                for (int index = 0; index < parameterNames.length; index++) {
                    // set the parameter value
                    parameterValues[index] = currentTest.getParameter(parameterNames[index]);

                    // check if parameter value set expects a global parameter value
                    if (parameterValues[index].startsWith("$")) {
                        String newParameterValue = currentTest.getParameter(parameterValues[index].substring(1));
                        // Check if global parameter value is set
                        Assert.assertNotNull(newParameterValue,
                                "Global parameter name, " + parameterValues[index].substring(1));
                        parameterValues[index] = newParameterValue;
                        setNewParameterValue = true;
                    }
                }
                // invoke the setFruit BeforeTest method again to set the protected members if
                // global parameters are required
                if (setNewParameterValue) {
                    try {
                        method.invoke(testResult.getInstance(), (Object[]) parameterValues);
                    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

我使用以下类

TestNG 6.14.3 上测试了上述内容
public class GrapeTest extends FruitTest {
    @Test
    public void grapeTest() {
        System.out.println("grapeTest - " + fruit);
    }
}

public class AppleTest extends FruitTest {
    @Test
    public void appleTest() {
        System.out.println("appleTest - " + fruit);
    }
}

<强>输出

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running TestSuite

appleTest - gala
grapeTest - red
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.493 sec - in TestSuite