Skip to content

Commit

Permalink
Merge pull request #374 from camunda-community-hub/feat/#276_sonarqub…
Browse files Browse the repository at this point in the history
…e_plugin

Feat/#276 sonarqube plugin
  • Loading branch information
rohwerj committed Sep 26, 2023
2 parents 5834ded + 05d37b7 commit 358b53b
Show file tree
Hide file tree
Showing 50 changed files with 11,024 additions and 31 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,4 @@ jobs:
run: ./mvnw enforcer:enforce -f regression-tests -Drules=requireProfileIdsExist "-Pcamunda-bpm-engine-${{ matrix.camunda-version }}"

- name: Build with Maven
run: ./mvnw clean verify -U -B -T4 "-Pregression-test" "-Pcamunda-bpm-engine-${{ matrix.camunda-version }}" -DskipExamples
run: ./mvnw clean verify -U -B -T4 "-Pregression-test" "-Pcamunda-bpm-engine-${{ matrix.camunda-version }}" -DskipExamples -DskipPlugins
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ build/
.settings/
# GitHub Pages

node/
node_modules/
24 changes: 23 additions & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,4 +237,26 @@ buildscript {
apply(plugin = "org.camunda.community.process_test_coverage.report-aggregator")
```
Afterwards the reports can be aggregated by calling `gradle aggregateProcessTestCoverage`.
Afterwards the reports can be aggregated by calling `gradle aggregateProcessTestCoverage`.
## Sonarqube plugin
We also provide a plugin for displaying process test coverage in Sonarqube.
This functionality is provided by the artifact:
```xml
<dependency>
<groupId>org.camunda.community.process_test_coverage</groupId>
<artifactId>sonar-camunda-process-test-coverage-plugin</artifactId>
<version>${camunda-process-test-coverage.version}</version>
</dependency>
```
To install this plugin into Sonarqube please have a look at:
https://docs.sonarsource.com/sonarqube/latest/setup-and-upgrade/install-a-plugin/
Currently we don't provide the plugin via the marketplace, so it has to be manually installed.

To get the measures into Sonarqube, you have to include the BPMN files into the sonar input sources.
E.g. by calling mvn sonar:sonar -Dsonar.sources=src/main or otherwise including the BPMN files by pattern.
Afterwards you'll have a process test coverage measurement on project level and for all BPMN files in your sources.
Also the report HTML is included as a page on project level.
18 changes: 18 additions & 0 deletions examples/spring-test-platform-7/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,22 @@
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.camunda.community.process_test_coverage</groupId>
<artifactId>camunda-process-test-coverage-report-aggregator-maven-plugin</artifactId>
<executions>
<execution>
<id>aggregate-reports</id>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,14 @@ object CoverageStateJsonExporter {
fun readCoverageStateResult(json: String): CoverageStateResult =
Gson().fromJson(json, CoverageStateResult::class.java)

@JvmStatic
fun combineCoverageStateResults(json1: String, json2: String): String {
val result1 = readCoverageStateResult(json1)
val result2 = readCoverageStateResult(json2)
return createCoverageStateResult(
result1.suites + result2.suites,
result1.models.plus(result2.models.filter { new -> !result1.models.map { model -> model.key }.contains(new.key) })
)
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package org.camunda.community.process_test_coverage.core.export

import org.camunda.community.process_test_coverage.core.model.Coverage
import org.camunda.community.process_test_coverage.core.model.Event
import org.camunda.community.process_test_coverage.core.model.Model
import org.camunda.community.process_test_coverage.core.model.Suite

data class CoverageStateResult(
val suites: Collection<Suite>,
val models: Collection<Model>
)
) : Coverage {
override fun getEvents() = suites.map { it.getEvents() }.flatten()

override fun getEvents(modelKey: String) = suites.map { it.getEvents(modelKey) }.flatten()

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package org.camunda.community.process_test_coverage.core.model
*
* @author dominikhorn
*/
class Model(
data class Model(

/**
* Key of the model.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package org.camunda.community.process_test_coverage.core.model
*
* @author dominikhorn
*/
class Run(
data class Run(
/**
* The id of the run
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package org.camunda.community.process_test_coverage.core.model
*
* @author dominikhorn
*/
class Suite(
data class Suite(
/**
* The id of the suite
*/
Expand Down
16 changes: 14 additions & 2 deletions extension/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
<module>spring-test-platform-7</module>
<module>spring-test-platform-8</module>
<module>report-generator</module>
<module>report-aggregator-maven-plugin</module>
<module>report-aggregator-gradle-plugin</module>
</modules>

<dependencyManagement>
Expand Down Expand Up @@ -88,4 +86,18 @@
<defaultGoal>clean install</defaultGoal>
</build>

<profiles>
<profile>
<id>plugins</id>
<activation>
<property><name>!skipPlugins</name></property>
</activation>
<modules>
<module>report-aggregator-maven-plugin</module>
<module>report-aggregator-gradle-plugin</module>
<module>sonar-process-test-coverage-plugin</module>
</modules>
</profile>
</profiles>

</project>
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
kotlinVersion=1.7.21
kotlinVersion=1.9.10
projectName=report-aggregator-gradle-plugin
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.camunda.community.process_test_coverage.report.aggregator

import org.camunda.community.process_test_coverage.core.export.CoverageStateJsonExporter
import org.camunda.community.process_test_coverage.core.export.CoverageStateJsonExporter.combineCoverageStateResults
import org.camunda.community.process_test_coverage.core.export.CoverageStateJsonExporter.createCoverageStateResult
import org.camunda.community.process_test_coverage.core.export.CoverageStateJsonExporter.readCoverageStateResult
import org.camunda.community.process_test_coverage.core.export.CoverageStateResult
import org.camunda.community.process_test_coverage.report.CoverageReportUtil
import org.gradle.api.Plugin
Expand Down Expand Up @@ -32,20 +34,15 @@ class ReportAggregatorPlugin : Plugin<Project> {
project.logger.debug("Reading file ${it.path}")
it.readText(Charsets.UTF_8)
}
.map { CoverageStateJsonExporter.readCoverageStateResult(it) }
.reduceOrNull { result1, result2 -> CoverageStateResult(
result1.suites + result2.suites,
result1.models.plus(result2.models.filter { new -> !result1.models.map { model -> model.key }.contains(new.key) })
)
}
.reduceOrNull { result1, result2 -> combineCoverageStateResults(result1, result2) }
?.let {
println(outputDirectory)
val report = readCoverageStateResult(it)
CoverageReportUtil.writeReport(
CoverageStateJsonExporter.createCoverageStateResult(it.suites, it.models), false,
createCoverageStateResult(report.suites, report.models), false,
outputDirectory, "report.json"
) { result -> result }
CoverageReportUtil.writeReport(
CoverageStateJsonExporter.createCoverageStateResult(it.suites, it.models), true,
createCoverageStateResult(report.suites, report.models), true,
outputDirectory, "report.html", CoverageReportUtil::generateHtml)
} ?: project.logger.warn("No coverage results found, skipping execution")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,63 @@
{"suites":[{"id":"[engine:junit-jupiter]/[class:org.camunda.community.process_test_coverage.report.aggregator.SecondTest]","name":"org.camunda.community.process_test_coverage.report.aggregator.SecondTest","runs":[{"id":"[engine:junit-jupiter]/[class:org.camunda.community.process_test_coverage.report.aggregator.SecondTest]/[method:should_have_100_percent_coverage]","name":"should_have_100_percent_coverage","events":[{"source":"FLOW_NODE","type":"START","definitionKey":"StartEvent_1","elementType":"startEvent","modelKey":"Testprocess","timestamp":1654807399},{"source":"FLOW_NODE","type":"END","definitionKey":"StartEvent_1","elementType":"startEvent","modelKey":"Testprocess","timestamp":1654807399},{"source":"SEQUENCE_FLOW","type":"TAKE","definitionKey":"Flow_0fnqvo6","elementType":"sequenceFlow","modelKey":"Testprocess","timestamp":1654807399},{"source":"FLOW_NODE","type":"START","definitionKey":"Event_0l5zycp","elementType":"endEvent","modelKey":"Testprocess","timestamp":1654807399},{"source":"FLOW_NODE","type":"END","definitionKey":"Event_0l5zycp","elementType":"endEvent","modelKey":"Testprocess","timestamp":1654807399}]}]}],"models":[{"key":"Testprocess","totalElementCount":3,"xml":"\u003c?xmlversion\u003d\"1.0\"encoding\u003d\"UTF-8\"standalone\u003d\"no\"?\u003e\n\u003cbpmn:definitionsxmlns:bpmn\u003d\"http://www.omg.org/spec/BPMN/20100524/MODEL\"xmlns:bpmndi\u003d\"http://www.omg.org/spec/BPMN/20100524/DI\"xmlns:dc\u003d\"http://www.omg.org/spec/DD/20100524/DC\"xmlns:di\u003d\"http://www.omg.org/spec/DD/20100524/DI\"xmlns:modeler\u003d\"http://camunda.org/schema/modeler/1.0\"exporter\u003d\"CamundaModeler\"exporterVersion\u003d\"5.0.0\"expressionLanguage\u003d\"http://www.w3.org/1999/XPath\"id\u003d\"Definitions_1r3mlfs\"modeler:executionPlatform\u003d\"CamundaPlatform\"modeler:executionPlatformVersion\u003d\"7.17.0\"targetNamespace\u003d\"http://bpmn.io/schema/bpmn\"typeLanguage\u003d\"http://www.w3.org/2001/XMLSchema\"\u003e\n\n\u003cbpmn:processid\u003d\"Testprocess\"isClosed\u003d\"false\"isExecutable\u003d\"true\"processType\u003d\"None\"\u003e\n\n\u003cbpmn:startEventid\u003d\"StartEvent_1\"isInterrupting\u003d\"true\"name\u003d\"Start\"parallelMultiple\u003d\"false\"\u003e\n\n\u003cbpmn:outgoing\u003eFlow_0fnqvo6\u003c/bpmn:outgoing\u003e\n\n\u003c/bpmn:startEvent\u003e\n\n\u003cbpmn:endEventid\u003d\"Event_0l5zycp\"name\u003d\"End\"\u003e\n\n\u003cbpmn:incoming\u003eFlow_0fnqvo6\u003c/bpmn:incoming\u003e\n\n\u003c/bpmn:endEvent\u003e\n\n\u003cbpmn:sequenceFlowid\u003d\"Flow_0fnqvo6\"sourceRef\u003d\"StartEvent_1\"targetRef\u003d\"Event_0l5zycp\"/\u003e\n\n\u003c/bpmn:process\u003e\n\n\u003cbpmndi:BPMNDiagramid\u003d\"BPMNDiagram_1\"\u003e\n\n\u003cbpmndi:BPMNPlanebpmnElement\u003d\"Testprocess\"id\u003d\"BPMNPlane_1\"\u003e\n\n\u003cbpmndi:BPMNEdgebpmnElement\u003d\"Flow_0fnqvo6\"id\u003d\"Flow_0fnqvo6_di\"\u003e\n\n\u003cdi:waypointx\u003d\"215\"y\u003d\"97\"/\u003e\n\n\u003cdi:waypointx\u003d\"272\"y\u003d\"97\"/\u003e\n\n\u003c/bpmndi:BPMNEdge\u003e\n\n\u003cbpmndi:BPMNShapebpmnElement\u003d\"StartEvent_1\"id\u003d\"_BPMNShape_StartEvent_2\"\u003e\n\n\u003cdc:Boundsheight\u003d\"36\"width\u003d\"36\"x\u003d\"179\"y\u003d\"79\"/\u003e\n\n\u003cbpmndi:BPMNLabel\u003e\n\n\u003cdc:Boundsheight\u003d\"14\"width\u003d\"28\"x\u003d\"183\"y\u003d\"122\"/\u003e\n\n\u003c/bpmndi:BPMNLabel\u003e\n\n\u003c/bpmndi:BPMNShape\u003e\n\n\u003cbpmndi:BPMNShapebpmnElement\u003d\"Event_0l5zycp\"id\u003d\"Event_0l5zycp_di\"\u003e\n\n\u003cdc:Boundsheight\u003d\"36\"width\u003d\"36\"x\u003d\"272\"y\u003d\"79\"/\u003e\n\n\u003cbpmndi:BPMNLabel\u003e\n\n\u003cdc:Boundsheight\u003d\"14\"width\u003d\"21\"x\u003d\"280\"y\u003d\"122\"/\u003e\n\n\u003c/bpmndi:BPMNLabel\u003e\n\n\u003c/bpmndi:BPMNShape\u003e\n\n\u003c/bpmndi:BPMNPlane\u003e\n\n\u003c/bpmndi:BPMNDiagram\u003e\n\n\u003c/bpmn:definitions\u003e\n"}]}
{
"suites": [
{
"id": "[engine:junit-jupiter]/[class:org.camunda.community.process_test_coverage.report.aggregator.SecondTest]",
"name": "org.camunda.community.process_test_coverage.report.aggregator.SecondTest",
"runs": [
{
"id": "[engine:junit-jupiter]/[class:org.camunda.community.process_test_coverage.report.aggregator.SecondTest]/[method:should_have_100_percent_coverage]",
"name": "should_have_100_percent_coverage",
"events": [
{
"source": "FLOW_NODE",
"type": "START",
"definitionKey": "StartEvent_1",
"elementType": "startEvent",
"modelKey": "Testprocess",
"timestamp": 1654807399
},
{
"source": "FLOW_NODE",
"type": "END",
"definitionKey": "StartEvent_1",
"elementType": "startEvent",
"modelKey": "Testprocess",
"timestamp": 1654807399
},
{
"source": "SEQUENCE_FLOW",
"type": "TAKE",
"definitionKey": "Flow_0fnqvo6",
"elementType": "sequenceFlow",
"modelKey": "Testprocess",
"timestamp": 1654807399
},
{
"source": "FLOW_NODE",
"type": "START",
"definitionKey": "Event_0l5zycp",
"elementType": "endEvent",
"modelKey": "Testprocess",
"timestamp": 1654807399
},
{
"source": "FLOW_NODE",
"type": "END",
"definitionKey": "Event_0l5zycp",
"elementType": "endEvent",
"modelKey": "Testprocess",
"timestamp": 1654807399
}
]
}
]
}
],
"models": [
{
"key": "Testprocess",
"totalElementCount": 3,
"xml": "\u003c?xmlversion\u003d\"1.0\"encoding\u003d\"UTF-8\"standalone\u003d\"no\"?\u003e\n\u003cbpmn:definitionsxmlns:bpmn\u003d\"http://www.omg.org/spec/BPMN/20100524/MODEL\"xmlns:bpmndi\u003d\"http://www.omg.org/spec/BPMN/20100524/DI\"xmlns:dc\u003d\"http://www.omg.org/spec/DD/20100524/DC\"xmlns:di\u003d\"http://www.omg.org/spec/DD/20100524/DI\"xmlns:modeler\u003d\"http://camunda.org/schema/modeler/1.0\"exporter\u003d\"CamundaModeler\"exporterVersion\u003d\"5.0.0\"expressionLanguage\u003d\"http://www.w3.org/1999/XPath\"id\u003d\"Definitions_1r3mlfs\"modeler:executionPlatform\u003d\"CamundaPlatform\"modeler:executionPlatformVersion\u003d\"7.17.0\"targetNamespace\u003d\"http://bpmn.io/schema/bpmn\"typeLanguage\u003d\"http://www.w3.org/2001/XMLSchema\"\u003e\n\n\u003cbpmn:processid\u003d\"Testprocess\"isClosed\u003d\"false\"isExecutable\u003d\"true\"processType\u003d\"None\"\u003e\n\n\u003cbpmn:startEventid\u003d\"StartEvent_1\"isInterrupting\u003d\"true\"name\u003d\"Start\"parallelMultiple\u003d\"false\"\u003e\n\n\u003cbpmn:outgoing\u003eFlow_0fnqvo6\u003c/bpmn:outgoing\u003e\n\n\u003c/bpmn:startEvent\u003e\n\n\u003cbpmn:endEventid\u003d\"Event_0l5zycp\"name\u003d\"End\"\u003e\n\n\u003cbpmn:incoming\u003eFlow_0fnqvo6\u003c/bpmn:incoming\u003e\n\n\u003c/bpmn:endEvent\u003e\n\n\u003cbpmn:sequenceFlowid\u003d\"Flow_0fnqvo6\"sourceRef\u003d\"StartEvent_1\"targetRef\u003d\"Event_0l5zycp\"/\u003e\n\n\u003c/bpmn:process\u003e\n\n\u003cbpmndi:BPMNDiagramid\u003d\"BPMNDiagram_1\"\u003e\n\n\u003cbpmndi:BPMNPlanebpmnElement\u003d\"Testprocess\"id\u003d\"BPMNPlane_1\"\u003e\n\n\u003cbpmndi:BPMNEdgebpmnElement\u003d\"Flow_0fnqvo6\"id\u003d\"Flow_0fnqvo6_di\"\u003e\n\n\u003cdi:waypointx\u003d\"215\"y\u003d\"97\"/\u003e\n\n\u003cdi:waypointx\u003d\"272\"y\u003d\"97\"/\u003e\n\n\u003c/bpmndi:BPMNEdge\u003e\n\n\u003cbpmndi:BPMNShapebpmnElement\u003d\"StartEvent_1\"id\u003d\"_BPMNShape_StartEvent_2\"\u003e\n\n\u003cdc:Boundsheight\u003d\"36\"width\u003d\"36\"x\u003d\"179\"y\u003d\"79\"/\u003e\n\n\u003cbpmndi:BPMNLabel\u003e\n\n\u003cdc:Boundsheight\u003d\"14\"width\u003d\"28\"x\u003d\"183\"y\u003d\"122\"/\u003e\n\n\u003c/bpmndi:BPMNLabel\u003e\n\n\u003c/bpmndi:BPMNShape\u003e\n\n\u003cbpmndi:BPMNShapebpmnElement\u003d\"Event_0l5zycp\"id\u003d\"Event_0l5zycp_di\"\u003e\n\n\u003cdc:Boundsheight\u003d\"36\"width\u003d\"36\"x\u003d\"272\"y\u003d\"79\"/\u003e\n\n\u003cbpmndi:BPMNLabel\u003e\n\n\u003cdc:Boundsheight\u003d\"14\"width\u003d\"21\"x\u003d\"280\"y\u003d\"122\"/\u003e\n\n\u003c/bpmndi:BPMNLabel\u003e\n\n\u003c/bpmndi:BPMNShape\u003e\n\n\u003c/bpmndi:BPMNPlane\u003e\n\n\u003c/bpmndi:BPMNDiagram\u003e\n\n\u003c/bpmn:definitions\u003e\n"
}
]
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package org.camunda.community.process_test_coverage.report.aggregator

import org.apache.maven.MavenExecutionException
import org.apache.maven.doxia.sink.Sink
import org.apache.maven.plugin.AbstractMojo
import org.apache.maven.plugins.annotations.LifecyclePhase
import org.apache.maven.plugins.annotations.Mojo
import org.apache.maven.plugins.annotations.Parameter
import org.apache.maven.project.MavenProject
import org.apache.maven.reporting.MavenReport
import org.camunda.community.process_test_coverage.core.export.CoverageStateJsonExporter.combineCoverageStateResults
import org.camunda.community.process_test_coverage.core.export.CoverageStateJsonExporter.createCoverageStateResult
import org.camunda.community.process_test_coverage.core.export.CoverageStateJsonExporter.readCoverageStateResult
import org.camunda.community.process_test_coverage.core.export.CoverageStateResult
import org.camunda.community.process_test_coverage.report.CoverageReportUtil
import org.codehaus.plexus.util.FileUtils
import java.io.File
Expand Down Expand Up @@ -95,16 +94,13 @@ class ReportAggregatorMojo : AbstractMojo(), MavenReport {
log.debug("Reading file ${it.path}")
FileUtils.fileRead(it)
}
.map { readCoverageStateResult(it) }
.reduceOrNull { result1, result2 -> CoverageStateResult(
result1.suites + result2.suites,
result1.models.plus(result2.models.filter { new -> !result1.models.map { model -> model.key }.contains(new.key) })
)}
.reduceOrNull { result1, result2 -> combineCoverageStateResults(result1, result2) }
?.let {
CoverageReportUtil.writeReport(createCoverageStateResult(it.suites, it.models), false,
val report = readCoverageStateResult(it)
CoverageReportUtil.writeReport(createCoverageStateResult(report.suites, report.models), false,
outputDirectory.path, "report.json"
) { result -> result }
CoverageReportUtil.writeReport(createCoverageStateResult(it.suites, it.models), true,
CoverageReportUtil.writeReport(createCoverageStateResult(report.suites, report.models), true,
outputDirectory.path, "report.html", CoverageReportUtil::generateHtml)
} ?: log.warn("No coverage results found, skipping execution")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class CoverageReportUtil {
*/
public static String TARGET_DIR_ROOT = System.getProperty("camunda-process-test-coverage.target-dir-root", "target/process-test-coverage/");
public static final String REPORT_RESOURCES = "static";
private static final String REPORT_TEMPLATE = "bpmn.report-template.html";
private static final String REPORT_TEMPLATE = "html/bpmn.report-template.html";


public static void createReport(final DefaultCollector coverageCollector) {
Expand Down
Loading

0 comments on commit 358b53b

Please sign in to comment.