aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-batch
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2014-08-29 15:22:50 +0200
committerJulien HENRY <julien.henry@sonarsource.com>2014-08-29 15:22:50 +0200
commit1471a387b3e4af4543a1eef6ecff4510eea9ccb7 (patch)
treefbefa5171d245d8609af3966fe8584f80a7093df /sonar-batch
parent1f7126fddca31c7a80fe51a3eb4d77e983059fcb (diff)
downloadsonarqube-1471a387b3e4af4543a1eef6ecff4510eea9ccb7.tar.gz
sonarqube-1471a387b3e4af4543a1eef6ecff4510eea9ccb7.zip
Add details of persisters in profiling output to ease understanding
Diffstat (limited to 'sonar-batch')
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/PersisterExecutionEvent.java50
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/PersistersPhaseEvent.java51
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/Phases.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/event/PersisterExecutionHandler.java45
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/event/PersistersPhaseHandler.java50
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/event/package-info.java23
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java33
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java66
9 files changed, 321 insertions, 6 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/PersisterExecutionEvent.java b/sonar-batch/src/main/java/org/sonar/batch/phases/PersisterExecutionEvent.java
new file mode 100644
index 00000000000..cb6574591c7
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/PersisterExecutionEvent.java
@@ -0,0 +1,50 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.phases;
+
+import org.sonar.batch.index.ScanPersister;
+import org.sonar.batch.phases.event.PersisterExecutionHandler;
+
+class PersisterExecutionEvent extends AbstractPhaseEvent<PersisterExecutionHandler>
+ implements PersisterExecutionHandler.PersisterExecutionEvent {
+
+ private final ScanPersister persister;
+
+ PersisterExecutionEvent(ScanPersister persister, boolean start) {
+ super(start);
+ this.persister = persister;
+ }
+
+ @Override
+ public ScanPersister getPersister() {
+ return persister;
+ }
+
+ @Override
+ public void dispatch(PersisterExecutionHandler handler) {
+ handler.onPersisterExecution(this);
+ }
+
+ @Override
+ public Class getType() {
+ return PersisterExecutionHandler.class;
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/PersistersPhaseEvent.java b/sonar-batch/src/main/java/org/sonar/batch/phases/PersistersPhaseEvent.java
new file mode 100644
index 00000000000..c2074effcda
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/PersistersPhaseEvent.java
@@ -0,0 +1,51 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.phases;
+
+import org.sonar.batch.index.ScanPersister;
+import org.sonar.batch.phases.event.PersistersPhaseHandler;
+
+import java.util.List;
+
+class PersistersPhaseEvent extends AbstractPhaseEvent<PersistersPhaseHandler>
+ implements PersistersPhaseHandler.PersistersPhaseEvent {
+
+ private final List<ScanPersister> persisters;
+
+ PersistersPhaseEvent(List<ScanPersister> persisters, boolean start) {
+ super(start);
+ this.persisters = persisters;
+ }
+
+ public List<ScanPersister> getPersisters() {
+ return persisters;
+ }
+
+ @Override
+ protected void dispatch(PersistersPhaseHandler handler) {
+ handler.onPersistersPhase(this);
+ }
+
+ @Override
+ protected Class getType() {
+ return PersistersPhaseHandler.class;
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java
index 5fc37a64dfd..c08312ce36c 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java
@@ -138,14 +138,15 @@ public final class PhaseExecutor {
private void executePersisters() {
LOGGER.info("Store results in database");
- String persistersStep = "Persisters";
- eventBus.fireEvent(new BatchStepEvent(persistersStep, true));
+ eventBus.fireEvent(new PersistersPhaseEvent(Lists.newArrayList(persisters), true));
for (ScanPersister persister : persisters) {
LOGGER.debug("Execute {}", persister.getClass().getName());
+ eventBus.fireEvent(new PersisterExecutionEvent(persister, true));
persister.persist();
+ eventBus.fireEvent(new PersisterExecutionEvent(persister, false));
}
- eventBus.fireEvent(new BatchStepEvent(persistersStep, false));
+ eventBus.fireEvent(new PersistersPhaseEvent(Lists.newArrayList(persisters), false));
}
private void updateStatusJob() {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/Phases.java b/sonar-batch/src/main/java/org/sonar/batch/phases/Phases.java
index 44b817907af..4ce24c70a6b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/Phases.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/Phases.java
@@ -27,7 +27,7 @@ import java.util.Set;
public class Phases {
public static enum Phase {
- MAVEN("Maven"), INIT("Initializers"), SENSOR("Sensors"), DECORATOR("Decorators"), POSTJOB("Post-Jobs");
+ MAVEN("Maven"), INIT("Initializers"), SENSOR("Sensors"), DECORATOR("Decorators"), PERSISTER("Persisters"), POSTJOB("Post-Jobs");
private final String label;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/event/PersisterExecutionHandler.java b/sonar-batch/src/main/java/org/sonar/batch/phases/event/PersisterExecutionHandler.java
new file mode 100644
index 00000000000..7df8dae4ade
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/event/PersisterExecutionHandler.java
@@ -0,0 +1,45 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.phases.event;
+
+import org.sonar.api.batch.events.EventHandler;
+import org.sonar.batch.index.ScanPersister;
+
+public interface PersisterExecutionHandler extends EventHandler {
+
+ /**
+ * This interface is not intended to be implemented by clients.
+ */
+ interface PersisterExecutionEvent {
+
+ ScanPersister getPersister();
+
+ boolean isStart();
+
+ boolean isEnd();
+
+ }
+
+ /**
+ * Called before and after execution of {@link ScanPersister}.
+ */
+ void onPersisterExecution(PersisterExecutionEvent event);
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/event/PersistersPhaseHandler.java b/sonar-batch/src/main/java/org/sonar/batch/phases/event/PersistersPhaseHandler.java
new file mode 100644
index 00000000000..087755bacab
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/event/PersistersPhaseHandler.java
@@ -0,0 +1,50 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.phases.event;
+
+import org.sonar.api.batch.events.EventHandler;
+import org.sonar.batch.index.ScanPersister;
+
+import java.util.List;
+
+public interface PersistersPhaseHandler extends EventHandler {
+
+ /**
+ * This interface is not intended to be implemented by clients.
+ */
+ interface PersistersPhaseEvent {
+
+ /**
+ * @return list of Persisters in the order of execution
+ */
+ List<ScanPersister> getPersisters();
+
+ boolean isStart();
+
+ boolean isEnd();
+
+ }
+
+ /**
+ * Called before and after execution of all {@link ScanPersister}s.
+ */
+ void onPersistersPhase(PersistersPhaseEvent event);
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/event/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/phases/event/package-info.java
new file mode 100644
index 00000000000..6aefbe5b6bb
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/event/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.batch.phases.event;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java b/sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java
index c2eec6f34a5..42d61fb4f64 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java
@@ -25,12 +25,23 @@ import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.Decorator;
-import org.sonar.api.batch.events.*;
+import org.sonar.api.batch.events.DecoratorExecutionHandler;
+import org.sonar.api.batch.events.DecoratorsPhaseHandler;
+import org.sonar.api.batch.events.InitializerExecutionHandler;
+import org.sonar.api.batch.events.InitializersPhaseHandler;
+import org.sonar.api.batch.events.MavenPhaseHandler;
+import org.sonar.api.batch.events.PostJobExecutionHandler;
+import org.sonar.api.batch.events.PostJobsPhaseHandler;
+import org.sonar.api.batch.events.ProjectAnalysisHandler;
+import org.sonar.api.batch.events.SensorExecutionHandler;
+import org.sonar.api.batch.events.SensorsPhaseHandler;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.TimeUtils;
import org.sonar.batch.events.BatchStepHandler;
import org.sonar.batch.phases.Phases;
+import org.sonar.batch.phases.event.PersisterExecutionHandler;
+import org.sonar.batch.phases.event.PersistersPhaseHandler;
import javax.annotation.Nullable;
@@ -43,7 +54,8 @@ import static org.sonar.batch.profiling.AbstractTimeProfiling.sortByDescendingTo
import static org.sonar.batch.profiling.AbstractTimeProfiling.truncate;
public class PhasesSumUpTimeProfiler implements ProjectAnalysisHandler, SensorExecutionHandler, DecoratorExecutionHandler, PostJobExecutionHandler, DecoratorsPhaseHandler,
- SensorsPhaseHandler, PostJobsPhaseHandler, MavenPhaseHandler, InitializersPhaseHandler, InitializerExecutionHandler, BatchStepHandler {
+ SensorsPhaseHandler, PostJobsPhaseHandler, MavenPhaseHandler, InitializersPhaseHandler, InitializerExecutionHandler, BatchStepHandler, PersistersPhaseHandler,
+ PersisterExecutionHandler {
static final Logger LOG = LoggerFactory.getLogger(PhasesSumUpTimeProfiler.class);
private static final int TEXT_RIGHT_PAD = 60;
@@ -137,6 +149,23 @@ public class PhasesSumUpTimeProfiler implements ProjectAnalysisHandler, SensorEx
}
}
+ public void onPersistersPhase(PersistersPhaseEvent event) {
+ if (event.isStart()) {
+ currentModuleProfiling.addPhaseProfiling(Phases.Phase.PERSISTER);
+ } else {
+ currentModuleProfiling.getProfilingPerPhase(Phases.Phase.PERSISTER).stop();
+ }
+ }
+
+ public void onPersisterExecution(PersisterExecutionEvent event) {
+ PhaseProfiling profiling = currentModuleProfiling.getProfilingPerPhase(Phases.Phase.PERSISTER);
+ if (event.isStart()) {
+ profiling.newItemProfiling(event.getPersister());
+ } else {
+ profiling.getProfilingPerItem(event.getPersister()).stop();
+ }
+ }
+
public void onDecoratorExecution(DecoratorExecutionEvent event) {
PhaseProfiling profiling = currentModuleProfiling.getProfilingPerPhase(Phases.Phase.DECORATOR);
if (event.isStart()) {
diff --git a/sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java b/sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java
index bb8096f8a83..ad19f8fd1c9 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java
@@ -44,7 +44,10 @@ import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.utils.System2;
import org.sonar.batch.events.BatchStepEvent;
+import org.sonar.batch.index.ScanPersister;
import org.sonar.batch.phases.Phases.Phase;
+import org.sonar.batch.phases.event.PersisterExecutionHandler;
+import org.sonar.batch.phases.event.PersistersPhaseHandler;
import java.util.Arrays;
import java.util.Collections;
@@ -77,6 +80,7 @@ public class PhasesSumUpTimeProfilerTest {
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.INIT).getProfilingPerItem(new FakeInitializer()).totalTime()).isEqualTo(7L);
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.SENSOR).getProfilingPerItem(new FakeSensor()).totalTime()).isEqualTo(10L);
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator1()).totalTime()).isEqualTo(20L);
+ assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.PERSISTER).getProfilingPerItem(new FakeScanPersister()).totalTime()).isEqualTo(40L);
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.POSTJOB).getProfilingPerItem(new FakePostJob()).totalTime()).isEqualTo(30L);
assertThat(profiler.currentModuleProfiling.getProfilingPerBatchStep("Free memory").totalTime()).isEqualTo(9L);
@@ -98,6 +102,7 @@ public class PhasesSumUpTimeProfilerTest {
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.SENSOR).getProfilingPerItem(new FakeSensor()).totalTime()).isEqualTo(10L);
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator1()).totalTime()).isEqualTo(20L);
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator2()).totalTime()).isEqualTo(10L);
+ assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.PERSISTER).getProfilingPerItem(new FakeScanPersister()).totalTime()).isEqualTo(40L);
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.POSTJOB).getProfilingPerItem(new FakePostJob()).totalTime()).isEqualTo(30L);
assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.MAVEN).totalTime()).isEqualTo(12L);
@@ -105,6 +110,7 @@ public class PhasesSumUpTimeProfilerTest {
assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.SENSOR).getProfilingPerItem(new FakeSensor()).totalTime()).isEqualTo(30L);
assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator1()).totalTime()).isEqualTo(60L);
assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator2()).totalTime()).isEqualTo(30L);
+ assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.PERSISTER).getProfilingPerItem(new FakeScanPersister()).totalTime()).isEqualTo(120L);
assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.POSTJOB).getProfilingPerItem(new FakePostJob()).totalTime()).isEqualTo(90L);
}
@@ -153,6 +159,7 @@ public class PhasesSumUpTimeProfilerTest {
initializerPhase(profiler);
sensorPhase(profiler);
decoratorPhase(profiler);
+ persistersPhase(profiler);
postJobPhase(profiler);
batchStep(profiler);
// End of moduleA
@@ -230,6 +237,19 @@ public class PhasesSumUpTimeProfilerTest {
profiler.onSensorsPhase(sensorsEvent(false));
}
+ private void persistersPhase(PhasesSumUpTimeProfiler profiler) throws InterruptedException {
+ ScanPersister persister = new FakeScanPersister();
+ // Start of persister phase
+ profiler.onPersistersPhase(persistersEvent(true));
+ // Start of a ScanPersister
+ profiler.onPersisterExecution(persisterEvent(persister, true));
+ clock.sleep(40);
+ // End of a ScanPersister
+ profiler.onPersisterExecution(persisterEvent(persister, false));
+ // End of persister phase
+ profiler.onPersistersPhase(persistersEvent(false));
+ }
+
private void postJobPhase(PhasesSumUpTimeProfiler profiler) throws InterruptedException {
PostJob postJob = new FakePostJob();
// Start of sensor phase
@@ -323,6 +343,26 @@ public class PhasesSumUpTimeProfilerTest {
};
}
+ private PersisterExecutionHandler.PersisterExecutionEvent persisterEvent(final ScanPersister persister, final boolean start) {
+ return new PersisterExecutionHandler.PersisterExecutionEvent() {
+
+ @Override
+ public boolean isStart() {
+ return start;
+ }
+
+ @Override
+ public boolean isEnd() {
+ return !start;
+ }
+
+ @Override
+ public ScanPersister getPersister() {
+ return persister;
+ }
+ };
+ }
+
private SensorsPhaseEvent sensorsEvent(final boolean start) {
return new SensorsPhaseHandler.SensorsPhaseEvent() {
@@ -398,6 +438,26 @@ public class PhasesSumUpTimeProfilerTest {
};
}
+ private PersistersPhaseHandler.PersistersPhaseEvent persistersEvent(final boolean start) {
+ return new PersistersPhaseHandler.PersistersPhaseEvent() {
+
+ @Override
+ public boolean isStart() {
+ return start;
+ }
+
+ @Override
+ public boolean isEnd() {
+ return !start;
+ }
+
+ @Override
+ public List<ScanPersister> getPersisters() {
+ return null;
+ }
+ };
+ }
+
private DecoratorsPhaseHandler.DecoratorsPhaseEvent decoratorsEvent(final boolean start) {
return new DecoratorsPhaseHandler.DecoratorsPhaseEvent() {
@@ -486,4 +546,10 @@ public class PhasesSumUpTimeProfilerTest {
public void executeOn(Project project, SensorContext context) {
}
}
+
+ public class FakeScanPersister implements ScanPersister {
+ @Override
+ public void persist() {
+ }
+ }
}