Skip to content

Commit e0de0ef

Browse files
pynicolasalban-auzeill
authored andcommitted
SONARPY-235 PythonXUnitSensor: use new sensor API
1 parent 4d72c3c commit e0de0ef

4 files changed

Lines changed: 90 additions & 76 deletions

File tree

sonar-python-plugin/src/main/java/org/sonar/plugins/python/PythonReportSensor.java

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,37 +24,35 @@
2424
import java.util.Objects;
2525
import org.slf4j.Logger;
2626
import org.slf4j.LoggerFactory;
27-
import org.sonar.api.batch.Sensor;
28-
import org.sonar.api.batch.SensorContext;
29-
import org.sonar.api.batch.fs.FilePredicates;
30-
import org.sonar.api.batch.fs.FileSystem;
27+
import org.sonar.api.batch.sensor.Sensor;
28+
import org.sonar.api.batch.sensor.SensorContext;
3129
import org.sonar.api.batch.fs.InputFile;
30+
import org.sonar.api.batch.sensor.SensorDescriptor;
3231
import org.sonar.api.config.Settings;
33-
import org.sonar.api.resources.Project;
3432
import org.sonar.api.utils.WildcardPattern;
3533

3634
public abstract class PythonReportSensor implements Sensor {
3735

3836
private static final Logger LOG = LoggerFactory.getLogger(PythonReportSensor.class);
3937

40-
protected Settings conf = null;
41-
protected FileSystem fileSystem;
38+
protected Settings conf;
4239

43-
public PythonReportSensor(Settings conf, FileSystem fileSystem) {
40+
public PythonReportSensor(Settings conf) {
4441
this.conf = conf;
45-
this.fileSystem = fileSystem;
4642
}
4743

4844
@Override
49-
public boolean shouldExecuteOnProject(Project project) {
50-
FilePredicates p = fileSystem.predicates();
51-
return fileSystem.hasFiles(p.and(p.hasType(InputFile.Type.MAIN), p.hasLanguage(Python.KEY)));
45+
public void describe(SensorDescriptor descriptor) {
46+
descriptor
47+
.name(getClass().getSimpleName())
48+
.onlyOnLanguage(Python.KEY)
49+
.onlyOnFileType(InputFile.Type.MAIN);
5250
}
5351

5452
@Override
55-
public void analyse(Project project, SensorContext context) {
53+
public void execute(SensorContext context) {
5654
try {
57-
List<File> reports = getReports(conf, fileSystem.baseDir().getPath(), reportPathKey(), defaultReportPath());
55+
List<File> reports = getReports(conf, context.fileSystem().baseDir().getPath(), reportPathKey(), defaultReportPath());
5856
processReports(context, reports);
5957
} catch (javax.xml.stream.XMLStreamException e) {
6058
String msg = new StringBuilder()
@@ -66,11 +64,6 @@ public void analyse(Project project, SensorContext context) {
6664
}
6765
}
6866

69-
@Override
70-
public String toString() {
71-
return getClass().getSimpleName();
72-
}
73-
7467
public static List<File> getReports(Settings conf, String baseDirPath, String reportPathPropertyKey, String defaultReportPath) {
7568
String reportPath = conf.getString(reportPathPropertyKey);
7669
boolean propertyIsProvided = !Objects.equals(reportPath, defaultReportPath);

sonar-python-plugin/src/main/java/org/sonar/plugins/python/xunit/PythonXUnitSensor.java

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
import org.apache.commons.lang.StringUtils;
3131
import org.slf4j.Logger;
3232
import org.slf4j.LoggerFactory;
33-
import org.sonar.api.batch.SensorContext;
33+
import org.sonar.api.batch.fs.InputComponent;
34+
import org.sonar.api.batch.measure.Metric;
35+
import org.sonar.api.batch.sensor.SensorContext;
3436
import org.sonar.api.batch.fs.FileSystem;
3537
import org.sonar.api.batch.fs.InputFile;
3638
import org.sonar.api.config.Settings;
@@ -45,8 +47,11 @@ public class PythonXUnitSensor extends PythonReportSensor {
4547
public static final String DEFAULT_REPORT_PATH = "xunit-reports/xunit-result-*.xml";
4648
public static final String SKIP_DETAILS = "sonar.python.xunit.skipDetails";
4749

50+
private final FileSystem fileSystem;
51+
4852
public PythonXUnitSensor(Settings conf, FileSystem fileSystem) {
49-
super(conf, fileSystem);
53+
super(conf);
54+
this.fileSystem = fileSystem;
5055
}
5156

5257
@Override
@@ -75,11 +80,11 @@ private static void simpleMode(final SensorContext context, List<File> reports)
7580
parser.parse(report);
7681
}
7782

78-
double testsCount = 0.0;
79-
double testsSkipped = 0.0;
80-
double testsErrors = 0.0;
81-
double testsFailures = 0.0;
82-
double testsTime = 0.0;
83+
int testsCount = 0;
84+
int testsSkipped = 0;
85+
int testsErrors = 0;
86+
int testsFailures = 0;
87+
long testsTime = 0;
8388
for (TestSuite report : parserHandler.getParsedReports()) {
8489
testsCount += report.getTests() - report.getSkipped();
8590
testsSkipped += report.getSkipped();
@@ -89,11 +94,12 @@ private static void simpleMode(final SensorContext context, List<File> reports)
8994
}
9095

9196
if (testsCount > 0) {
92-
context.saveMeasure(CoreMetrics.TESTS, testsCount);
93-
context.saveMeasure(CoreMetrics.SKIPPED_TESTS, testsSkipped);
94-
context.saveMeasure(CoreMetrics.TEST_ERRORS, testsErrors);
95-
context.saveMeasure(CoreMetrics.TEST_FAILURES, testsFailures);
96-
context.saveMeasure(CoreMetrics.TEST_EXECUTION_TIME, testsTime);
97+
InputComponent module = context.module();
98+
saveMeasure(context, module, CoreMetrics.TESTS, testsCount);
99+
saveMeasure(context, module, CoreMetrics.SKIPPED_TESTS, testsSkipped);
100+
saveMeasure(context, module, CoreMetrics.TEST_ERRORS, testsErrors);
101+
saveMeasure(context, module, CoreMetrics.TEST_FAILURES, testsFailures);
102+
saveMeasure(context, module, CoreMetrics.TEST_EXECUTION_TIME, testsTime);
97103
}
98104
}
99105

@@ -118,11 +124,11 @@ private void processReportDetailed(SensorContext context, Collection<TestSuite>
118124
LOG.debug("Saving test execution measures for '{}' under resource '{}'", fileReport.getKey(), inputFile.relativePath());
119125
}
120126

121-
context.saveMeasure(inputFile, CoreMetrics.SKIPPED_TESTS, (double) fileReport.getSkipped());
122-
context.saveMeasure(inputFile, CoreMetrics.TESTS, (double) fileReport.getTests() - fileReport.getSkipped());
123-
context.saveMeasure(inputFile, CoreMetrics.TEST_ERRORS, (double) fileReport.getErrors());
124-
context.saveMeasure(inputFile, CoreMetrics.TEST_FAILURES, (double) fileReport.getFailures());
125-
context.saveMeasure(inputFile, CoreMetrics.TEST_EXECUTION_TIME, (double) fileReport.getTime());
127+
saveMeasure(context, inputFile, CoreMetrics.SKIPPED_TESTS, fileReport.getSkipped());
128+
saveMeasure(context, inputFile, CoreMetrics.TESTS, fileReport.getTests() - fileReport.getSkipped());
129+
saveMeasure(context, inputFile, CoreMetrics.TEST_ERRORS, fileReport.getErrors());
130+
saveMeasure(context, inputFile, CoreMetrics.TEST_FAILURES, fileReport.getFailures());
131+
saveMeasure(context, inputFile, CoreMetrics.TEST_EXECUTION_TIME, fileReport.getTime());
126132
}
127133
}
128134

@@ -177,4 +183,21 @@ private InputFile getSonarTestFile(File file) {
177183
LOG.debug("Using the key '{}' to lookup the resource in SonarQube", file.getPath());
178184
return fileSystem.inputFile(fileSystem.predicates().is(file));
179185
}
186+
187+
private static void saveMeasure(SensorContext context, InputComponent component, Metric<Integer> metric, int value) {
188+
context.<Integer>newMeasure()
189+
.on(component)
190+
.forMetric(metric)
191+
.withValue(value)
192+
.save();
193+
}
194+
195+
private static void saveMeasure(SensorContext context, InputComponent component, Metric<Long> metric, long value) {
196+
context.<Long>newMeasure()
197+
.on(component)
198+
.forMetric(metric)
199+
.withValue(value)
200+
.save();
201+
}
202+
180203
}

sonar-python-plugin/src/test/java/org/sonar/plugins/python/xunit/PythonXUnitSensorTest.java

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,33 +22,33 @@
2222
import java.io.File;
2323
import org.junit.Before;
2424
import org.junit.Test;
25-
import org.sonar.api.batch.SensorContext;
25+
import org.sonar.api.batch.fs.InputComponent;
2626
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
2727
import org.sonar.api.batch.fs.internal.DefaultInputFile;
28+
import org.sonar.api.batch.sensor.internal.SensorContextTester;
2829
import org.sonar.api.config.MapSettings;
2930
import org.sonar.api.config.Settings;
3031
import org.sonar.api.measures.CoreMetrics;
31-
import org.sonar.api.resources.Project;
32+
import org.sonar.api.measures.Metric;
3233

33-
import static org.mockito.Matchers.anyDouble;
3434
import static org.mockito.Matchers.eq;
3535
import static org.mockito.Mockito.mock;
3636
import static org.mockito.Mockito.verify;
3737
import static org.mockito.Mockito.verifyNoMoreInteractions;
38+
import static org.assertj.core.api.Assertions.assertThat;
3839

3940
public class PythonXUnitSensorTest {
41+
42+
private File baseDir = new File("src/test/resources/org/sonar/plugins/python");
4043
Settings settings;
4144
PythonXUnitSensor sensor;
42-
SensorContext context;
43-
Project project;
45+
SensorContextTester context = SensorContextTester.create(baseDir);
4446
DefaultFileSystem fs;
4547

4648
@Before
4749
public void setUp() {
4850
settings = new MapSettings();
49-
project = mock(Project.class);
50-
fs = new DefaultFileSystem(new File("src/test/resources/org/sonar/plugins/python"));
51-
context = mock(SensorContext.class);
51+
fs = new DefaultFileSystem(baseDir);
5252
sensor = new PythonXUnitSensor(settings, fs);
5353
}
5454

@@ -58,55 +58,61 @@ public void shouldSaveCorrectMeasures() {
5858
DefaultInputFile testFile2 = new DefaultInputFile("", "tests/dir/test_sample2.py");
5959
fs.add(testFile1);
6060
fs.add(testFile2);
61-
sensor.analyse(project, context);
61+
sensor.execute(context);
6262

63-
verify(context).saveMeasure(testFile1, CoreMetrics.TESTS, 3.);
64-
verify(context).saveMeasure(testFile2, CoreMetrics.TESTS, 3.);
65-
verify(context).saveMeasure(testFile1, CoreMetrics.TESTS, 0.);
63+
assertThat(measure(testFile1, CoreMetrics.TESTS)).isEqualTo(3);
64+
assertThat(measure(testFile2, CoreMetrics.TESTS)).isEqualTo(3);
6665

67-
verify(context).saveMeasure(testFile1, CoreMetrics.SKIPPED_TESTS, 0.);
68-
verify(context).saveMeasure(testFile2, CoreMetrics.SKIPPED_TESTS, 1.);
69-
verify(context).saveMeasure(testFile1, CoreMetrics.SKIPPED_TESTS, 1.);
66+
assertThat(measure(testFile1, CoreMetrics.SKIPPED_TESTS)).isEqualTo(0);
67+
assertThat(measure(testFile2, CoreMetrics.SKIPPED_TESTS)).isEqualTo(1);
7068

71-
verify(context).saveMeasure(testFile1, CoreMetrics.TEST_ERRORS, 1.);
72-
verify(context).saveMeasure(testFile2, CoreMetrics.TEST_ERRORS, 1.);
73-
verify(context).saveMeasure(testFile1, CoreMetrics.TEST_ERRORS, 0.);
69+
assertThat(measure(testFile1, CoreMetrics.TEST_ERRORS)).isEqualTo(1);
70+
assertThat(measure(testFile2, CoreMetrics.TEST_ERRORS)).isEqualTo(1);
7471

75-
verify(context).saveMeasure(testFile1, CoreMetrics.TEST_FAILURES, 1.);
76-
verify(context).saveMeasure(testFile2, CoreMetrics.TEST_FAILURES, 1.);
77-
verify(context).saveMeasure(testFile1, CoreMetrics.TEST_FAILURES, 0.);
72+
assertThat(measure(testFile1, CoreMetrics.TEST_FAILURES)).isEqualTo(1);
73+
assertThat(measure(testFile2, CoreMetrics.TEST_FAILURES)).isEqualTo(1);
7874
}
7975

8076
@Test
8177
public void shouldSaveCorrectMeasuresSimpleMode() {
8278
settings.setProperty(PythonXUnitSensor.SKIP_DETAILS, true);
8379
fs.add(new DefaultInputFile("", "test_sample.py"));
8480
fs.add(new DefaultInputFile("", "tests/dir/test_sample.py"));
85-
sensor.analyse(project, context);
81+
sensor.execute(context);
8682

8783
// includes test with not found file
88-
verify(context).saveMeasure(CoreMetrics.TESTS, 7.);
89-
verify(context).saveMeasure(CoreMetrics.SKIPPED_TESTS, 2.);
90-
// includes test with not found file
91-
verify(context).saveMeasure(CoreMetrics.TEST_ERRORS, 3.);
92-
verify(context).saveMeasure(CoreMetrics.TEST_FAILURES, 2.);
93-
verify(context).saveMeasure(eq(CoreMetrics.TEST_EXECUTION_TIME), anyDouble());
94-
verifyNoMoreInteractions(context);
84+
assertThat(moduleMeasure(CoreMetrics.TESTS)).isEqualTo(7);
85+
assertThat(moduleMeasure(CoreMetrics.SKIPPED_TESTS)).isEqualTo(1);
86+
assertThat(moduleMeasure(CoreMetrics.TEST_ERRORS)).isEqualTo(3);
87+
assertThat(moduleMeasure(CoreMetrics.TEST_FAILURES)).isEqualTo(2);
9588
}
9689

9790
@Test
9891
public void shouldReportNothingWhenNoReportFound() {
92+
DefaultInputFile testFile1 = new DefaultInputFile("", "test_sample1.py");
93+
fs.add(testFile1);
94+
9995
settings.setProperty(PythonXUnitSensor.REPORT_PATH_KEY, "notexistingpath");
10096
sensor = new PythonXUnitSensor(settings, fs);
101-
sensor.analyse(project, context);
97+
sensor.execute(context);
10298

103-
verifyNoMoreInteractions(context);
99+
assertThat(context.measures(context.module().key())).isEmpty();
100+
assertThat(context.measures(testFile1.key())).isEmpty();
104101
}
105102

106103
@Test(expected = IllegalStateException.class)
107104
public void shouldThrowWhenGivenInvalidTime() {
108105
settings.setProperty(PythonXUnitSensor.REPORT_PATH_KEY, "xunit-reports/invalid-time-xunit-report.xml");
109106
sensor = new PythonXUnitSensor(settings, fs);
110-
sensor.analyse(project, context);
107+
sensor.execute(context);
111108
}
109+
110+
private Integer moduleMeasure(Metric<Integer> metric) {
111+
return measure(context.module(), metric);
112+
}
113+
114+
private Integer measure(InputComponent component, Metric<Integer> metric) {
115+
return context.measure(component.key(), metric).value();
116+
}
117+
112118
}

sonar-python-plugin/src/test/resources/org/sonar/plugins/python/xunit-reports/xunit-result-skipped.xml

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)