]> source.dussan.org Git - sonarqube.git/blob
d0cc62620932ca7a0e7bcddf29e0c35d53e9dea2
[sonarqube.git] /
1 /*
2  * Sonar, open source software quality management tool.
3  * Copyright (C) 2008-2011 SonarSource
4  * mailto:contact AT sonarsource DOT com
5  *
6  * Sonar is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * Sonar is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Sonar; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
19  */
20 package org.sonar.plugins.surefire.api;
21
22 import org.apache.commons.lang.StringUtils;
23 import org.sonar.api.batch.SensorContext;
24 import org.sonar.api.measures.CoreMetrics;
25 import org.sonar.api.measures.Measure;
26 import org.sonar.api.measures.Metric;
27 import org.sonar.api.resources.Project;
28 import org.sonar.api.resources.Resource;
29 import org.sonar.api.utils.ParsingUtils;
30 import org.sonar.api.utils.SonarException;
31 import org.sonar.api.utils.StaxParser;
32 import org.sonar.plugins.surefire.data.SurefireStaxHandler;
33 import org.sonar.plugins.surefire.data.UnitTestClassReport;
34 import org.sonar.plugins.surefire.data.UnitTestIndex;
35
36 import java.io.File;
37 import java.io.FilenameFilter;
38 import java.util.Map;
39
40 import javax.xml.stream.XMLStreamException;
41
42 /**
43  * @since 2.4
44  */
45 public abstract class AbstractSurefireParser {
46
47   public void collect(Project project, SensorContext context, File reportsDir) {
48     File[] xmlFiles = getReports(reportsDir);
49
50     if (xmlFiles.length != 0) {
51       parseFiles(context, xmlFiles);
52     }
53   }
54
55   private File[] getReports(File dir) {
56     if (dir == null || !dir.isDirectory() || !dir.exists()) {
57       return new File[0];
58     }
59     return dir.listFiles(new FilenameFilter() {
60       public boolean accept(File dir, String name) {
61         return name.startsWith("TEST") && name.endsWith(".xml");
62       }
63     });
64   }
65
66   private void parseFiles(SensorContext context, File[] reports) {
67     UnitTestIndex index = new UnitTestIndex();
68     parseFiles(reports, index);
69     sanitize(index);
70     save(index, context);
71   }
72
73   private void parseFiles(File[] reports, UnitTestIndex index) {
74     SurefireStaxHandler staxParser = new SurefireStaxHandler(index);
75     StaxParser parser = new StaxParser(staxParser, false);
76     for (File report : reports) {
77       try {
78         parser.parse(report);
79       } catch (XMLStreamException e) {
80         throw new SonarException("Fail to parse the Surefire report: " + report, e);
81       }
82     }
83   }
84
85   private void sanitize(UnitTestIndex index) {
86     for (String classname : index.getClassnames()) {
87       if (StringUtils.contains(classname, "$")) {
88         // Surefire reports classes whereas sonar supports files
89         String parentClassName = StringUtils.substringBeforeLast(classname, "$");
90         index.merge(classname, parentClassName);
91       }
92     }
93   }
94
95   private void save(UnitTestIndex index, SensorContext context) {
96     for (Map.Entry<String, UnitTestClassReport> entry : index.getIndexByClassname().entrySet()) {
97       UnitTestClassReport report = entry.getValue();
98       if (report.getTests() > 0) {
99         Resource resource = getUnitTestResource(entry.getKey());
100         double testsCount = report.getTests() - report.getSkipped();
101         saveMeasure(context, resource, CoreMetrics.SKIPPED_TESTS, report.getSkipped());
102         saveMeasure(context, resource, CoreMetrics.TESTS, testsCount);
103         saveMeasure(context, resource, CoreMetrics.TEST_ERRORS, report.getErrors());
104         saveMeasure(context, resource, CoreMetrics.TEST_FAILURES, report.getFailures());
105         saveMeasure(context, resource, CoreMetrics.TEST_EXECUTION_TIME, report.getDurationMilliseconds());
106         double passedTests = testsCount - report.getErrors() - report.getFailures();
107         if (testsCount > 0) {
108           double percentage = passedTests * 100d / testsCount;
109           saveMeasure(context, resource, CoreMetrics.TEST_SUCCESS_DENSITY, ParsingUtils.scaleValue(percentage));
110         }
111         saveResults(context, resource, report);
112       }
113     }
114   }
115
116   private void saveMeasure(SensorContext context, Resource resource, Metric metric, double value) {
117     if (!Double.isNaN(value)) {
118       context.saveMeasure(resource, metric, value);
119     }
120   }
121
122   private void saveResults(SensorContext context, Resource resource, UnitTestClassReport report) {
123     context.saveMeasure(resource, new Measure(CoreMetrics.TEST_DATA, report.toXml()));
124   }
125
126   protected abstract Resource<?> getUnitTestResource(String classKey);
127
128 }