in src/com/facebook/buck/cli/TestCommand.java [386:523]
private int runTests(
Iterable<TestRule> tests,
BuildContext buildContext,
ExecutionContext executionContext,
StepRunner stepRunner,
final TestCommandOptions options) throws IOException {
ImmutableSet<JavaLibraryRule> rulesUnderTest;
// If needed, we first run instrumentation on the class files.
if (options.isCodeCoverageEnabled()) {
rulesUnderTest = getRulesUnderTest(tests);
if (!rulesUnderTest.isEmpty()) {
try {
stepRunner.runStep(
new MakeCleanDirectoryStep(JUnitStep.EMMA_OUTPUT_DIR));
stepRunner.runStep(
getInstrumentCommand(
rulesUnderTest,
executionContext.getProjectFilesystem()));
} catch (StepFailedException e) {
console.printBuildFailureWithoutStacktrace(e);
return 1;
}
}
} else {
rulesUnderTest = ImmutableSet.of();
}
getBuckEventBus().post(TestRunEvent.started(
options.isRunAllTests(), options.getArgumentsFormattedAsBuildTargets()));
// Start running all of the tests. The result of each java_test() rule is represented as a
// ListenableFuture.
List<ListenableFuture<TestResults>> results = Lists.newArrayList();
// Unless `--verbose 0` is specified, print out test results as they become available.
// Failures with the ListenableFuture should always be printed, as they indicate an error with
// Buck, not the test being run.
Verbosity verbosity = console.getVerbosity();
final boolean printTestResults = (verbosity != Verbosity.SILENT);
FutureCallback<TestResults> onTestFinishedCallback = new FutureCallback<TestResults>() {
@Override
public void onSuccess(TestResults testResults) {
if (printTestResults) {
getBuckEventBus().post(IndividualTestEvent.finished(
options.getArgumentsFormattedAsBuildTargets(), testResults));
}
}
@Override
public void onFailure(Throwable throwable) {
// This should never happen, but if it does, that means that something has gone awry, so
// we should bubble it up.
throwable.printStackTrace(getStdErr());
}
};
TestRuleKeyFileHelper testRuleKeyFileHelper = new TestRuleKeyFileHelper(
executionContext.getProjectFilesystem());
for (TestRule test : tests) {
List<Step> steps;
// Determine whether the test needs to be executed.
boolean isTestRunRequired =
isTestRunRequiredForTest(test, executionContext, testRuleKeyFileHelper);
if (isTestRunRequired) {
getBuckEventBus().post(IndividualTestEvent.started(
options.getArgumentsFormattedAsBuildTargets()));
ImmutableList.Builder<Step> stepsBuilder = ImmutableList.builder();
List<Step> testSteps = test.runTests(buildContext, executionContext);
if (!testSteps.isEmpty()) {
stepsBuilder.addAll(testSteps);
stepsBuilder.add(testRuleKeyFileHelper.createRuleKeyInDirStep(test));
}
steps = stepsBuilder.build();
} else {
steps = ImmutableList.of();
}
// Always run the commands, even if the list of commands as empty. There may be zero commands
// because the rule is cached, but its results must still be processed.
ListenableFuture<TestResults> testResults =
stepRunner.runStepsAndYieldResult(steps,
getCachingStatusTransformingCallable(
isTestRunRequired,
test.interpretTestResults(executionContext)),
test.getBuildTarget());
Futures.addCallback(testResults, onTestFinishedCallback);
results.add(testResults);
}
// Block until all the tests have finished running.
ListenableFuture<List<TestResults>> uberFuture = Futures.allAsList(results);
List<TestResults> completedResults;
try {
completedResults = uberFuture.get();
} catch (InterruptedException e) {
e.printStackTrace(getStdErr());
return 1;
} catch (ExecutionException e) {
e.printStackTrace(getStdErr());
return 1;
}
getBuckEventBus().post(TestRunEvent.finished(
options.getArgumentsFormattedAsBuildTargets(), completedResults));
// Write out the results as XML, if requested.
if (options.getPathToXmlTestOutput() != null) {
try (Writer writer = Files.newWriter(
new File(options.getPathToXmlTestOutput()),
Charsets.UTF_8)) {
writeXmlOutput(completedResults, writer);
}
}
// Generate the code coverage report.
if (options.isCodeCoverageEnabled() && !rulesUnderTest.isEmpty()) {
try {
Optional<DefaultJavaPackageFinder> defaultJavaPackageFinderOptional =
options.getJavaPackageFinder();
stepRunner.runStep(
getReportCommand(rulesUnderTest, defaultJavaPackageFinderOptional, getProjectFilesystem()));
} catch (StepFailedException e) {
console.printBuildFailureWithoutStacktrace(e);
return 1;
}
}
boolean failures = Iterables.any(completedResults, new Predicate<TestResults>() {
@Override
public boolean apply(TestResults results) {
return !results.isSuccess();
}
});
return failures ? 1 : 0;
}