Domanda

I want to create bugs reports in my issue tracking software when unit tests fail. This means I need to save what normally is printed to my IDE's console when a test fails as a String. Thus far, I have the following code:

@Rule
public ErrorCollector collector = new ErrorCollector();
...

@Test
public void testFailedUnitTest() {
    collector.checkThat(3, equalTo(5));
}

It outputs the following to the console. I want to put this into a String instead of/in addition to outputting it to my IDE's console:

java.lang.AssertionError: 
Expected: <5>
     but: was <3>
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
    at org.junit.Assert.assertThat(Assert.java:865)
    ...

I have tried:

  1. Surrounding it with try/catch blocks and using e.get... but it didn't catch the java.lang.AssertionError. The code in the catch block wasn't even executed. I think that's because my collector is waiting to throw the exception after testFailedUnitTest() completes to throw the error so that it can continue executing a test that fails.

  2. Surrounding a normal, non-collector JUnit test with try/catch blocks.

  3. Grabbing the output in my tearDown(), after all the tests have completed. But there is no method like public String[] getJUnitFailures() in the ErrorCollector JavaDoc so that didn't work.

  4. Various ways involving editing something in my pom.xml such as setting the redirectTestOutputToFile element to true but they have the same problems as 2), and unfortunately some legacy code doesn't use Maven. However, Maven-specific methods would be acceptable.

I spoke with someone in person who said that I might be able to log each test's output to a file using the Logger class and read each file in as a String. He admitted that that's a sloppy hack and could interfere with our other logging facilities.

Would that even work and if so, is it the best way to do it?

Thank you in advance. :)

È stato utile?

Soluzione

Looks like a TestWatcher can do what you want.


Example

import java.io.PrintWriter;
import java.io.StringWriter;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;

public class FailedTestCapturer {

  @SuppressWarnings("null")
  private static int throwNPE() {
    String x = null;
    return x.length();
  }

  private String exception;
  @Rule
  public final TestRule watchman = new TestWatcher() {
    @Override
    protected void failed(Throwable e, Description description) {
      StringWriter writer = new StringWriter();
      e.printStackTrace(new PrintWriter(writer));
      exception = writer.toString();
      System.out.println("Captured exception! --> " + exception);
    }
  };

  @Test
  public void failingTest() {
    throwNPE();
  }
}

Output

Captured exception! --> java.lang.NullPointerException
    at FailedTestCapturer.throwNPE(FailedTestCapturer.java:15)
    at FailedTestCapturer.failingTest(FailedTestCapturer.java:32)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top