草庐IT

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

coder 2024-03-04 原文

好的,所以我有这样一个类

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 方法。我想根据其输入唯一地跟踪 add 的每次调用。所以说,add 是用 1,2 作为输入调用的,那么这是一个独特的调用。如果失败,我想将此信息存储到具有调用 ID 的数据库中。

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

更新

我正在添加改进的代码,以帮助更好地理解上下文。 这是我的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 -->

我有两次加法调用和一次减法调用。 这是我的数据提供者

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 ;
    }

}

我预计,add 会运行两次,一次以 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 发送的特殊参数向每个方法提供数据。我如何实现这一点?

最佳答案

为此,您可以在 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
===============================================

关于java - 唯一标识 testng 中的每个测试调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33364109/

有关java - 唯一标识 testng 中的每个测试调用的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  3. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  4. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  5. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  6. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  7. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  8. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  9. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  10. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

随机推荐