唯一标识testng中的每个测试调用

时间:2015-10-27 09:27:37

标签: java testng

好的,所以我有一个这样的课程

public class Calculator {

    @Test(dataProvider = "dp")
    public void add(int a, int b) {
        System.out.println("Invoked add: a, b" + a + "," + b);
    }

    @DataProvider(name = "dp")
    public Object[][] createData(ITestContext ctx) {
        return new Object[][] { new Object[] { 1, 2 }, new Object[] { 2, 3 } };
    }

当测试运行时,它将运行add方法两次。我想基于其输入跟踪每个添加唯一的调用。所以说,使用1,2作为输入调用add,然后这是一个唯一的调用。如果失败,我想将此信息存储到具有调用ID的数据库中。

如何使用testng实现这一目标?所有侦听器(methodinvocationlistener等)似乎都没有提供唯一标识方法运行的上下文。是的,他们确实让你看到参数,但我无法跟踪个别参数。那么,我是否以某种方式将自己的唯一参数注入结果对象并从那里跟踪它?

更新

我正在添加改进的代码,以帮助更好地理解上下文。 这是我的testng.xml

<suite name="Default Suite">
  <test name="test">
    <classes>
      <class name="com.test.testng.Calculator">
        <methods>
          <include name="add">
            <parameter name="data-id" value="1"/>
          </include> <!-- add -->
          <include name="add">
            <parameter name="data-id" value="2"/>
          </include> <!-- add -->
          <include name="subtract">
            <parameter name="data-id" value="3"/>
          </include> <!-- subtract -->
        </methods>
      </class> <!-- com.test.testng.Calculator -->
    </classes>
  </test> <!-- test -->
</suite> <!-- Default Suite -->

我有两个add的调用和一个subtract调用。 这是我的数据提供商

public class Calculator {

    @Test(dataProvider = "dp")
    public void add(int first, int second) {
        System.out.println("invoked add");
    }

    @Test(dataProvider = "dp")
    public void subtract(int first, int second) {
        System.out.println("invoked subtract");
    }

    @DataProvider(name = "dp")
    public Object[][] createData(Method m, ITestContext ctx) {    
        Object[][] data = new Object[][] { new Object[] { 1, 2 }, new Object[] { 2, 3 }, new Object[] { 3, 4 } };
        for (XmlClass test : ctx.getCurrentXmlTest().getXmlClasses()) {
            for (XmlInclude method : test.getIncludedMethods()) {
                if (method.getName().equals(m.getName()))
                int key = Integer.parseInt(method.getAllParameters().get("data-id"));
                return new Object[][] { data[key - 1] };
            }
        }
        return null ;
    }

}

我预计,添加运行两次,一次使用1,2作为输入,另一次使用2,3作为输入。同样,减去3,4作为输入。但是,我看到的是这个 -

[SuiteRunner] Created 1 TestRunners
[TestRunner] Running test test on 1  classes,  included groups:[] excluded groups:[]
===== Test class
com.test.testng.Calculator
    @Test Calculator.add(int, int)[pri:0, instance:com.test.testng.Calculator@39a054a5]
    @Test Calculator.subtract(int, int)[pri:0, instance:com.test.testng.Calculator@39a054a5]
======
method.getAllParamas(){data-id=1}

[Invoker 665576141] Invoking com.test.testng.Calculator.add
invoked

[Invoker 665576141] Invoking com.test.testng.Calculator.subtract
subtract
===== Invoked methods
    Calculator.add(int, int)[pri:0, instance:com.test.testng.Calculator@39a054a5]1 2  966808741
    Calculator.subtract(int, int)[pri:0, instance:com.test.testng.Calculator@39a054a5]1 2  966808741
=====

我需要根据我要从testng xml发送的特殊参数为每个方法提供数据。我如何实现这一目标?

3 个答案:

答案 0 :(得分:1)

[] []中的第一个参数是测试运行次数。第二是参数的数量。即
    public Object [] [] createData(ITestContext ctx){         return new Object [] [] {new Object [] {0,2},new Object [] {0,3}         };     }

将使用两个参数2,3进行一次测试。

答案 1 :(得分:1)

单元测试由开发人员检查他/她自己的代码,而不是其他人。

对问题的评论表明&#34;用户指定的参数/测试&#34;在上下文中,它将它放在 system 测试领域。

请勿使用单元测试框架执行系统测试。

重要的一点是,在您建议的环境中, external 可能会向代码(用户添加新的测试参数)中断构建。这是不好的。很坏。如果需要新功能,开发人员将增强代码并添加新测试以覆盖它。

查看BDD框架JBehave,这似乎更符合您的需求。

答案 2 :(得分:1)

要实现这一点,您可以在testng.xml中定义不同的测试用例,如下所示:

<suite name="Default Suite">
  <test name="test">
    <classes>
      <class name="com.test.testng.Calculator">
        <methods>
          <include name="add">
            <parameter name="data-id" value="1"/>
          </include> <!-- add -->
          <include name="subtract">
            <parameter name="data-id" value="3"/>
          </include> <!-- subtract -->
        </methods>
      </class> <!-- com.test.testng.Calculator -->
    </classes>
  </test> <!-- test -->
  <test name="test2">
    <classes>
      <class name="com.test.testng.Calculator">
        <methods>
          <include name="add">
            <parameter name="data-id" value="2"/>
          </include> <!-- add -->
        </methods>
      </class> <!-- com.test.testng.Calculator -->
    </classes>
  </test> <!-- test -->
</suite> <!-- Default Suite -->

我添加登录提供程序方法:

package com.test.testng;

import java.lang.reflect.Method;

import org.testng.ITestContext;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlInclude;

public class Calculator {

    @Test(dataProvider = "dp")
    public void add(int first, int second) {
        System.out.println("invoked add");
    }

    @Test(dataProvider = "dp")
    public void subtract(int first, int second) {
        System.out.println("invoked subtract");
    }

    @DataProvider(name = "dp")
    public Object[][] createData(Method m, ITestContext ctx) {    
        Object[][] data = new Object[][] { new Object[] { 1, 2 }, new Object[] { 2, 3 }, new Object[] { 3, 4 } };
        for (XmlClass test : ctx.getCurrentXmlTest().getXmlClasses()) {
            for (XmlInclude method : test.getIncludedMethods()) {

                if (method.getName().equals(m.getName())) {
                    int key = Integer.parseInt(method.getAllParameters().get("data-id"));
                    System.out.println("Running method " + m.getName() + "  with data-id: " + key);
                    return new Object[][] { data[key - 1] };
                }


            }
        }
        return null ;
    }

}

将此xml作为testng套件运行(使用eclipse插件)显示:

[TestNG] Running:
  /Users/fhernandez/Documents/workspaceTest/testNg-test/src/test/resources/testng.xml

Running method add  with data-id: 1
invoked add
Running method subtract  with data-id: 3
invoked subtract
Running method add  with data-id: 2
invoked add

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

如果我理解你的要求,你可以实现它。

实现此目的的另一种方法是在测试类之前放置一个方面或代理,并检查方法调用,在此方面/代理中实现您的需求。

<强>更新

我使用

添加一个监听器到计算器
@Listeners(Listener.class)
public class Calculator

听众如下所示

    package com.test.testng;

import java.util.Arrays;

import org.testng.IInvokedMethod;
import org.testng.IInvokedMethodListener;
import org.testng.ITestResult;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlInclude;

public class Listener implements IInvokedMethodListener {

    public void afterInvocation(IInvokedMethod method, ITestResult itr) {
        // TODO implements
    }

    public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {

        // Parameters value
        System.out.println("Parameters invocation value for method " + method.getTestMethod().getMethodName());
        Arrays.asList(testResult.getParameters()).stream().forEach(System.out::println);

        // get data-id
        for (XmlClass test : testResult.getTestContext().getCurrentXmlTest().getXmlClasses()) {
            for (XmlInclude met : test.getIncludedMethods()) {

                if (met.getName().equals(method.getTestMethod().getMethodName())) {
                    int key = Integer.parseInt(met.getAllParameters().get("data-id"));
                    System.out.println("listener: Running method " + method.getTestMethod().getMethodName() + "  with data-id: " + key);
                }        
            }
        }
    }
}

beforeInvocation中的代码显示参数调用值和data-id,这是输出

    [TestNG] Running:
  /Users/fhernandez/Documents/workspaceTest/testNg-test/src/test/resources/testng.xml

Running method add  with data-id: 1
Parameters invocation value for method add
1
2
listener: Running method add  with data-id: 1
invoked add
Running method subtract  with data-id: 3
Parameters invocation value for method subtract
3
4
listener: Running method subtract  with data-id: 3
invoked subtract
Running method add  with data-id: 2
Parameters invocation value for method add
2
3
listener: Running method add  with data-id: 2
invoked add

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