在并行执行测试时获取顺序日志

时间:2016-08-17 03:11:30

标签: java unit-testing testng integration-testing

我们一直在使用testngjava来执行代码的集成测试。我们为测试执行实现了 侦听器 ,如下所示: -

public class TestExecutionListener implements IInvokedMethodListener {

    @Override
    public void beforeInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) {
        System.out.println("Testing : " + iInvokedMethod.getTestMethod().getMethodName());
    }

    @Override
    public void afterInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) {
        System.out.println("Successfully Tested : " + iInvokedMethod.getTestMethod().getMethodName());
    }
}

我们的 testng.xml 定义为: -

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

<suite name="TestSuite" verbose="1" parallel="classes" thread-count="10">
    <listeners>
        <listener class-name="core.TestExecutionListener"/>
    </listeners>

    <test name="IntegrationTests">
        <classes>
            <class name="test.SomeTest1"/>
            <class name="test.SomeTest2"/>
            <class name="test.SomeTest3"/>
            <class name="test.SomeTest4"/>
            ... There are more than 20 classes
        </classes>
    </test>
</suite>

当我们执行测试时,我们得到的输出如下:

Testing : SomeTest1Method1
Testing : SomeTest2Method2
Testing : SomeTest4Method5
Successfully Tested : SomeTest2Method2
Successfully Tested : SomeTest4Method5

虽然我们期望输出的是: -

Testing : SomeTest1Method1
Successfully Tested : SomeTest1Method1
Testing : SomeTest2Method2
Successfully Tested : SomeTest2Method2
Testing : SomeTest4Method5
Successfully Tested : SomeTest4Method5

由于xml中的parallel="classes"属性而猜测这一点,因为将其更改为false可提供所需的输出。但很明显,与并行执行相比,更改后的执行会消耗更多时间。

有没有办法并行运行这些测试,但仍能依次获得此输出?

2 个答案:

答案 0 :(得分:3)

当你启用parallel时,你会注意到日志中的beforeInvocationafterInvocation之间会有一段时间,并且时间差异因测试而异,因此交错输出。

如果您想要的是彼此相邻的开始和结束消息,那么您基本上是在抛出时间因素,因此只需将beforeInvocation消息添加到afterInvocation方法,如下所示:

public class TestExecutionListener implements IInvokedMethodListener {

    @Override
    public void beforeInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) {
    }

    @Override
    public void afterInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) {
        System.out.println("Testing : " + iInvokedMethod.getTestMethod().getMethodName());
        System.out.println("Successfully Tested : " + iInvokedMethod.getTestMethod().getMethodName());
    }
}

IMO这是根据您的规范执行此操作的唯一方法。但是,如果在测试期间必须收集其他信息,那么您可以在TestExecutionListener中缓冲一些日志,例如:

public class TestExecutionListener implements IInvokedMethodListener {
    private Map<Integer, Deque<String>> logsMap = new HashMap<Integer, Deque<String>>();

    public void log(IInvokedMethod iInvokedMethod, String log) {
        if(!logsMap.containsKey(iInvokedMethod.getId())) {
            logsMap.put(iInvokedMethod.getId(), new ArrayDeque<String>());
        }

        logsMap.get(iInvokedMethod.getId()).add(log);
    }

    @Override
    public void beforeInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) {
        log(iInvokedMethod, "Testing : " + iInvokedMethod.getTestMethod().getMethodName());
    }

    @Override
    public void afterInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) {
        log(iInvokedMethod, "Successfully Tested : " + iInvokedMethod.getTestMethod().getMethodName());

        Deque<String> logs = logsMap.get(iInvokedMethod.getId());
        while(!logs.isEmpty()) {
            System.out.println(logs.poll());
        }
    }
}

答案 1 :(得分:0)

首先,我建议您使用log4j或类似的记录工具,这是优雅的,模块化的和提供了很多灵活的选择。这也奠定了设计和发展的道路。以多种方式处理日志记录机制。

如果您有业务需求,需要单独跟踪每个线程的日志,则应考虑将此日志流式传输到不同的文件。 Log4j类工具确实支持写入多个文件的要求。你可以只进行谷歌搜索,你将获得很多信息。