// Copyright 2011 The Bazel Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.testing.junit.runner.internal.junit4; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.google.common.collect.Lists; import com.google.testing.junit.runner.internal.SignalHandlers; import com.google.testing.junit.runner.model.TestSuiteModel; import com.google.testing.junit.runner.util.Supplier; import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.io.PrintStream; import java.util.List; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.Description; import org.junit.runner.JUnitCore; import org.junit.runner.Request; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.InOrder; import sun.misc.Signal; import sun.misc.SignalHandler; /** * Tests for {@link JUnit4TestXmlListener} */ @RunWith(JUnit4.class) public class JUnit4TestXmlListenerTest { private static final String CHARSET = "UTF-8"; private final FakeSignalHandlers fakeSignalHandlers = new FakeSignalHandlers(); private final ByteArrayOutputStream errStream = new ByteArrayOutputStream(); private PrintStream errPrintStream; @Before public void createErrPrintStream() throws Exception { errPrintStream = new PrintStream(errStream, true, CHARSET); } @Test public void signalHandlerWritesXml() throws Exception { TestSuiteModelSupplier mockModelSupplier = mock(TestSuiteModelSupplier.class); TestSuiteModel mockModel = mock(TestSuiteModel.class); CancellableRequestFactory mockRequestFactory = mock(CancellableRequestFactory.class); OutputStream mockXmlStream = mock(OutputStream.class); JUnit4TestXmlListener listener = new JUnit4TestXmlListener( mockModelSupplier, mockRequestFactory, fakeSignalHandlers, mockXmlStream, errPrintStream); Request request = Request.classWithoutSuiteMethod(PassingTest.class); Description suiteDescription = request.getRunner().getDescription(); when(mockModelSupplier.get()).thenReturn(mockModel); listener.testRunStarted(suiteDescription); assertEquals(1, fakeSignalHandlers.handlers.size()); fakeSignalHandlers.handlers.get(0).handle(new Signal("TERM")); String errOutput = errStream.toString(CHARSET); assertTrue("expected signal name in stderr", errOutput.contains("SIGTERM")); assertTrue("expected message in stderr", errOutput.contains("Done writing test XML")); InOrder inOrder = inOrder(mockRequestFactory, mockModel); inOrder.verify(mockRequestFactory).cancelRun(); inOrder.verify(mockModel).testRunInterrupted(); inOrder.verify(mockModel).writeAsXml(mockXmlStream); } @Test public void writesXmlAtTestEnd() throws Exception { TestSuiteModelSupplier mockModelSupplier = mock(TestSuiteModelSupplier.class); TestSuiteModel mockModel = mock(TestSuiteModel.class); CancellableRequestFactory mockRequestFactory = mock(CancellableRequestFactory.class); OutputStream mockXmlStream = mock(OutputStream.class); JUnit4TestXmlListener listener = new JUnit4TestXmlListener( mockModelSupplier, mockRequestFactory, fakeSignalHandlers, mockXmlStream, errPrintStream); when(mockModelSupplier.get()).thenReturn(mockModel); JUnitCore core = new JUnitCore(); core.addListener(listener); core.run(Request.classWithoutSuiteMethod(PassingTest.class)); assertEquals("no output to stderr expected", 0, errStream.size()); verify(mockModel).writeAsXml(mockXmlStream); verify(mockRequestFactory, never()).cancelRun(); } @Test public void assumptionViolationsAreReportedAsSkippedTests() throws Exception { TestSuiteModelSupplier mockModelSupplier = mock(TestSuiteModelSupplier.class); TestSuiteModel mockModel = mock(TestSuiteModel.class); CancellableRequestFactory mockRequestFactory = mock(CancellableRequestFactory.class); OutputStream mockXmlStream = mock(OutputStream.class); JUnit4TestXmlListener listener = new JUnit4TestXmlListener( mockModelSupplier, mockRequestFactory, fakeSignalHandlers, mockXmlStream, errPrintStream); Request request = Request.classWithoutSuiteMethod(TestWithAssumptionViolation.class); Description suiteDescription = request.getRunner().getDescription(); Description testDescription = suiteDescription.getChildren().get(0); when(mockModelSupplier.get()).thenReturn(mockModel); JUnitCore core = new JUnitCore(); core.addListener(listener); core.run(request); assertEquals("no output to stderr expected", 0, errStream.size()); InOrder inOrder = inOrder(mockModel); inOrder.verify(mockModel).testSkipped(testDescription); inOrder.verify(mockModel).writeAsXml(mockXmlStream); verify(mockRequestFactory, never()).cancelRun(); } @Test public void assumptionViolationsAtSuiteLevelAreReportedAsSkippedSuite() throws Exception { TestSuiteModelSupplier mockModelSupplier = mock(TestSuiteModelSupplier.class); TestSuiteModel mockModel = mock(TestSuiteModel.class); CancellableRequestFactory mockRequestFactory = mock(CancellableRequestFactory.class); OutputStream mockXmlStream = mock(OutputStream.class); JUnit4TestXmlListener listener = new JUnit4TestXmlListener( mockModelSupplier, mockRequestFactory, fakeSignalHandlers, mockXmlStream, errPrintStream); Request request = Request.classWithoutSuiteMethod( TestWithAssumptionViolationOnTheSuiteLevel.class); Description suiteDescription = request.getRunner().getDescription(); when(mockModelSupplier.get()).thenReturn(mockModel); JUnitCore core = new JUnitCore(); core.addListener(listener); core.run(request); assertEquals("no output to stderr expected", 0, errStream.size()); InOrder inOrder = inOrder(mockModel); inOrder.verify(mockModel).testSkipped(suiteDescription); inOrder.verify(mockModel).writeAsXml(mockXmlStream); verify(mockRequestFactory, never()).cancelRun(); } @Test public void failuresAreReported() throws Exception { TestSuiteModelSupplier mockModelSupplier = mock(TestSuiteModelSupplier.class); TestSuiteModel mockModel = mock(TestSuiteModel.class); CancellableRequestFactory mockRequestFactory = mock(CancellableRequestFactory.class); OutputStream mockXmlStream = mock(OutputStream.class); JUnit4TestXmlListener listener = new JUnit4TestXmlListener( mockModelSupplier, mockRequestFactory, fakeSignalHandlers, mockXmlStream, errPrintStream); Request request = Request.classWithoutSuiteMethod(FailingTest.class); Description suiteDescription = request.getRunner().getDescription(); Description testDescription = suiteDescription.getChildren().get(0); when(mockModelSupplier.get()).thenReturn(mockModel); JUnitCore core = new JUnitCore(); core.addListener(listener); core.run(request); assertEquals("no output to stderr expected", 0, errStream.size()); InOrder inOrder = inOrder(mockModel); inOrder.verify(mockModel).testFailure(eq(testDescription), any(Throwable.class)); inOrder.verify(mockModel).writeAsXml(mockXmlStream); verify(mockRequestFactory, never()).cancelRun(); } @Test public void ignoredTestAreReportedAsSuppressedTests() throws Exception { TestSuiteModelSupplier mockModelSupplier = mock(TestSuiteModelSupplier.class); TestSuiteModel mockModel = mock(TestSuiteModel.class); CancellableRequestFactory mockRequestFactory = mock(CancellableRequestFactory.class); OutputStream mockXmlStream = mock(OutputStream.class); JUnit4TestXmlListener listener = new JUnit4TestXmlListener( mockModelSupplier, mockRequestFactory, fakeSignalHandlers, mockXmlStream, errPrintStream); Request request = Request.classWithoutSuiteMethod(TestWithIgnoredTestCase.class); Description suiteDescription = request.getRunner().getDescription(); Description testDescription = suiteDescription.getChildren().get(0); when(mockModelSupplier.get()).thenReturn(mockModel); JUnitCore core = new JUnitCore(); core.addListener(listener); core.run(request); assertEquals("no output to stderr expected", 0, errStream.size()); InOrder inOrder = inOrder(mockModel); inOrder.verify(mockModel).testSuppressed(testDescription); inOrder.verify(mockModel).writeAsXml(mockXmlStream); verify(mockRequestFactory, never()).cancelRun(); } /** * Test with a method that always passes. */ public static class PassingTest { @Test public void alwaysPasses() { } } /** * Test with a method that always fails. */ public static class FailingTest { @Test public void alwaysFails() { fail(); } } /** * Test with a method that is always skipped. */ public static class TestWithAssumptionViolation { @Test public void alwaysSkipped() { assumeTrue(false); } } /** * Test with a method that is always skipped. */ public static class TestWithAssumptionViolationOnTheSuiteLevel { @BeforeClass public static void failedSuiteLevelAssumption() { assumeTrue(false); } @Test public void fakeTest() {} } public static class TestWithIgnoredTestCase { @Test @Ignore public void alwaysIgnored() { } } private static class FakeSignalHandlers extends SignalHandlers { public List<SignalHandler> handlers = Lists.newArrayList(); public FakeSignalHandlers() { super(null); } @Override public void installHandler(Signal signal, SignalHandler signalHandler) { if (signal.getName().equals("TERM")) { handlers.add(signalHandler); } } } private interface TestSuiteModelSupplier extends Supplier<TestSuiteModel> { } }