blob: 253d21f4f4f57d8ff041ddd45fd5a9522a37eb97 [file] [log] [blame]
// Copyright 2015 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.devtools.build.lib.runtime;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.AdditionalMatchers.find;
import static org.mockito.AdditionalMatchers.not;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.contains;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
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.ImmutableList;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.test.TestProvider;
import com.google.devtools.build.lib.analysis.test.TestProvider.TestParams;
import com.google.devtools.build.lib.buildeventstream.BuildEventContext;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.TestStatus;
import com.google.devtools.build.lib.buildeventstream.PathConverter;
import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.util.io.AnsiTerminalPrinter;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import com.google.devtools.build.lib.view.test.TestStatus.BlazeTestStatus;
import com.google.devtools.build.lib.view.test.TestStatus.FailedTestCasesStatus;
import com.google.devtools.build.lib.view.test.TestStatus.TestCase;
import com.google.devtools.build.lib.view.test.TestStatus.TestCase.Status;
import com.google.protobuf.util.Durations;
import com.google.protobuf.util.Timestamps;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.InOrder;
import org.mockito.Mockito;
@RunWith(JUnit4.class)
public class TestSummaryTest {
private static final String ANY_STRING = ".*?";
private static final String PATH = "package";
private static final String TARGET_NAME = "name";
private ConfiguredTarget stubTarget;
private static final ImmutableList<Long> SMALL_TIMING = ImmutableList.of(1L, 2L, 3L, 4L);
private static final int CACHED = SMALL_TIMING.size();
private static final int NOT_CACHED = 0;
private FileSystem fs;
private TestSummary.Builder basicBuilder;
@Before
public final void createFileSystem() throws Exception {
fs = new InMemoryFileSystem(BlazeClock.instance(), DigestHashFunction.SHA256);
stubTarget = stubTarget();
basicBuilder = getTemplateBuilder();
}
private TestSummary.Builder getTemplateBuilder() {
BuildConfigurationValue configuration = Mockito.mock(BuildConfigurationValue.class);
when(configuration.checksum()).thenReturn("abcdef");
return TestSummary.newBuilder(stubTarget)
.setConfiguration(configuration)
.setStatus(BlazeTestStatus.PASSED)
.setNumCached(NOT_CACHED)
.setActionRan(true)
.setRanRemotely(false)
.setWasUnreportedWrongSize(false);
}
private List<Path> getPathList(String... names) {
List<Path> list = new ArrayList<>();
for (String name : names) {
list.add(fs.getPath(name));
}
return list;
}
@Test
public void testShouldProperlyTestLabels() throws Exception {
ConfiguredTarget target = target("somepath", "MyTarget");
String expectedString = ANY_STRING + "//somepath:MyTarget" + ANY_STRING;
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summaryStatus = createTestSummary(target, BlazeTestStatus.PASSED, CACHED);
TestSummaryPrinter.print(summaryStatus, terminalPrinter, Path::getPathString, true, false);
terminalPrinter.print(find(expectedString));
}
@Test
public void testShouldPrintPassedStatus() throws Exception {
String expectedString = ANY_STRING + "INFO" + ANY_STRING + BlazeTestStatus.PASSED + ANY_STRING;
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summary = createTestSummary(stubTarget, BlazeTestStatus.PASSED, NOT_CACHED);
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, true, false);
verify(terminalPrinter).print(find(expectedString));
}
@Test
public void testShouldPrintFailedStatus() throws Exception {
String expectedString = ANY_STRING + "ERROR" + ANY_STRING + BlazeTestStatus.FAILED + ANY_STRING;
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summary = createTestSummary(stubTarget, BlazeTestStatus.FAILED, NOT_CACHED);
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, true, false);
terminalPrinter.print(find(expectedString));
}
private void assertShouldNotPrint(BlazeTestStatus status, boolean verboseSummary) {
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummaryPrinter.print(
createTestSummary(stubTarget, status, NOT_CACHED),
terminalPrinter,
Path::getPathString,
verboseSummary,
false);
verify(terminalPrinter, never()).print(anyString());
}
@Test
public void testShouldPrintFailedToBuildStatus() {
String expectedString = ANY_STRING + "INFO" + ANY_STRING + BlazeTestStatus.FAILED_TO_BUILD;
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summary = createTestSummary(BlazeTestStatus.FAILED_TO_BUILD, NOT_CACHED);
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, true, false);
terminalPrinter.print(find(expectedString));
}
@Test
public void testShouldNotPrintFailedToBuildStatus() {
assertShouldNotPrint(BlazeTestStatus.FAILED_TO_BUILD, false);
}
@Test
public void testShouldNotPrintHaltedStatus() {
assertShouldNotPrint(BlazeTestStatus.BLAZE_HALTED_BEFORE_TESTING, true);
}
@Test
public void testShouldPrintCachedStatus() throws Exception {
String expectedString = ANY_STRING + "\\(cached" + ANY_STRING;
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summary = createTestSummary(stubTarget, BlazeTestStatus.PASSED, CACHED);
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, true, false);
terminalPrinter.print(find(expectedString));
}
@Test
public void testPartialCachedStatus() throws Exception {
String expectedString = ANY_STRING + "\\(3/4 cached" + ANY_STRING;
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summary = createTestSummary(stubTarget, BlazeTestStatus.PASSED, CACHED - 1);
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, true, false);
terminalPrinter.print(find(expectedString));
}
@Test
public void testIncompleteCached() throws Exception {
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summary = createTestSummary(stubTarget, BlazeTestStatus.INCOMPLETE, CACHED - 1);
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, true, false);
verify(terminalPrinter).print(not(contains("cached")));
}
@Test
public void testShouldPrintUncachedStatus() throws Exception {
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summary = createTestSummary(stubTarget, BlazeTestStatus.PASSED, NOT_CACHED);
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, true, false);
verify(terminalPrinter).print(not(contains("cached")));
}
@Test
public void testNoTiming() throws Exception {
String expectedString = ANY_STRING + "INFO" + ANY_STRING + BlazeTestStatus.PASSED;
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summary = createTestSummary(stubTarget, BlazeTestStatus.PASSED, NOT_CACHED);
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, true, false);
terminalPrinter.print(find(expectedString));
}
@Test
public void testBuilder() throws Exception {
// No need to copy if built twice in a row; no direct setters on the object.
TestSummary summary = basicBuilder.build();
TestSummary sameSummary = basicBuilder.build();
assertThat(sameSummary).isSameInstanceAs(summary);
basicBuilder.addTestTimes(ImmutableList.of(40L));
TestSummary summaryCopy = basicBuilder.build();
assertThat(summaryCopy.getTarget()).isEqualTo(summary.getTarget());
assertThat(summaryCopy.getStatus()).isEqualTo(summary.getStatus());
assertThat(summaryCopy.numCached()).isEqualTo(summary.numCached());
assertThat(summaryCopy).isNotSameInstanceAs(summary);
assertThat(summary.totalRuns()).isEqualTo(0);
assertThat(summaryCopy.totalRuns()).isEqualTo(1);
// Check that the builder can add a new warning to the copy,
// despite the immutability of the original.
basicBuilder.addTestTimes(ImmutableList.of(60L));
TestSummary fiftyCached = basicBuilder.setNumCached(50).build();
assertThat(fiftyCached.getStatus()).isEqualTo(summary.getStatus());
assertThat(fiftyCached.numCached()).isEqualTo(50);
assertThat(fiftyCached.totalRuns()).isEqualTo(2);
TestSummary sixtyCached = basicBuilder.setNumCached(60).build();
assertThat(sixtyCached.numCached()).isEqualTo(60);
assertThat(fiftyCached.numCached()).isEqualTo(50);
}
@Test
public void testAsStreamProto() throws Exception {
TestParams testParams = mock(TestParams.class);
when(testParams.getRuns()).thenReturn(2);
when(testParams.getShards()).thenReturn(3);
TestProvider testProvider = new TestProvider(testParams);
when(stubTarget.getProvider(eq(TestProvider.class))).thenReturn(testProvider);
PathConverter pathConverter = mock(PathConverter.class);
when(pathConverter.apply(any(Path.class)))
.thenAnswer(
invocation -> "/path/to" + ((Path) invocation.getArguments()[0]).getPathString());
BuildEventContext converters = mock(BuildEventContext.class);
when(converters.pathConverter()).thenReturn(pathConverter);
TestSummary summary =
basicBuilder
.setStatus(BlazeTestStatus.FAILED)
.addPassedLogs(getPathList("/apple"))
.addFailedLogs(getPathList("/pear"))
.mergeTiming(1000, 300)
.build();
assertThat(summary.asStreamProto(converters).getTestSummary())
.isEqualTo(
BuildEventStreamProtos.TestSummary.newBuilder()
.setOverallStatus(TestStatus.FAILED)
.setFirstStartTimeMillis(1000)
.setFirstStartTime(Timestamps.fromMillis(1000))
.setLastStopTimeMillis(1300)
.setLastStopTime(Timestamps.fromMillis(1300))
.setTotalRunDurationMillis(300)
.setTotalRunDuration(Durations.fromMillis(300))
.setRunCount(2)
.setShardCount(3)
.addPassed(BuildEventStreamProtos.File.newBuilder().setUri("/path/to/apple"))
.addFailed(BuildEventStreamProtos.File.newBuilder().setUri("/path/to/pear"))
.build());
}
@Test
public void testSingleTime() throws Exception {
String expectedString = ANY_STRING + "INFO" + ANY_STRING + BlazeTestStatus.PASSED + ANY_STRING +
"in 3.4s";
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summary = basicBuilder.addTestTimes(ImmutableList.of(3412L)).build();
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, true, false);
terminalPrinter.print(find(expectedString));
}
@Test
public void testNoTime() throws Exception {
// The last part matches anything not containing "in".
String expectedString = ANY_STRING + "INFO" + ANY_STRING + BlazeTestStatus.PASSED + "(?!in)*";
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summary = basicBuilder.addTestTimes(ImmutableList.of(3412L)).build();
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, false, false);
terminalPrinter.print(find(expectedString));
}
@Test
public void testMultipleTimes() throws Exception {
String expectedString = ANY_STRING + "INFO" + ANY_STRING + BlazeTestStatus.PASSED + ANY_STRING +
"\n Stats over 3 runs: max = 3.0s, min = 1.0s, " +
"avg = 2.0s, dev = 0.8s";
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summary = basicBuilder
.addTestTimes(ImmutableList.of(1000L, 2000L, 3000L))
.build();
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, true, false);
terminalPrinter.print(find(expectedString));
}
@Test
public void testCoverageDataReferences() throws Exception {
List<Path> paths = getPathList("/cov1.dat", "/cov2.dat", "/cov3.dat", "/cov4.dat");
FileSystemUtils.writeContentAsLatin1(paths.get(1), "something");
FileSystemUtils.writeContentAsLatin1(paths.get(3), "");
FileSystemUtils.writeContentAsLatin1(paths.get(3), "something else");
TestSummary summary = basicBuilder.addCoverageFiles(paths).build();
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, true, false);
verify(terminalPrinter).print(find(ANY_STRING + "INFO" + ANY_STRING + BlazeTestStatus.PASSED));
verify(terminalPrinter).print(find(" /cov2.dat"));
verify(terminalPrinter).print(find(" /cov4.dat"));
}
@Test
public void testFlakyAttempts() throws Exception {
String expectedString = ANY_STRING + "WARNING" + ANY_STRING + BlazeTestStatus.FLAKY +
ANY_STRING + ", failed in 2 out of 3";
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summary = basicBuilder
.setStatus(BlazeTestStatus.FLAKY)
.addPassedLogs(getPathList("/a"))
.addFailedLogs(getPathList("/b", "/c"))
.build();
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, true, false);
terminalPrinter.print(find(expectedString));
}
@Test
public void testNumberOfFailedRuns() throws Exception {
String expectedString = ANY_STRING + "ERROR" + ANY_STRING + BlazeTestStatus.FAILED +
ANY_STRING + "in 2 out of 3";
AnsiTerminalPrinter terminalPrinter = Mockito.mock(AnsiTerminalPrinter.class);
TestSummary summary = basicBuilder
.setStatus(BlazeTestStatus.FAILED)
.addPassedLogs(getPathList("/a"))
.addFailedLogs(getPathList("/b", "/c"))
.build();
TestSummaryPrinter.print(summary, terminalPrinter, Path::getPathString, true, false);
terminalPrinter.print(find(expectedString));
}
@Test
public void testFileNamesNotShown() throws Exception {
List<TestCase> emptyDetails = ImmutableList.of();
TestSummary summary = basicBuilder
.setStatus(BlazeTestStatus.FAILED)
.addPassedLogs(getPathList("/apple"))
.addFailedLogs(getPathList("/pear"))
.addCoverageFiles(getPathList("/maracuja"))
.addFailedTestCases(emptyDetails, FailedTestCasesStatus.FULL)
.build();
// Check that only //package:name is printed.
AnsiTerminalPrinter printer = Mockito.mock(AnsiTerminalPrinter.class);
TestSummaryPrinter.print(summary, printer, Path::getPathString, true, true);
verify(printer).print(contains("//package:name"));
}
@Test
public void testMessageShownWhenTestCasesMissing() throws Exception {
ImmutableList<TestCase> emptyList = ImmutableList.of();
TestSummary summary = createTestSummaryWithDetails(
BlazeTestStatus.FAILED, emptyList, FailedTestCasesStatus.NOT_AVAILABLE);
AnsiTerminalPrinter printer = Mockito.mock(AnsiTerminalPrinter.class);
TestSummaryPrinter.print(summary, printer, Path::getPathString, true, true);
verify(printer).print(contains("//package:name"));
verify(printer).print(contains("not available"));
}
@Test
public void testMessageShownForPartialResults() throws Exception {
ImmutableList<TestCase> testCases =
ImmutableList.of(newDetail("orange", TestCase.Status.FAILED, 1500L));
TestSummary summary = createTestSummaryWithDetails(BlazeTestStatus.FAILED, testCases,
FailedTestCasesStatus.PARTIAL);
AnsiTerminalPrinter printer = Mockito.mock(AnsiTerminalPrinter.class);
TestSummaryPrinter.print(summary, printer, Path::getPathString, true, true);
verify(printer).print(contains("//package:name"));
verify(printer).print(find("FAILED.*orange"));
verify(printer).print(contains("incomplete"));
}
private TestCase newDetail(String name, TestCase.Status status, long duration) {
return TestCase.newBuilder()
.setName(name)
.setStatus(status)
.setRunDurationMillis(duration)
.build();
}
@Test
public void testTestCaseNamesShownWhenNeeded() throws Exception {
TestCase detailPassed =
newDetail("strawberry", TestCase.Status.PASSED, 1000L);
TestCase detailFailed =
newDetail("orange", TestCase.Status.FAILED, 1500L);
TestSummary summaryPassed = createTestSummaryWithDetails(
BlazeTestStatus.PASSED, Arrays.asList(detailPassed));
TestSummary summaryFailed = createTestSummaryWithDetails(
BlazeTestStatus.FAILED, Arrays.asList(detailPassed, detailFailed));
assertThat(summaryFailed.getStatus()).isEqualTo(BlazeTestStatus.FAILED);
AnsiTerminalPrinter printerPassed = Mockito.mock(AnsiTerminalPrinter.class);
TestSummaryPrinter.print(summaryPassed, printerPassed, Path::getPathString, true, true);
verify(printerPassed).print(contains("//package:name"));
AnsiTerminalPrinter printerFailed = Mockito.mock(AnsiTerminalPrinter.class);
TestSummaryPrinter.print(summaryFailed, printerFailed, Path::getPathString, true, true);
verify(printerFailed).print(contains("//package:name"));
verify(printerFailed).print(find("FAILED.*orange *\\(1\\.5"));
}
@Test
public void testShowTestCaseNames() throws Exception {
TestCase detailPassed = newDetail("strawberry", TestCase.Status.PASSED, 1000L);
TestCase detailFailed = newDetail("orange", TestCase.Status.FAILED, 1500L);
TestSummary summaryPassed =
createPassedTestSummary(BlazeTestStatus.PASSED, Arrays.asList(detailPassed));
TestSummary summaryFailed =
createTestSummaryWithDetails(
BlazeTestStatus.FAILED, Arrays.asList(detailPassed, detailFailed));
assertThat(summaryFailed.getStatus()).isEqualTo(BlazeTestStatus.FAILED);
AnsiTerminalPrinter printerPassed = Mockito.mock(AnsiTerminalPrinter.class);
TestSummaryPrinter.print(summaryPassed, printerPassed, Path::getPathString, true, true);
verify(printerPassed).print(contains("//package:name"));
verify(printerPassed).print(find("PASSED.*strawberry *\\(1\\.0"));
AnsiTerminalPrinter printerFailed = Mockito.mock(AnsiTerminalPrinter.class);
TestSummaryPrinter.print(summaryFailed, printerFailed, Path::getPathString, true, true);
verify(printerFailed).print(contains("//package:name"));
verify(printerFailed).print(find("FAILED.*orange *\\(1\\.5"));
}
@Test
public void testTestCaseNamesOrdered() throws Exception {
TestCase[] details = {
newDetail("apple", TestCase.Status.FAILED, 1000L),
newDetail("banana", TestCase.Status.FAILED, 1000L),
newDetail("cranberry", TestCase.Status.FAILED, 1000L)
};
// The exceedingly dumb approach: writing all the permutations down manually
// is simply easier than any way of generating them.
int[][] permutations = {
{ 0, 1, 2 },
{ 0, 2, 1 },
{ 1, 0, 2 },
{ 1, 2, 0 },
{ 2, 0, 1 },
{ 2, 1, 0 }
};
for (int[] permutation : permutations) {
List<TestCase> permutatedDetails = new ArrayList<>();
for (int element : permutation) {
permutatedDetails.add(details[element]);
}
TestSummary summary = createTestSummaryWithDetails(BlazeTestStatus.FAILED, permutatedDetails);
// A mock that checks the ordering of method calls
AnsiTerminalPrinter printer = Mockito.mock(AnsiTerminalPrinter.class);
TestSummaryPrinter.print(summary, printer, Path::getPathString, true, true);
InOrder order = Mockito.inOrder(printer);
order.verify(printer).print(contains("//package:name"));
order.verify(printer).print(find("FAILED.*apple"));
order.verify(printer).print(find("FAILED.*banana"));
order.verify(printer).print(find("FAILED.*cranberry"));
}
}
@Test
public void testCachedResultsFirstInSort() throws Exception {
TestSummary summaryFailedCached = createTestSummary(BlazeTestStatus.FAILED, CACHED);
TestSummary summaryFailedNotCached = createTestSummary(BlazeTestStatus.FAILED, NOT_CACHED);
TestSummary summaryPassedCached = createTestSummary(BlazeTestStatus.PASSED, CACHED);
TestSummary summaryPassedNotCached = createTestSummary(BlazeTestStatus.PASSED, NOT_CACHED);
// This way we can make the test independent from the sort order of FAILEd
// and PASSED.
assertThat(summaryFailedCached.compareTo(summaryPassedNotCached)).isLessThan(0);
assertThat(summaryPassedCached.compareTo(summaryFailedNotCached)).isLessThan(0);
}
@Test
public void testCollectingFailedDetails() throws Exception {
TestCase rootCase =
TestCase.newBuilder()
.setName("tests")
.setRunDurationMillis(5000L)
.addChild(newDetail("apple", TestCase.Status.FAILED, 1000L))
.addChild(newDetail("cherry", TestCase.Status.ERROR, 1000L))
.build();
TestSummary summary =
getTemplateBuilder().collectTestCases(rootCase).setStatus(BlazeTestStatus.FAILED).build();
AnsiTerminalPrinter printer = Mockito.mock(AnsiTerminalPrinter.class);
TestSummaryPrinter.print(summary, printer, Path::getPathString, true, true);
verify(printer).print(contains("//package:name"));
verify(printer).print(find("FAILED.*apple"));
verify(printer).print(find("ERROR.*cherry"));
}
@Test
public void testCollectingAllDetails() throws Exception {
TestCase rootCase =
TestCase.newBuilder()
.setName("tests")
.setRunDurationMillis(5000L)
.addChild(newDetail("apple", TestCase.Status.FAILED, 1000L))
.addChild(newDetail("banana", TestCase.Status.PASSED, 1000L))
.addChild(newDetail("cherry", TestCase.Status.ERROR, 1000L))
.addChild(newDetail("sugarcane", Status.SKIPPED, 0))
.build();
TestSummary summary =
getTemplateBuilder().collectTestCases(rootCase).setStatus(BlazeTestStatus.FAILED).build();
AnsiTerminalPrinter printer = Mockito.mock(AnsiTerminalPrinter.class);
TestSummaryPrinter.print(summary, printer, Path::getPathString, true, true);
verify(printer).print(contains("//package:name"));
verify(printer).print(find("FAILED.*apple"));
verify(printer).print(find("PASSED.*banana"));
verify(printer).print(find("ERROR.*cherry"));
verify(printer).print(find("SKIPPED.*sugarcane"));
}
@Test
public void testCollectingPassedDetails() throws Exception {
TestCase rootCase =
TestCase.newBuilder()
.setName("tests")
.setRunDurationMillis(5000L)
.addChild(newDetail("apple", TestCase.Status.PASSED, 1000L))
.addChild(newDetail("banana", Status.SKIPPED, 0))
.build();
TestSummary summary =
getTemplateBuilder().collectTestCases(rootCase).setStatus(BlazeTestStatus.PASSED).build();
AnsiTerminalPrinter printer = Mockito.mock(AnsiTerminalPrinter.class);
TestSummaryPrinter.print(summary, printer, Path::getPathString, true, true);
verify(printer).print(contains("//package:name"));
verify(printer).print(find("PASSED.*apple"));
verify(printer).print(find("SKIPPED.*banana"));
}
@Test
public void countTotalTestCases() throws Exception {
TestCase rootCase =
TestCase.newBuilder()
.setName("tests")
.setRunDurationMillis(5000L)
.addChild(newDetail("apple", TestCase.Status.FAILED, 1000L))
.addChild(newDetail("banana", TestCase.Status.PASSED, 1000L))
.addChild(newDetail("cherry", TestCase.Status.ERROR, 1000L))
.addChild(newDetail("sugarcane", Status.SKIPPED, 0))
.build();
TestSummary summary =
getTemplateBuilder().collectTestCases(rootCase).setStatus(BlazeTestStatus.FAILED).build();
assertThat(summary.getTotalTestCases()).isEqualTo(4);
}
@Test
public void countUnknownTestCases() throws Exception {
TestSummary summary =
getTemplateBuilder().collectTestCases(null).setStatus(BlazeTestStatus.FAILED).build();
assertThat(summary.getTotalTestCases()).isEqualTo(1);
assertThat(summary.getUnkownTestCases()).isEqualTo(1);
}
@Test
public void countNotRunTestCases() throws Exception {
TestCase a =
TestCase.newBuilder()
.addChild(
TestCase.newBuilder().setName("A").setStatus(Status.PASSED).setRun(true).build())
.addChild(
TestCase.newBuilder().setName("B").setStatus(Status.PASSED).setRun(true).build())
.addChild(
TestCase.newBuilder().setName("C").setStatus(Status.PASSED).setRun(false).build())
.build();
TestSummary summary =
getTemplateBuilder().collectTestCases(a).setStatus(BlazeTestStatus.FAILED).build();
assertThat(summary.getTotalTestCases()).isEqualTo(2);
assertThat(summary.getUnkownTestCases()).isEqualTo(0);
assertThat(summary.getFailedTestCases()).isEmpty();
}
@Test
public void countTotalTestCasesInNestedTree() throws Exception {
TestCase aCase =
TestCase.newBuilder()
.setName("tests-1")
.setRunDurationMillis(5000L)
.addChild(newDetail("apple", TestCase.Status.FAILED, 1000L))
.addChild(newDetail("banana", TestCase.Status.PASSED, 1000L))
.addChild(newDetail("cherry", TestCase.Status.ERROR, 1000L))
.build();
TestCase anotherCase =
TestCase.newBuilder()
.setName("tests-2")
.setRunDurationMillis(5000L)
.addChild(newDetail("apple", TestCase.Status.FAILED, 1000L))
.addChild(newDetail("banana", TestCase.Status.PASSED, 1000L))
.addChild(newDetail("cherry", TestCase.Status.ERROR, 1000L))
.build();
TestCase rootCase =
TestCase.newBuilder().setName("tests").addChild(aCase).addChild(anotherCase).build();
TestSummary summary =
getTemplateBuilder().collectTestCases(rootCase).setStatus(BlazeTestStatus.FAILED).build();
assertThat(summary.getTotalTestCases()).isEqualTo(6);
}
private ConfiguredTarget target(String path, String targetName) throws Exception {
ConfiguredTarget target = Mockito.mock(ConfiguredTarget.class);
when(target.getLabel()).thenReturn(Label.create(path, targetName));
when(target.getConfigurationChecksum()).thenReturn("abcdef");
TestParams mockParams = Mockito.mock(TestParams.class);
when(mockParams.getShards()).thenReturn(1);
when(target.getProvider(TestProvider.class)).thenReturn(new TestProvider(mockParams));
return target;
}
private ConfiguredTarget stubTarget() throws Exception {
return target(PATH, TARGET_NAME);
}
private TestSummary createPassedTestSummary(BlazeTestStatus status, List<TestCase> details) {
return getTemplateBuilder().setStatus(status).addPassedTestCases(details).build();
}
private TestSummary createTestSummaryWithDetails(BlazeTestStatus status,
List<TestCase> details) {
TestSummary summary = getTemplateBuilder()
.setStatus(status)
.addFailedTestCases(details, FailedTestCasesStatus.FULL)
.build();
return summary;
}
private TestSummary createTestSummaryWithDetails(
BlazeTestStatus status, List<TestCase> testCaseList,
FailedTestCasesStatus detailsStatus) {
TestSummary summary = getTemplateBuilder()
.setStatus(status)
.addFailedTestCases(testCaseList, detailsStatus)
.build();
return summary;
}
private static TestSummary createTestSummary(ConfiguredTarget target, BlazeTestStatus status,
int numCached) {
ImmutableList<TestCase> emptyList = ImmutableList.of();
return TestSummary.newBuilder(target)
.setStatus(status)
.setNumCached(numCached)
.setActionRan(true)
.setRanRemotely(false)
.setWasUnreportedWrongSize(false)
.addFailedTestCases(emptyList, FailedTestCasesStatus.FULL)
.addTestTimes(SMALL_TIMING)
.build();
}
private TestSummary createTestSummary(BlazeTestStatus status, int numCached) {
TestSummary summary = getTemplateBuilder()
.setStatus(status)
.setNumCached(numCached)
.addTestTimes(SMALL_TIMING)
.build();
return summary;
}
}