public void afterTest(TestDescriptor testDescriptor, TestResult result) {
   if (!testDescriptor.isComposite()) {
     String className = testDescriptor.getClassName();
     TestMethodResult methodResult = new TestMethodResult(testDescriptor.getName(), result);
     TestClassResult classResult = results.get(className);
     if (classResult == null) {
       classResult = new TestClassResult(className, result.getStartTime());
       results.put(className, classResult);
     }
     classResult.add(methodResult);
   }
 }
 public void onOutput(TestDescriptor testDescriptor, TestOutputEvent outputEvent) {
   String className = testDescriptor.getClassName();
   if (className == null) {
     // this means that we receive an output before even starting any class (or too late).
     // we don't have a place for such output in any of the reports so skipping.
     return;
   }
   cachingFileWriter.write(
       outputsFile(className, outputEvent.getDestination()), outputEvent.getMessage());
 }
 public void afterSuite(TestDescriptor suite, TestResult result) {
   if (suite.getParent() == null) {
     cachingFileWriter.closeAll();
     writeResults();
   }
 }