1 /******************************************************************************* 2 * Copyright (c) 2009, 2021 Mountainminds GmbH & Co. KG and Contributors 3 * This program and the accompanying materials are made available under 4 * the terms of the Eclipse Public License 2.0 which is available at 5 * http://www.eclipse.org/legal/epl-2.0 6 * 7 * SPDX-License-Identifier: EPL-2.0 8 * 9 * Contributors: 10 * Brock Janiczak - initial API and implementation 11 * 12 *******************************************************************************/ 13 package org.jacoco.examples; 14 15 import java.io.File; 16 import java.io.IOException; 17 18 import org.jacoco.core.analysis.Analyzer; 19 import org.jacoco.core.analysis.CoverageBuilder; 20 import org.jacoco.core.analysis.IBundleCoverage; 21 import org.jacoco.core.tools.ExecFileLoader; 22 import org.jacoco.report.DirectorySourceFileLocator; 23 import org.jacoco.report.FileMultiReportOutput; 24 import org.jacoco.report.IReportVisitor; 25 import org.jacoco.report.html.HTMLFormatter; 26 27 /** 28 * This example creates a HTML report for eclipse like projects based on a 29 * single execution data store called jacoco.exec. The report contains no 30 * grouping information. 31 * 32 * The class files under test must be compiled with debug information, otherwise 33 * source highlighting will not work. 34 */ 35 public class ReportGenerator { 36 37 private final String title; 38 39 private final File executionDataFile; 40 private final File classesDirectory; 41 private final File sourceDirectory; 42 private final File reportDirectory; 43 44 private ExecFileLoader execFileLoader; 45 46 /** 47 * Create a new generator based for the given project. 48 * 49 * @param projectDirectory 50 */ ReportGenerator(final File projectDirectory)51 public ReportGenerator(final File projectDirectory) { 52 this.title = projectDirectory.getName(); 53 this.executionDataFile = new File(projectDirectory, "jacoco.exec"); 54 this.classesDirectory = new File(projectDirectory, "bin"); 55 this.sourceDirectory = new File(projectDirectory, "src"); 56 this.reportDirectory = new File(projectDirectory, "coveragereport"); 57 } 58 59 /** 60 * Create the report. 61 * 62 * @throws IOException 63 */ create()64 public void create() throws IOException { 65 66 // Read the jacoco.exec file. Multiple data files could be merged 67 // at this point 68 loadExecutionData(); 69 70 // Run the structure analyzer on a single class folder to build up 71 // the coverage model. The process would be similar if your classes 72 // were in a jar file. Typically you would create a bundle for each 73 // class folder and each jar you want in your report. If you have 74 // more than one bundle you will need to add a grouping node to your 75 // report 76 final IBundleCoverage bundleCoverage = analyzeStructure(); 77 78 createReport(bundleCoverage); 79 80 } 81 createReport(final IBundleCoverage bundleCoverage)82 private void createReport(final IBundleCoverage bundleCoverage) 83 throws IOException { 84 85 // Create a concrete report visitor based on some supplied 86 // configuration. In this case we use the defaults 87 final HTMLFormatter htmlFormatter = new HTMLFormatter(); 88 final IReportVisitor visitor = htmlFormatter 89 .createVisitor(new FileMultiReportOutput(reportDirectory)); 90 91 // Initialize the report with all of the execution and session 92 // information. At this point the report doesn't know about the 93 // structure of the report being created 94 visitor.visitInfo(execFileLoader.getSessionInfoStore().getInfos(), 95 execFileLoader.getExecutionDataStore().getContents()); 96 97 // Populate the report structure with the bundle coverage information. 98 // Call visitGroup if you need groups in your report. 99 visitor.visitBundle(bundleCoverage, 100 new DirectorySourceFileLocator(sourceDirectory, "utf-8", 4)); 101 102 // Signal end of structure information to allow report to write all 103 // information out 104 visitor.visitEnd(); 105 106 } 107 loadExecutionData()108 private void loadExecutionData() throws IOException { 109 execFileLoader = new ExecFileLoader(); 110 execFileLoader.load(executionDataFile); 111 } 112 analyzeStructure()113 private IBundleCoverage analyzeStructure() throws IOException { 114 final CoverageBuilder coverageBuilder = new CoverageBuilder(); 115 final Analyzer analyzer = new Analyzer( 116 execFileLoader.getExecutionDataStore(), coverageBuilder); 117 118 analyzer.analyzeAll(classesDirectory); 119 120 return coverageBuilder.getBundle(title); 121 } 122 123 /** 124 * Starts the report generation process 125 * 126 * @param args 127 * Arguments to the application. This will be the location of the 128 * eclipse projects that will be used to generate reports for 129 * @throws IOException 130 */ main(final String[] args)131 public static void main(final String[] args) throws IOException { 132 for (int i = 0; i < args.length; i++) { 133 final ReportGenerator generator = new ReportGenerator( 134 new File(args[i])); 135 generator.create(); 136 } 137 } 138 139 } 140