有没有办法让testng进行测试的dryrun并输出将在没有实际运行它们的情况下运行的测试的package.name.parameters?我有一个使用IHookable
的部分解决方案,它无需调用IHookCallBack
即可记录测试信息。这种方法的缺点是所有@Before Class/Suite/Test/Method
都被调用。我们利用那些非常强大的功能并在其中添加了大量耗时的功能,我希望跳过这些功能。
答案 0 :(得分:2)
TestNG在6.14版中添加了此选项(请参见here)。
要激活它,请使用JVM参数:
-Dtestng.mode.dryrun=true
答案 1 :(得分:1)
我最终实现了IMethodInterceptor
仍然会调用被测系统的构造函数,以及@BeforeSuite
和@BeforeTest
。如果SUT使用@Factory
创建自身或其他类的多个实例,则该类应实现一个名为String classParameters
的属性,以区别于其他类。另外,由于未调用@BeforeClass
,因此依赖于调用@DataProvider
的任何@BeforeClass
都无法正常工作。
它并不是一个完美的解决方案,但足以满足我的需求。希望这有助于其他人。
/* DryRunListener.groovy */
import org.testng.IMethodInstance
import org.testng.IMethodInterceptor
import org.testng.ITestContext
import org.testng.annotations.DataProvider
import org.testng.annotations.Test
/*
* This interceptor builds up a list of tests that would run without actually running them
* The @BeforeMethod and @BeforeClass methods are NOT run, but the @BeforeSuite, @BeforeTest and constructors still run.
* If data providers rely on the @BeforeClass methods getting called, they won't work
*/
class DryRunListener implements IMethodInterceptor {
def tests = []
@Override
List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
for (method in methods) {
// Get class name plus any parameters given by factories
def className = getClassName(method)
// Handling for data providers. If the method uses one, go invoke it
def params = getParametersForMethod(method)
tests = params.collect { "${canonicalName}.$method.method.methodName(${it.join ", "})" }
}
tests.each { println it } // or save it or whatever...
return [] // tells testng - Don't run any methods!
}
/*
* When using factories, there's no way to distinguish instances the factory has created.
* TestNG has a mechanism whereby you inherit from ITest, and implement a getTestName, which is typically
* set during a @BeforeMethod call, and is used by reporters. This requires @BeforeMethod actually be called,
* which we don't want to do from this interceptor. Instead, we ask the testclass to implement a property for
* returning a serialized string called classParameters, which we will append to the canonicalName of the class
*/
String getClassName(IMethodInstance method) {
def realClass = method.method.realClass
def canonicalName = realClass.canonicalName
if (realClass.metaClass.hasProperty(method.instance, "classParameters")) {
canonicalName += "($method.instance.classParameters)"
}
canonicalName
}
/*
* The interceptor receives the list of methods before they have been exploded for
*/
Object[][] getParametersForMethod(IMethodInstance method) {
def testAnnotation = method.method.constructorOrMethod.method.getAnnotation(Test.class)
Class dataProviderClass = testAnnotation.dataProviderClass()
if (dataProviderClass == null || dataProviderClass == Object.class) {
dataProviderClass = method.method.realClass
}
String dataProviderName = testAnnotation.dataProvider()
def dataProviderMethod = dataProviderClass.methods.find { it.getAnnotation(DataProvider.class)?.name() == dataProviderName }
return dataProviderMethod?.invoke(method.instance) ?: [[]]
}
}
答案 2 :(得分:0)
1)Java Reflection是你最好的朋友。您可以使用反射并获取所有信息。 2)其他可能的解决方案是使用 Xml 类(XmlTest ...)将testng.xml转换为programmitacal等效项。你会发现很多API可以帮助你实现这一目标。 如果这有帮助,请告诉我。