TestNG能看到我的Spock(JUnit)测试结果吗?

时间:2014-03-25 11:51:15

标签: unit-testing groovy junit testng spock

需要让TestNG运行我的Spock测试,因为TestNG用于整个系统的其余部分。
由于TestNG支持运行JUnit测试,我尝试了这个:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="suiteTestName" verbose="1" junit="true">
    <test name="myTestName">
        <classes>
            <class name="mypackage.artifact.SomeArtifactSpecification" />
        </classes>
    </test>
</suite>

所以这实际上完全运行了Groovy'AsseArtifactSpecification'Spock单元测试。我可以从测试中看到一些I / O,但是因为我在Eclipse中运行,所以我使用调试器来验证所有测试是否正确执行。我的类路径上有TestNG-6.8.7和JUnit-4.10。问题是TestNG似乎并不知道它确实如此!这是结束输出:

===============================================
myTestName
Total tests run: 0, Failures: 0, Skips: 0
===============================================

有谁知道是否有可能让TestNG识别这些测试?

其他详细信息 - 为Bounty添加

在下面的一条评论中,彼得表示这取决于TestNG正在做什么。我尽可能地调查了这一点。似乎Junit和TestNG都调用了Spock的Sputnik类第63行的'run'方法。但是,当直接从JUnit调用时,从JUnit4TestClassReference调用Sputnik。从TestNG调用时,从JUnitCore调用Sputnik。

所以问题仍然存在:如何让TestNG识别Spock的测试输出?如果我要长寿和繁荣,我真的需要知道!似乎答案可能是让TestNG与JUnit4TestClassReference一起运行,或者使用某种类型的聪明包装器来使TestNG这样做......

对于血淋淋的细节,我在下面发布了两个堆栈跟踪。第一个来自TestNG运行,它不起作用,第二个是直接运行Spock而没有TestNG。

来自TestNG的第一个堆栈跟踪:

org.testng.remote.RemoteTestNG at localhost:54288   
Thread [main] (Suspended (breakpoint at line 65 in ArtifactManagerSpecification))   
    ArtifactManagerSpecification.$spock_feature_0_0() line: 65  
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57  
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43  
    Method.invoke(Object, Object...) line: 601  
    ReflectionUtil.invokeMethod(Object, Method, Object...) line: 138    
    ParameterizedSpecRunner(BaseSpecRunner).invokeRaw(Object, MethodInfo, Object...) line: 330  
    ParameterizedSpecRunner(BaseSpecRunner).invoke(Object, MethodInfo, Object...) line: 311 
    ParameterizedSpecRunner(BaseSpecRunner).invokeFeatureMethod() line: 285 
    ParameterizedSpecRunner(BaseSpecRunner).doRunIteration() line: 256  
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57  
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43  
    Method.invoke(Object, Object...) line: 601  
    ReflectionUtil.invokeMethod(Object, Method, Object...) line: 138    
    ParameterizedSpecRunner(BaseSpecRunner).invokeRaw(Object, MethodInfo, Object...) line: 330  
    ParameterizedSpecRunner(BaseSpecRunner).invoke(Object, MethodInfo, Object...) line: 311 
    ParameterizedSpecRunner(BaseSpecRunner).runIteration(Object[], int) line: 223   
    ParameterizedSpecRunner(BaseSpecRunner).initializeAndRunIteration(Object[], int) line: 214  
    ParameterizedSpecRunner(BaseSpecRunner).runSimpleFeature() line: 205    
    ParameterizedSpecRunner(BaseSpecRunner).doRunFeature() line: 199    
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57  
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43  
    Method.invoke(Object, Object...) line: 601  
    ReflectionUtil.invokeMethod(Object, Method, Object...) line: 138    
    ParameterizedSpecRunner(BaseSpecRunner).invokeRaw(Object, MethodInfo, Object...) line: 330  
    ParameterizedSpecRunner(BaseSpecRunner).invoke(Object, MethodInfo, Object...) line: 311 
    ParameterizedSpecRunner(BaseSpecRunner).runFeature() line: 175  
    ParameterizedSpecRunner(BaseSpecRunner).runFeatures() line: 152 
    ParameterizedSpecRunner(BaseSpecRunner).doRunSpec() line: 112   
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57  
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43  
    Method.invoke(Object, Object...) line: 601  
    ReflectionUtil.invokeMethod(Object, Method, Object...) line: 138    
    ParameterizedSpecRunner(BaseSpecRunner).invokeRaw(Object, MethodInfo, Object...) line: 330  
    ParameterizedSpecRunner(BaseSpecRunner).invoke(Object, MethodInfo, Object...) line: 311 
    ParameterizedSpecRunner(BaseSpecRunner).runSpec() line: 91  
    ParameterizedSpecRunner(BaseSpecRunner).run() line: 82  
    Sputnik.run(RunNotifier) line: 63   
    JUnitCore.run(Runner) line: 157 
    JUnitCore.run(Request) line: 136    
    JUnit4TestRunner.start(Class, String...) line: 81   
    JUnit4TestRunner.run(Class, String...) line: 69 
    TestRunner$1.run() line: 682    
    TestRunner.runWorkers(List<IWorker<ITestNGMethod>>, String, ListMultiMap<Integer,TestMethodWorker>) line: 1005  
    TestRunner.privateRunJUnit(XmlTest) line: 713   
    TestRunner.run() line: 614  
    SuiteRunner.runTest(TestRunner) line: 334   
    SuiteRunner.runSequentially() line: 329 
    SuiteRunner.privateRun() line: 291  
    SuiteRunner.run() line: 240 
    SuiteRunnerWorker.runSuite(SuiteRunnerMap, XmlSuite) line: 52   
    SuiteRunnerWorker.run() line: 86    
    RemoteTestNG(TestNG).runSuitesSequentially(XmlSuite, SuiteRunnerMap, int, String) line: 1224    
    RemoteTestNG(TestNG).runSuitesLocally() line: 1149  
    RemoteTestNG(TestNG).run() line: 1057   
    RemoteTestNG.run() line: 111    
    RemoteTestNG.initAndRun(String[], CommandLineArgs, RemoteArgs) line: 204    
    RemoteTestNG.main(String[]) line: 175   

直接运行Spock的第二个堆栈跟踪(可行)

Thread [main] (Suspended (breakpoint at line 65 in ArtifactManagerSpecification))   
ArtifactManagerSpecification.$spock_feature_0_0() line: 65  
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57  
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43  
Method.invoke(Object, Object...) line: 601  
ReflectionUtil.invokeMethod(Object, Method, Object...) line: 138    
ParameterizedSpecRunner(BaseSpecRunner).invokeRaw(Object, MethodInfo, Object...) line: 330  
ParameterizedSpecRunner(BaseSpecRunner).invoke(Object, MethodInfo, Object...) line: 311 
ParameterizedSpecRunner(BaseSpecRunner).invokeFeatureMethod() line: 285 
ParameterizedSpecRunner(BaseSpecRunner).doRunIteration() line: 256  
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57  
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43  
Method.invoke(Object, Object...) line: 601  
ReflectionUtil.invokeMethod(Object, Method, Object...) line: 138    
ParameterizedSpecRunner(BaseSpecRunner).invokeRaw(Object, MethodInfo, Object...) line: 330  
ParameterizedSpecRunner(BaseSpecRunner).invoke(Object, MethodInfo, Object...) line: 311 
ParameterizedSpecRunner(BaseSpecRunner).runIteration(Object[], int) line: 223   
ParameterizedSpecRunner(BaseSpecRunner).initializeAndRunIteration(Object[], int) line: 214  
ParameterizedSpecRunner(BaseSpecRunner).runSimpleFeature() line: 205    
ParameterizedSpecRunner(BaseSpecRunner).doRunFeature() line: 199    
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57  
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43  
Method.invoke(Object, Object...) line: 601  
ReflectionUtil.invokeMethod(Object, Method, Object...) line: 138    
ParameterizedSpecRunner(BaseSpecRunner).invokeRaw(Object, MethodInfo, Object...) line: 330  
ParameterizedSpecRunner(BaseSpecRunner).invoke(Object, MethodInfo, Object...) line: 311 
ParameterizedSpecRunner(BaseSpecRunner).runFeature() line: 175  
ParameterizedSpecRunner(BaseSpecRunner).runFeatures() line: 152 
ParameterizedSpecRunner(BaseSpecRunner).doRunSpec() line: 112   
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57  
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43  
Method.invoke(Object, Object...) line: 601  
ReflectionUtil.invokeMethod(Object, Method, Object...) line: 138    
ParameterizedSpecRunner(BaseSpecRunner).invokeRaw(Object, MethodInfo, Object...) line: 330  
ParameterizedSpecRunner(BaseSpecRunner).invoke(Object, MethodInfo, Object...) line: 311 
ParameterizedSpecRunner(BaseSpecRunner).runSpec() line: 91  
ParameterizedSpecRunner(BaseSpecRunner).run() line: 82  
Sputnik.run(RunNotifier) line: 63   
JUnit4TestClassReference(JUnit4TestReference).run(TestExecution) line: 50   
TestExecution.run(ITestReference[]) line: 38    
RemoteTestRunner.runTests(String[], String, TestExecution) line: 467    
RemoteTestRunner.runTests(TestExecution) line: 683  
RemoteTestRunner.run() line: 390    
RemoteTestRunner.main(String[]) line: 197   

1 个答案:

答案 0 :(得分:3)

我进一步调查了这一点,至少我找到了原因。

在下面的 org.testng.junit.JUnit4TestMethod 中,无法正确解析Spock测试名称。我猜,但我认为Spock使用一种名称修改来支持它允许的好文本方法名称。因此,即使下面的TestNG代码获得类似&#34的方法名称;这是我的测试&#34;,它无法通过所示方式解决。我相信真正的方法名称是:$ spock_feature_0_0

private static Method getMethod(Description desc) {
    Class<?> c = desc.getTestClass();
    String method = desc.getMethodName();
    try {
        return c.getMethod(method);
    } catch (Throwable t) {
        Utils.log("JUnit4TestMethod", 2,
                "Method '" + method + "' not found in class '" + c.getName() + "': " + t.getMessage());
        return null;
    }
}

结果,这会在调用 c.getMethod(method)时引发异常 - 它无法将Spock方法名称解析为类上的实际方法。

看起来真的很糟糕的情况&#39;是这个代码中由Junit( org.junit.runner.notification.RunNotifier )调用上面的代码:

private abstract class SafeNotifier {
    void run() {
        synchronized (fListeners) {
            for (Iterator<RunListener> all= fListeners.iterator(); all.hasNext();)
                try {
                    notifyListener(all.next());
                } catch (Exception e) {
                    all.remove(); // Remove the offending listener first to avoid an infinite loop
                    fireTestFailure(new Failure(Description.TEST_MECHANISM, e));
                }
        }
    }

这段代码不能安静地删除监听器,而是记录它......