From 055d4226fce309645590bd502a77f7d7bf16fd00 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Wed, 19 Apr 2023 21:47:03 +0200 Subject: [PATCH 01/23] Add TestExecutionMermaidDiagramFormatterSpec --- ...xecutionMermaidDiagramFormatterSpec.groovy | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy diff --git a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy new file mode 100644 index 0000000..bf11809 --- /dev/null +++ b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy @@ -0,0 +1,32 @@ +package io.github.platan.tests_execution_chart.reporters.mermaid + + +import io.github.platan.tests_execution_chart.report.TestExecutionScheduleReportBuilder +import spock.lang.Specification + +class TestExecutionMermaidDiagramFormatterSpec extends Specification { + + def "should format report"() { + given: + def reportBuilder = new TestExecutionScheduleReportBuilder() + reportBuilder.add('Test1', 'test1', 1681402397000, 1681402397100, 'SUCCESS') + reportBuilder.add('Test1', 'test2', 1681402397100, 1681402397300, 'SUCCESS') + reportBuilder.add('Test2', 'test1', 1681402397000, 1681402397100, 'SUCCESS') + + when: + def mermaidReport = new TestExecutionMermaidDiagramFormatter().format(reportBuilder.getResults()) + + + def indent = """gantt +dateFormat YYYY-MM-DDTHH:mm:ss.SSSZZ +axisFormat %H:%M:%S.%L +section Test1 +test1 - 100 ms :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+0200 +test2 - 200 ms :active, 2023-04-13T18:13:17.100+0200, 2023-04-13T18:13:17.300+0200 +section Test2 +test1 - 100 ms :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+0200 +""" + then: + mermaidReport == indent + } +} From bdeebae5314ae4386ea4925d6d37bd5035724931 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Wed, 19 Apr 2023 22:09:54 +0200 Subject: [PATCH 02/23] Set time zone in tests --- .../TestExecutionMermaidDiagramFormatterSpec.groovy | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy index bf11809..73217b7 100644 --- a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy +++ b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy @@ -1,13 +1,16 @@ package io.github.platan.tests_execution_chart.reporters.mermaid - import io.github.platan.tests_execution_chart.report.TestExecutionScheduleReportBuilder import spock.lang.Specification +import java.time.ZoneOffset + class TestExecutionMermaidDiagramFormatterSpec extends Specification { def "should format report"() { given: + def getDefault = TimeZone.getDefault() + TimeZone.setDefault(SimpleTimeZone.getTimeZone(ZoneOffset.ofHours(2))) def reportBuilder = new TestExecutionScheduleReportBuilder() reportBuilder.add('Test1', 'test1', 1681402397000, 1681402397100, 'SUCCESS') reportBuilder.add('Test1', 'test2', 1681402397100, 1681402397300, 'SUCCESS') @@ -28,5 +31,8 @@ test1 - 100 ms :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+02 """ then: mermaidReport == indent + + cleanup: + TimeZone.setDefault(getDefault) } } From c10d4e03fd62cbc19ad6969aa0d33489e76ea5fc Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Thu, 20 Apr 2023 21:10:03 +0200 Subject: [PATCH 03/23] Replace Date with Instant MermaidGanttDiagramFormatter --- .../reporters/mermaid/MermaidGanttDiagramFormatter.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt index fd60e6b..d4c18e0 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt @@ -1,7 +1,8 @@ package io.github.platan.tests_execution_chart.reporters.mermaid -import java.text.SimpleDateFormat -import java.util.Date +import java.time.Instant +import java.time.ZoneId +import java.time.format.DateTimeFormatter internal class MermaidGanttDiagramFormatter { @@ -10,7 +11,7 @@ internal class MermaidGanttDiagramFormatter { ganttDiagram.append("gantt\n") ganttDiagram.append("dateFormat ${diagram.dateFormat}\n") ganttDiagram.append("axisFormat ${diagram.axisFormat}\n") - val format = SimpleDateFormat(dateFormat) + val format = DateTimeFormatter.ofPattern(dateFormat).withZone(ZoneId.systemDefault()) diagram.sections.forEach { section -> ganttDiagram.append("section ${escape(section.name)}\n") section.rows.forEach { row -> @@ -18,8 +19,8 @@ internal class MermaidGanttDiagramFormatter { if (row.type != null) { status = "${row.type}, " } - val end = format.format(Date(row.end)) - val start = format.format(Date(row.start)) + val end = format.format(Instant.ofEpochMilli(row.end)) + val start = format.format(Instant.ofEpochMilli(row.start)) ganttDiagram.append("${escape(row.name)} :${status}$start, $end\n") } } From e658d92fd8effdd1b759d3d3f4b9abaa9adaf478 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Wed, 26 Apr 2023 21:13:18 +0200 Subject: [PATCH 04/23] Add MermaidGanttDiagramFormatterTest --- ...iagramFormatterToSvgConversionSpec.groovy} | 2 +- .../MermaidGanttDiagramFormatterTest.groovy | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) rename src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/{MermaidGanttDiagramFormatterSpec.groovy => MermaidGanttDiagramFormatterToSvgConversionSpec.groovy} (95%) create mode 100644 src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy diff --git a/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterSpec.groovy b/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy similarity index 95% rename from src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterSpec.groovy rename to src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy index 910d7f2..8a9230a 100644 --- a/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterSpec.groovy +++ b/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy @@ -4,7 +4,7 @@ import spock.lang.Retry import spock.lang.Specification import spock.lang.TempDir -class MermaidGanttDiagramFormatterSpec extends Specification { +class MermaidGanttDiagramFormatterToSvgConversionSpec extends Specification { @TempDir File tempDir diff --git a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy new file mode 100644 index 0000000..a7712ed --- /dev/null +++ b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy @@ -0,0 +1,39 @@ +package io.github.platan.tests_execution_chart.reporters.mermaid + + +import spock.lang.Specification + +import java.time.ZoneOffset + +class MermaidGanttDiagramFormatterTest extends Specification { + + def "should format report"() { + given: + def getDefault = TimeZone.getDefault() + TimeZone.setDefault(SimpleTimeZone.getTimeZone(ZoneOffset.ofHours(2))) + def diagramBuilder = new MermaidGanttDiagram.MermaidGanttDiagramBuilder() + diagramBuilder.add('Test1', 'test1 - 100 ms', 'active', 1681402397000, 1681402397100) + diagramBuilder.add('Test1', 'test2 - 200 ms', 'active', 1681402397100, 1681402397300) + diagramBuilder.add('Test2', 'test1 - 100 ms', 'active', 1681402397000, 1681402397100) + MermaidGanttDiagram diagram = diagramBuilder.build("YYYY-MM-DDTHH:mm:ss.SSSZZ", "%H:%M:%S.%L") + + when: + def mermaidReport = new MermaidGanttDiagramFormatter().format(diagram, "yyyy-MM-dd'T'HH:mm:ss.SSSZ") + + + def indent = """gantt +dateFormat YYYY-MM-DDTHH:mm:ss.SSSZZ +axisFormat %H:%M:%S.%L +section Test1 +test1 - 100 ms :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+0200 +test2 - 200 ms :active, 2023-04-13T18:13:17.100+0200, 2023-04-13T18:13:17.300+0200 +section Test2 +test1 - 100 ms :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+0200 +""" + then: + mermaidReport == indent + + cleanup: + TimeZone.setDefault(getDefault) + } +} From 9832d8c72c3076937614f3020d289900abc77838 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Wed, 26 Apr 2023 21:28:28 +0200 Subject: [PATCH 05/23] Add milestones to MermaidGanttDiagramFormatter --- .../reporters/mermaid/MermaidGanttDiagram.kt | 17 +++++++++++++++-- .../mermaid/MermaidGanttDiagramFormatter.kt | 4 ++++ .../MermaidGanttDiagramFormatterTest.groovy | 2 ++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagram.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagram.kt index d50d214..e1bb12e 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagram.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagram.kt @@ -1,18 +1,30 @@ package io.github.platan.tests_execution_chart.reporters.mermaid -data class MermaidGanttDiagram(val dateFormat: String, val axisFormat: String, val sections: List
) { +data class MermaidGanttDiagram( + val dateFormat: String, + val axisFormat: String, + val sections: List
, + val milestones: List +) { data class Section(val name: String, val rows: List) { data class Row(val name: String, val type: String?, val start: Long, val end: Long) } + data class Milestone(val name: String, val timestamp: Long) + class MermaidGanttDiagramBuilder { private val sectionsMap: MutableMap> = mutableMapOf() + private val milestones: MutableList = mutableListOf() fun add(sectionName: String, rowName: String, type: String?, start: Long, end: Long) { val section: MutableList = sectionsMap.getOrPut(sectionName) { mutableListOf() } section.add(Section.Row(rowName, type, start, end)) } + fun addMilestone(name: String, timestamp: Long) { + milestones.add(Milestone(name, timestamp)) + } + fun build(dateFormat: String, axisFormat: String): MermaidGanttDiagram { return MermaidGanttDiagram( dateFormat, @@ -29,7 +41,8 @@ data class MermaidGanttDiagram(val dateFormat: String, val axisFormat: String, v ) } ) - } + }, + milestones.toList() ) } } diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt index d4c18e0..bced49a 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt @@ -24,6 +24,10 @@ internal class MermaidGanttDiagramFormatter { ganttDiagram.append("${escape(row.name)} :${status}$start, $end\n") } } + diagram.milestones.forEach { milestone -> + val timestamp = format.format(Instant.ofEpochMilli(milestone.timestamp)) + ganttDiagram.append("${milestone.name} : milestone, $timestamp, 0\n") + } return ganttDiagram.toString() } diff --git a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy index a7712ed..c01ece8 100644 --- a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy +++ b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy @@ -15,6 +15,7 @@ class MermaidGanttDiagramFormatterTest extends Specification { diagramBuilder.add('Test1', 'test1 - 100 ms', 'active', 1681402397000, 1681402397100) diagramBuilder.add('Test1', 'test2 - 200 ms', 'active', 1681402397100, 1681402397300) diagramBuilder.add('Test2', 'test1 - 100 ms', 'active', 1681402397000, 1681402397100) + diagramBuilder.addMilestone('milestone1', 1681402397400) MermaidGanttDiagram diagram = diagramBuilder.build("YYYY-MM-DDTHH:mm:ss.SSSZZ", "%H:%M:%S.%L") when: @@ -29,6 +30,7 @@ test1 - 100 ms :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+02 test2 - 200 ms :active, 2023-04-13T18:13:17.100+0200, 2023-04-13T18:13:17.300+0200 section Test2 test1 - 100 ms :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+0200 +milestone1 : milestone, 2023-04-13T18:13:17.400+0200, 0 """ then: mermaidReport == indent From cec3ac9c3d873806d74a15b5b09b4e7406848482 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Sun, 30 Apr 2023 11:13:24 +0200 Subject: [PATCH 06/23] Preserve order of tasks and milestones --- ...DiagramFormatterToSvgConversionSpec.groovy | 3 +- .../reporters/mermaid/MermaidGanttDiagram.kt | 43 +++++++------------ .../mermaid/MermaidGanttDiagramFormatter.kt | 32 ++++++++------ .../TestExecutionMermaidDiagramFormatter.kt | 14 ++++-- .../MermaidGanttDiagramFormatterTest.groovy | 15 ++++--- 5 files changed, 57 insertions(+), 50 deletions(-) diff --git a/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy b/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy index 8a9230a..3bbfbb0 100644 --- a/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy +++ b/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy @@ -27,7 +27,8 @@ class MermaidGanttDiagramFormatterToSvgConversionSpec extends Specification { def "should produce result parsable by mmdc (mermaid CLI)"() { given: def diagramBuilder = new MermaidGanttDiagram.MermaidGanttDiagramBuilder() - diagramBuilder.add("test-section $SPECIAL_CHARS", "test-row $SPECIAL_CHARS", 'active', 1, 2) + diagramBuilder.addSection("test-section $SPECIAL_CHARS") + diagramBuilder.addTask("test-row $SPECIAL_CHARS", 'active', 1, 2) def diagram = diagramBuilder.build("YYYY-MM-DD\\THH\\:mm\\:ss\\.SSSZ", "%H:%M:%S.%L") def mermaid = new MermaidGanttDiagramFormatter().format(diagram, "yyyy-MM-dd'T'HH:mm:ss.SSSZ") inputFile.text = mermaid diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagram.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagram.kt index e1bb12e..e22494e 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagram.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagram.kt @@ -3,46 +3,33 @@ package io.github.platan.tests_execution_chart.reporters.mermaid data class MermaidGanttDiagram( val dateFormat: String, val axisFormat: String, - val sections: List
, - val milestones: List + val entries: List ) { - data class Section(val name: String, val rows: List) { - data class Row(val name: String, val type: String?, val start: Long, val end: Long) - } - - data class Milestone(val name: String, val timestamp: Long) + sealed interface Entry + data class Section(val name: String) : Entry + data class Task(val name: String, val type: String?, val start: Long, val end: Long) : Entry + data class Milestone(val name: String, val timestamp: Long) : Entry class MermaidGanttDiagramBuilder { - private val sectionsMap: MutableMap> = mutableMapOf() - private val milestones: MutableList = mutableListOf() - fun add(sectionName: String, rowName: String, type: String?, start: Long, end: Long) { - val section: MutableList = - sectionsMap.getOrPut(sectionName) { mutableListOf() } - section.add(Section.Row(rowName, type, start, end)) + private val entries: MutableList = mutableListOf() + + fun addTask(name: String, type: String?, start: Long, end: Long) { + entries.add(Task(name, type, start, end)) + } + + fun addSection(name: String) { + entries.add(Section(name)) } fun addMilestone(name: String, timestamp: Long) { - milestones.add(Milestone(name, timestamp)) + entries.add(Milestone(name, timestamp)) } fun build(dateFormat: String, axisFormat: String): MermaidGanttDiagram { return MermaidGanttDiagram( dateFormat, axisFormat, - sectionsMap.entries.map { sectionEntry -> - Section( - sectionEntry.key, - sectionEntry.value.map { row -> - Section.Row( - row.name, - row.type, - row.start, - row.end - ) - } - ) - }, - milestones.toList() + entries.toList() ) } } diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt index bced49a..12b0945 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt @@ -12,22 +12,28 @@ internal class MermaidGanttDiagramFormatter { ganttDiagram.append("dateFormat ${diagram.dateFormat}\n") ganttDiagram.append("axisFormat ${diagram.axisFormat}\n") val format = DateTimeFormatter.ofPattern(dateFormat).withZone(ZoneId.systemDefault()) - diagram.sections.forEach { section -> - ganttDiagram.append("section ${escape(section.name)}\n") - section.rows.forEach { row -> - var status = "" - if (row.type != null) { - status = "${row.type}, " + diagram.entries.forEach { entry -> + when (entry) { + is MermaidGanttDiagram.Section -> { + ganttDiagram.append("section ${escape(entry.name)}\n") + } + + is MermaidGanttDiagram.Task -> { + var status = "" + if (entry.type != null) { + status = "${entry.type}, " + } + val end = format.format(Instant.ofEpochMilli(entry.end)) + val start = format.format(Instant.ofEpochMilli(entry.start)) + ganttDiagram.append("${escape(entry.name)} :${status}$start, $end\n") + } + + is MermaidGanttDiagram.Milestone -> { + val timestamp = format.format(Instant.ofEpochMilli(entry.timestamp)) + ganttDiagram.append("${entry.name} : milestone, $timestamp, 0\n") } - val end = format.format(Instant.ofEpochMilli(row.end)) - val start = format.format(Instant.ofEpochMilli(row.start)) - ganttDiagram.append("${escape(row.name)} :${status}$start, $end\n") } } - diagram.milestones.forEach { milestone -> - val timestamp = format.format(Instant.ofEpochMilli(milestone.timestamp)) - ganttDiagram.append("${milestone.name} : milestone, $timestamp, 0\n") - } return ganttDiagram.toString() } diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatter.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatter.kt index 098a471..e8e5d46 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatter.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatter.kt @@ -10,9 +10,17 @@ class TestExecutionMermaidDiagramFormatter { fun format(report: TestExecutionScheduleReport): String { val diagramBuilder = MermaidGanttDiagram.MermaidGanttDiagramBuilder() - report.results.forEach { - val testNameWithDuration = "${it.testName} - ${it.endTime.minus(it.startTime)} ms" - diagramBuilder.add(it.className!!, testNameWithDuration, types[it.resultType], it.startTime, it.endTime) + report.results.groupBy { result -> result.className }.forEach { (className, results) -> + diagramBuilder.addSection(className.orEmpty()) + results.forEach { + val testNameWithDuration = "${it.testName} - ${it.endTime.minus(it.startTime)} ms" + diagramBuilder.addTask( + testNameWithDuration, + types[it.resultType], + it.startTime, + it.endTime + ) + } } val diagram = diagramBuilder.build("YYYY-MM-DDTHH:mm:ss.SSSZZ", "%H:%M:%S.%L") return MermaidGanttDiagramFormatter().format(diagram, "yyyy-MM-dd'T'HH:mm:ss.SSSZ") diff --git a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy index c01ece8..d84810e 100644 --- a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy +++ b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy @@ -12,10 +12,14 @@ class MermaidGanttDiagramFormatterTest extends Specification { def getDefault = TimeZone.getDefault() TimeZone.setDefault(SimpleTimeZone.getTimeZone(ZoneOffset.ofHours(2))) def diagramBuilder = new MermaidGanttDiagram.MermaidGanttDiagramBuilder() - diagramBuilder.add('Test1', 'test1 - 100 ms', 'active', 1681402397000, 1681402397100) - diagramBuilder.add('Test1', 'test2 - 200 ms', 'active', 1681402397100, 1681402397300) - diagramBuilder.add('Test2', 'test1 - 100 ms', 'active', 1681402397000, 1681402397100) - diagramBuilder.addMilestone('milestone1', 1681402397400) + diagramBuilder.addSection('Test1') + diagramBuilder.addTask('test1 - 100 ms', 'active', 1681402397000, 1681402397100) + diagramBuilder.addTask('test2 - 200 ms', 'active', 1681402397100, 1681402397300) + diagramBuilder.addMilestone('milestone1', 1681402397100) + diagramBuilder.addSection('Test2') + diagramBuilder.addTask('test1 - 100 ms', 'active', 1681402397000, 1681402397100) + diagramBuilder.addMilestone('milestone2', 1681402397400) + MermaidGanttDiagram diagram = diagramBuilder.build("YYYY-MM-DDTHH:mm:ss.SSSZZ", "%H:%M:%S.%L") when: @@ -28,9 +32,10 @@ axisFormat %H:%M:%S.%L section Test1 test1 - 100 ms :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+0200 test2 - 200 ms :active, 2023-04-13T18:13:17.100+0200, 2023-04-13T18:13:17.300+0200 +milestone1 : milestone, 2023-04-13T18:13:17.100+0200, 0 section Test2 test1 - 100 ms :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+0200 -milestone1 : milestone, 2023-04-13T18:13:17.400+0200, 0 +milestone2 : milestone, 2023-04-13T18:13:17.400+0200, 0 """ then: mermaidReport == indent From 42ef49f5d5e8d4489544134256fbaa7c8ac9f3f9 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Sun, 30 Apr 2023 11:31:16 +0200 Subject: [PATCH 07/23] Escape milestone name --- .../MermaidGanttDiagramFormatterToSvgConversionSpec.groovy | 1 + .../reporters/mermaid/MermaidGanttDiagramFormatter.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy b/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy index 3bbfbb0..3033125 100644 --- a/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy +++ b/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy @@ -29,6 +29,7 @@ class MermaidGanttDiagramFormatterToSvgConversionSpec extends Specification { def diagramBuilder = new MermaidGanttDiagram.MermaidGanttDiagramBuilder() diagramBuilder.addSection("test-section $SPECIAL_CHARS") diagramBuilder.addTask("test-row $SPECIAL_CHARS", 'active', 1, 2) + diagramBuilder.addMilestone("test-milestone $SPECIAL_CHARS", 1) def diagram = diagramBuilder.build("YYYY-MM-DD\\THH\\:mm\\:ss\\.SSSZ", "%H:%M:%S.%L") def mermaid = new MermaidGanttDiagramFormatter().format(diagram, "yyyy-MM-dd'T'HH:mm:ss.SSSZ") inputFile.text = mermaid diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt index 12b0945..59a8664 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt @@ -30,7 +30,7 @@ internal class MermaidGanttDiagramFormatter { is MermaidGanttDiagram.Milestone -> { val timestamp = format.format(Instant.ofEpochMilli(entry.timestamp)) - ganttDiagram.append("${entry.name} : milestone, $timestamp, 0\n") + ganttDiagram.append("${escape(entry.name)} : milestone, $timestamp, 0\n") } } } From 12f58ab0999aba894422a291765c5d73b26c49b9 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Sun, 30 Apr 2023 11:52:19 +0200 Subject: [PATCH 08/23] Document mark.maxEndTimeOfPreviousRuns property --- README.md | 6 ++++++ .../CreateTestsExecutionReportExtension.kt | 4 ++++ .../CreateTestsExecutionReportTask.kt | 10 +++++++++- .../TestsExecutionReportPlugin.kt | 1 + .../platan/tests_execution_chart/config/Mark.kt | 12 ++++++++++++ 5 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/io/github/platan/tests_execution_chart/config/Mark.kt diff --git a/README.md b/README.md index a84a4a8..b76eed1 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,9 @@ configure = objectFactory.property(Boolean::class.java).convention(false) diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/CreateTestsExecutionReportTask.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/CreateTestsExecutionReportTask.kt index bc0b292..b1eee45 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/CreateTestsExecutionReportTask.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/CreateTestsExecutionReportTask.kt @@ -1,6 +1,7 @@ package io.github.platan.tests_execution_chart import io.github.platan.tests_execution_chart.config.Formats +import io.github.platan.tests_execution_chart.config.Mark import io.github.platan.tests_execution_chart.report.TestExecutionScheduleReport import io.github.platan.tests_execution_chart.reporters.Logger import io.github.platan.tests_execution_chart.reporters.html.HtmlGanttDiagramReporter @@ -37,6 +38,9 @@ abstract class CreateTestsExecutionReportTask @Inject constructor(objectFactory: @Nested abstract fun getFormats(): Formats + @Nested + abstract fun getMark(): Mark + @get:Input val shiftTimestampsToStartOfDay: Property = objectFactory.property(Boolean::class.java).convention(false) @@ -57,7 +61,11 @@ abstract class CreateTestsExecutionReportTask @Inject constructor(objectFactory: ) } if (getFormats().getJson().enabled.get()) { - JsonReporter(getFormats().getJson(), customLogger).report(adjustedResults, task.project.buildDir, task.name) + JsonReporter(getFormats().getJson(), customLogger).report( + adjustedResults, + task.project.buildDir, + task.name + ) } if (getFormats().getHtml().enabled.get()) { HtmlGanttDiagramReporter(getFormats().getHtml().toHtmlConfig(), customLogger).report( diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/TestsExecutionReportPlugin.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/TestsExecutionReportPlugin.kt index 71f2f66..c1440cd 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/TestsExecutionReportPlugin.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/TestsExecutionReportPlugin.kt @@ -51,5 +51,6 @@ class TestsExecutionReportPlugin : Plugin { .set(createTestsExecutionReportExtension.getFormats().getMermaid().outputLocation) task.shiftTimestampsToStartOfDay.set(createTestsExecutionReportExtension.shiftTimestampsToStartOfDay) + task.getMark().maxEndTimeOfPreviousRuns.set(createTestsExecutionReportExtension.getMark().maxEndTimeOfPreviousRuns) } } diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/config/Mark.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/config/Mark.kt new file mode 100644 index 0000000..1236cc1 --- /dev/null +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/config/Mark.kt @@ -0,0 +1,12 @@ +package io.github.platan.tests_execution_chart.config + +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import javax.inject.Inject + +abstract class Mark @Inject constructor(objectFactory: ObjectFactory) { + + @get:Input + val maxEndTimeOfPreviousRuns: Property = objectFactory.property(Boolean::class.java).convention(false) +} From e8ccae245382e9acea99418f3061f5b1e4706730 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Tue, 23 May 2023 21:26:34 +0200 Subject: [PATCH 09/23] Agg mark to TestExecutionScheduleReport --- README.md | 26 +++++++++++------ .../CreateTestsExecutionReportExtension.kt | 8 ++++-- .../CreateTestsExecutionReportTask.kt | 4 +-- .../TestsExecutionReportPlugin.kt | 7 ++++- .../tests_execution_chart/config/Mark.kt | 5 +++- .../tests_execution_chart/config/Marks.kt | 16 +++++++++++ .../tests_execution_chart/report/Mark.kt | 9 ++++++ .../report/TestExecutionScheduleReport.kt | 12 +++++++- ...estExecutionScheduleReportMarksTest.groovy | 28 +++++++++++++++++++ 9 files changed, 99 insertions(+), 16 deletions(-) create mode 100644 src/main/kotlin/io/github/platan/tests_execution_chart/config/Marks.kt create mode 100644 src/main/kotlin/io/github/platan/tests_execution_chart/report/Mark.kt create mode 100644 src/test/groovy/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReportMarksTest.groovy diff --git a/README.md b/README.md index b76eed1..2ee012a 100644 --- a/README.md +++ b/README.md @@ -105,11 +105,11 @@ rendered: ([info](https://github.blog/2022-02-14-include-diagrams-markdown-files ```mermaid gantt -dateFormat YYYY-MM-DDTHH:mm:ss.SSSZZ -axisFormat %H:%M:%S.%L -section Test1Spec -test 2 - 120 ms :active, 2022-11-08T20:46:17.854+0100, 2022-11-08T20:46:17.974+0100 -test 1 - 213 ms :active, 2022-11-08T20:46:17.854+0100, 2022-11-08T20:46:18.067+0100 + dateFormat YYYY-MM-DDTHH:mm:ss.SSSZZ + axisFormat %H:%M:%S.%L + section Test1Spec + test 2 - 120 ms: active, 2022-11-08T20:46:17.854+0100, 2022-11-08T20:46:17.974+0100 + test 1 - 213 ms: active, 2022-11-08T20:46:17.854+0100, 2022-11-08T20:46:18.067+0100 ``` # Configuration @@ -125,6 +125,8 @@ Options: | `formats.json.enabled` | boolean | Generate report in json format | `true` | | `formats.mermaid.enabled` | boolean | Generate report in mermaid text format | `true` | | `shiftTimestampsToStartOfDay` | boolean | Adjust the earliest timestamp to the start of the day | `false` | +| `marks.totalTimeOfAllTests.enabled` | boolean | Enable mark showing total time of all tests | `false` | +| `marks.totalTimeOfAllTests.name` | string | Label used for mark | `total time of all tests` | `build.gradle.kts`: @@ -149,8 +151,11 @@ configure = objectFactory.property(Boolean::class.java).convention(false) @@ -23,4 +23,8 @@ abstract class CreateTestsExecutionReportExtension @Inject constructor(objectFac open fun formats(action: Action) { action.execute(getFormats()) } + + open fun marks(action: Action) { + action.execute(getMarks()) + } } diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/CreateTestsExecutionReportTask.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/CreateTestsExecutionReportTask.kt index b1eee45..0e2c728 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/CreateTestsExecutionReportTask.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/CreateTestsExecutionReportTask.kt @@ -1,7 +1,7 @@ package io.github.platan.tests_execution_chart import io.github.platan.tests_execution_chart.config.Formats -import io.github.platan.tests_execution_chart.config.Mark +import io.github.platan.tests_execution_chart.config.Marks import io.github.platan.tests_execution_chart.report.TestExecutionScheduleReport import io.github.platan.tests_execution_chart.reporters.Logger import io.github.platan.tests_execution_chart.reporters.html.HtmlGanttDiagramReporter @@ -39,7 +39,7 @@ abstract class CreateTestsExecutionReportTask @Inject constructor(objectFactory: abstract fun getFormats(): Formats @Nested - abstract fun getMark(): Mark + abstract fun getMarks(): Marks @get:Input val shiftTimestampsToStartOfDay: Property = objectFactory.property(Boolean::class.java).convention(false) diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/TestsExecutionReportPlugin.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/TestsExecutionReportPlugin.kt index c1440cd..ac2c109 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/TestsExecutionReportPlugin.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/TestsExecutionReportPlugin.kt @@ -51,6 +51,11 @@ class TestsExecutionReportPlugin : Plugin { .set(createTestsExecutionReportExtension.getFormats().getMermaid().outputLocation) task.shiftTimestampsToStartOfDay.set(createTestsExecutionReportExtension.shiftTimestampsToStartOfDay) - task.getMark().maxEndTimeOfPreviousRuns.set(createTestsExecutionReportExtension.getMark().maxEndTimeOfPreviousRuns) + task.getMarks().getTotalTimeOfAllTests().enabled.set( + createTestsExecutionReportExtension.getMarks().getTotalTimeOfAllTests().enabled + ) + task.getMarks().getTotalTimeOfAllTests().name.set( + createTestsExecutionReportExtension.getMarks().getTotalTimeOfAllTests().name + ) } } diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/config/Mark.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/config/Mark.kt index 1236cc1..bd12e34 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/config/Mark.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/config/Mark.kt @@ -8,5 +8,8 @@ import javax.inject.Inject abstract class Mark @Inject constructor(objectFactory: ObjectFactory) { @get:Input - val maxEndTimeOfPreviousRuns: Property = objectFactory.property(Boolean::class.java).convention(false) + val enabled: Property = objectFactory.property(Boolean::class.java).convention(false) + + @get:Input + val name: Property = objectFactory.property(String::class.java).convention("") } diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/config/Marks.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/config/Marks.kt new file mode 100644 index 0000000..2a336b2 --- /dev/null +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/config/Marks.kt @@ -0,0 +1,16 @@ +package io.github.platan.tests_execution_chart.config + +import org.gradle.api.Action +import org.gradle.api.model.ObjectFactory +import org.gradle.api.tasks.Nested +import javax.inject.Inject + +abstract class Marks @Inject constructor(objectFactory: ObjectFactory) { + + @Nested + abstract fun getTotalTimeOfAllTests(): Mark + + open fun config(action: Action) { + action.execute(getTotalTimeOfAllTests()) + } +} diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/report/Mark.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/report/Mark.kt new file mode 100644 index 0000000..27c012f --- /dev/null +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/report/Mark.kt @@ -0,0 +1,9 @@ +package io.github.platan.tests_execution_chart.report + +import kotlinx.serialization.Serializable + +@Serializable +data class Mark( + var name: String, + var timestamp: Long +) diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReport.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReport.kt index 62629eb..01314a2 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReport.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReport.kt @@ -7,7 +7,10 @@ import java.time.ZoneId import java.time.temporal.ChronoUnit @Serializable -data class TestExecutionScheduleReport(val results: List) { +data class TestExecutionScheduleReport(val results: List, val marks: List = emptyList()) { + + constructor(results: List) : this(results, emptyList()) + fun timestampsShiftedToStartOfDay(zoneId: ZoneId): TestExecutionScheduleReport { return when { results.isEmpty() -> this @@ -19,4 +22,11 @@ data class TestExecutionScheduleReport(val results: List) { } } } + + fun addTotalTimeOfAllTestsMark(markName: String): TestExecutionScheduleReport { + val minStartTime = results.minBy { it.startTime }.startTime + val totalDurationOfAllTestsMs = results.sumOf { it.durationMs } + val totalTimeOfAllTestsMark = minStartTime + totalDurationOfAllTestsMs + return this.copy(marks = listOf(Mark(markName, totalTimeOfAllTestsMark))) + } } diff --git a/src/test/groovy/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReportMarksTest.groovy b/src/test/groovy/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReportMarksTest.groovy new file mode 100644 index 0000000..6bd7e60 --- /dev/null +++ b/src/test/groovy/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReportMarksTest.groovy @@ -0,0 +1,28 @@ +package io.github.platan.tests_execution_chart.report + +import spock.lang.Specification + +import java.time.Instant + +class TestExecutionScheduleReportMarksTest extends Specification { + + def "add mark with total time of all tests when report has many entries"() { + given: + def report = new TestExecutionScheduleReport([ + new TimedTestResult('class', 'test', toEpochMilli('2023-03-10T19:00:02Z'), toEpochMilli('2023-03-10T19:00:06Z'), 'passed'), + new TimedTestResult('class', 'test', toEpochMilli('2023-03-10T19:00:03Z'), toEpochMilli('2023-03-10T19:00:07Z'), 'passed'), + ]) + + when: + def resultWithMarks = report.addTotalTimeOfAllTestsMark('total time of all tests') + + then: + resultWithMarks.results == report.results + resultWithMarks.marks == [new Mark('total time of all tests', toEpochMilli('2023-03-10T19:00:10Z'))] + } + + + private static long toEpochMilli(String instant) { + Instant.parse(instant).toEpochMilli() + } +} From 05b170a59fde367cdc56160bd655274813fcce04 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Wed, 24 May 2023 17:51:56 +0200 Subject: [PATCH 10/23] Shift timestamps in marks --- .../io/github/platan/tests_execution_chart/report/Mark.kt | 7 ++++++- .../report/TestExecutionScheduleReport.kt | 5 ++++- .../report/TestExecutionScheduleReportTest.groovy | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/report/Mark.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/report/Mark.kt index 27c012f..8cad591 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/report/Mark.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/report/Mark.kt @@ -1,9 +1,14 @@ package io.github.platan.tests_execution_chart.report import kotlinx.serialization.Serializable +import java.time.Duration @Serializable data class Mark( var name: String, var timestamp: Long -) +) { + fun shiftTimestamps(timeShift: Duration): Mark { + return this.copy(timestamp = this.timestamp + timeShift.toMillis()) + } +} diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReport.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReport.kt index 01314a2..500ed08 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReport.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReport.kt @@ -18,7 +18,10 @@ data class TestExecutionScheduleReport(val results: List, val m val minStartTime = Instant.ofEpochMilli(results.minBy { it.startTime }.startTime) val targetMinStartTime = minStartTime.atZone(zoneId).truncatedTo(ChronoUnit.DAYS).toInstant() val timeShift = Duration.between(minStartTime, targetMinStartTime) - return TestExecutionScheduleReport(results.map { it.shiftTimestamps(timeShift) }) + return TestExecutionScheduleReport( + results.map { it.shiftTimestamps(timeShift) }, + marks.map { it.shiftTimestamps(timeShift) } + ) } } } diff --git a/src/test/groovy/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReportTest.groovy b/src/test/groovy/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReportTest.groovy index 3764533..d62dc52 100644 --- a/src/test/groovy/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReportTest.groovy +++ b/src/test/groovy/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReportTest.groovy @@ -12,7 +12,7 @@ class TestExecutionScheduleReportTest extends Specification { def report = new TestExecutionScheduleReport([ new TimedTestResult('class', 'test', toEpochMilli('2023-03-10T19:00:02Z'), toEpochMilli('2023-03-10T19:00:05Z'), 'passed'), new TimedTestResult('class', 'test', toEpochMilli('2023-03-10T19:00:03Z'), toEpochMilli('2023-03-10T19:00:08Z'), 'passed'), - ]) + ], [new Mark('mark1', toEpochMilli('2023-03-10T19:00:05Z'))]) when: def shiftedResult = report.timestampsShiftedToStartOfDay(ZoneOffset.ofHours(0)) @@ -21,7 +21,7 @@ class TestExecutionScheduleReportTest extends Specification { shiftedResult == new TestExecutionScheduleReport([ new TimedTestResult('class', 'test', toEpochMilli('2023-03-10T00:00:00Z'), toEpochMilli('2023-03-10T00:00:03Z'), 'passed'), new TimedTestResult('class', 'test', toEpochMilli('2023-03-10T00:00:01Z'), toEpochMilli('2023-03-10T00:00:06Z'), 'passed'), - ]) + ], [new Mark('mark1', toEpochMilli('2023-03-10T00:00:03Z'))]) } def "shift timestamps when report has one entry"() { From a45a76d5ef44157dfb0b76d0d13c3d52f7d5b2d9 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Wed, 24 May 2023 17:53:08 +0200 Subject: [PATCH 11/23] Remove unused param --- .../io/github/platan/tests_execution_chart/config/Marks.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/config/Marks.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/config/Marks.kt index 2a336b2..adb559f 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/config/Marks.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/config/Marks.kt @@ -1,11 +1,9 @@ package io.github.platan.tests_execution_chart.config import org.gradle.api.Action -import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.Nested -import javax.inject.Inject -abstract class Marks @Inject constructor(objectFactory: ObjectFactory) { +abstract class Marks { @Nested abstract fun getTotalTimeOfAllTests(): Mark From f859e38aec7cc14da47cfae7bbb40223a6bc65c1 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Wed, 24 May 2023 19:07:08 +0200 Subject: [PATCH 12/23] Support marks in TestExecutionMermaidDiagramFormatter --- .../mermaid/TestExecutionMermaidDiagramFormatter.kt | 3 +++ .../mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatter.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatter.kt index e8e5d46..577eb11 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatter.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatter.kt @@ -22,6 +22,9 @@ class TestExecutionMermaidDiagramFormatter { ) } } + report.marks.forEach { mark -> + diagramBuilder.addMilestone(mark.name, mark.timestamp) + } val diagram = diagramBuilder.build("YYYY-MM-DDTHH:mm:ss.SSSZZ", "%H:%M:%S.%L") return MermaidGanttDiagramFormatter().format(diagram, "yyyy-MM-dd'T'HH:mm:ss.SSSZ") } diff --git a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy index 73217b7..b66ca72 100644 --- a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy +++ b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy @@ -1,5 +1,6 @@ package io.github.platan.tests_execution_chart.reporters.mermaid +import io.github.platan.tests_execution_chart.report.Mark import io.github.platan.tests_execution_chart.report.TestExecutionScheduleReportBuilder import spock.lang.Specification @@ -15,9 +16,11 @@ class TestExecutionMermaidDiagramFormatterSpec extends Specification { reportBuilder.add('Test1', 'test1', 1681402397000, 1681402397100, 'SUCCESS') reportBuilder.add('Test1', 'test2', 1681402397100, 1681402397300, 'SUCCESS') reportBuilder.add('Test2', 'test1', 1681402397000, 1681402397100, 'SUCCESS') + def results = reportBuilder.getResults() + def report = results.copy(results.results, [new Mark('mark1', 1681402397400)]) when: - def mermaidReport = new TestExecutionMermaidDiagramFormatter().format(reportBuilder.getResults()) + def mermaidReport = new TestExecutionMermaidDiagramFormatter().format(report) def indent = """gantt @@ -28,6 +31,7 @@ test1 - 100 ms :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+02 test2 - 200 ms :active, 2023-04-13T18:13:17.100+0200, 2023-04-13T18:13:17.300+0200 section Test2 test1 - 100 ms :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+0200 +mark1 : milestone, 2023-04-13T18:13:17.400+0200, 0 """ then: mermaidReport == indent From 23869d4af8ffd4b810f56d5cbdd18d55168b6147 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Thu, 25 May 2023 21:06:09 +0200 Subject: [PATCH 13/23] Add test for TestExecutionMermaidDiagramFormatter without marks --- ...xecutionMermaidDiagramFormatterSpec.groovy | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy index b66ca72..7e1622d 100644 --- a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy +++ b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatterSpec.groovy @@ -8,7 +8,37 @@ import java.time.ZoneOffset class TestExecutionMermaidDiagramFormatterSpec extends Specification { - def "should format report"() { + def "should format report with test results"() { + given: + def getDefault = TimeZone.getDefault() + TimeZone.setDefault(SimpleTimeZone.getTimeZone(ZoneOffset.ofHours(2))) + def reportBuilder = new TestExecutionScheduleReportBuilder() + reportBuilder.add('Test1', 'test1', 1681402397000, 1681402397100, 'SUCCESS') + reportBuilder.add('Test1', 'test2', 1681402397100, 1681402397300, 'SUCCESS') + reportBuilder.add('Test2', 'test1', 1681402397000, 1681402397100, 'SUCCESS') + def report = reportBuilder.getResults() + + when: + def mermaidReport = new TestExecutionMermaidDiagramFormatter().format(report) + + + def indent = """gantt +dateFormat YYYY-MM-DDTHH:mm:ss.SSSZZ +axisFormat %H:%M:%S.%L +section Test1 +test1 - 100 ms :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+0200 +test2 - 200 ms :active, 2023-04-13T18:13:17.100+0200, 2023-04-13T18:13:17.300+0200 +section Test2 +test1 - 100 ms :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+0200 +""" + then: + mermaidReport == indent + + cleanup: + TimeZone.setDefault(getDefault) + } + + def "should format report with test results and marks"() { given: def getDefault = TimeZone.getDefault() TimeZone.setDefault(SimpleTimeZone.getTimeZone(ZoneOffset.ofHours(2))) From 263a8802adee0af8f2cbc24646979b598f10eea6 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Thu, 25 May 2023 21:34:52 +0200 Subject: [PATCH 14/23] Add mark to report --- .../groovy/ReportsFunctionalTest.groovy | 8 ++++++++ .../CreateTestsExecutionReportTask.kt | 11 +++++++---- .../platan/tests_execution_chart/config/Mark.kt | 4 ++-- .../platan/tests_execution_chart/config/Marks.kt | 4 ++-- .../config/TotalTimeOfAllTestsMark.kt | 7 +++++++ 5 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 src/main/kotlin/io/github/platan/tests_execution_chart/config/TotalTimeOfAllTestsMark.kt diff --git a/src/functionalTest/groovy/ReportsFunctionalTest.groovy b/src/functionalTest/groovy/ReportsFunctionalTest.groovy index 27fca37..bbcbee8 100644 --- a/src/functionalTest/groovy/ReportsFunctionalTest.groovy +++ b/src/functionalTest/groovy/ReportsFunctionalTest.groovy @@ -34,6 +34,11 @@ class ReportsFunctionalTest extends Specification { json { enabled = true } mermaid { enabled = true } } + marks { + totalTimeOfAllTests { + enabled = true + } + } } repositories { mavenCentral() @@ -72,6 +77,9 @@ class ReportsFunctionalTest extends Specification { mermaidFile.exists() jsonFile.exists() htmlFile.exists() + + and: + mermaidFile.text.contains 'total time of all tests : milestone, ' } def "should replace special characters in mermaid graph test names"() { diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/CreateTestsExecutionReportTask.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/CreateTestsExecutionReportTask.kt index 0e2c728..d234495 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/CreateTestsExecutionReportTask.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/CreateTestsExecutionReportTask.kt @@ -79,10 +79,13 @@ abstract class CreateTestsExecutionReportTask @Inject constructor(objectFactory: } private fun adjustResults(results: TestExecutionScheduleReport): TestExecutionScheduleReport { - return if (shiftTimestampsToStartOfDay.get()) { - results.timestampsShiftedToStartOfDay(ZoneId.systemDefault()) - } else { - results + var adjusted = results + if (shiftTimestampsToStartOfDay.get()) { + adjusted = results.timestampsShiftedToStartOfDay(ZoneId.systemDefault()) + } + if (getMarks().getTotalTimeOfAllTests().enabled.get()) { + adjusted = adjusted.addTotalTimeOfAllTestsMark(getMarks().getTotalTimeOfAllTests().name.get()) } + return adjusted } } diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/config/Mark.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/config/Mark.kt index bd12e34..41c5dcd 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/config/Mark.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/config/Mark.kt @@ -5,11 +5,11 @@ import org.gradle.api.provider.Property import org.gradle.api.tasks.Input import javax.inject.Inject -abstract class Mark @Inject constructor(objectFactory: ObjectFactory) { +abstract class Mark @Inject constructor(objectFactory: ObjectFactory, name: String) { @get:Input val enabled: Property = objectFactory.property(Boolean::class.java).convention(false) @get:Input - val name: Property = objectFactory.property(String::class.java).convention("") + val name: Property = objectFactory.property(String::class.java).convention(name) } diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/config/Marks.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/config/Marks.kt index adb559f..0b076a2 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/config/Marks.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/config/Marks.kt @@ -6,9 +6,9 @@ import org.gradle.api.tasks.Nested abstract class Marks { @Nested - abstract fun getTotalTimeOfAllTests(): Mark + abstract fun getTotalTimeOfAllTests(): TotalTimeOfAllTestsMark - open fun config(action: Action) { + open fun totalTimeOfAllTests(action: Action) { action.execute(getTotalTimeOfAllTests()) } } diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/config/TotalTimeOfAllTestsMark.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/config/TotalTimeOfAllTestsMark.kt new file mode 100644 index 0000000..a107967 --- /dev/null +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/config/TotalTimeOfAllTestsMark.kt @@ -0,0 +1,7 @@ +package io.github.platan.tests_execution_chart.config + +import org.gradle.api.model.ObjectFactory +import javax.inject.Inject + +abstract class TotalTimeOfAllTestsMark @Inject constructor(objectFactory: ObjectFactory) : + Mark(objectFactory, "total time of all tests") From 5e2a9524cfc2ae035e3d8d5941eee5956767c9f5 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Thu, 25 May 2023 21:41:26 +0200 Subject: [PATCH 15/23] Add mark to visual regression --- src/functionalTest/resources/report-visual-regression.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/functionalTest/resources/report-visual-regression.json b/src/functionalTest/resources/report-visual-regression.json index 21bd152..2afa8c9 100644 --- a/src/functionalTest/resources/report-visual-regression.json +++ b/src/functionalTest/resources/report-visual-regression.json @@ -80,5 +80,11 @@ "resultType": "SUCCESS", "testName": "test 3" } + ], + "marks": [ + { + "timestamp": 1679338714982, + "name": "total time of all tests" + } ] } \ No newline at end of file From 5c90a47933d0ad820055e5f4147d4be2b1659db9 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Thu, 25 May 2023 21:41:53 +0200 Subject: [PATCH 16/23] Add totalTimeOfAllTests mark to sample project --- test-projects/spock-single-module/build.gradle | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test-projects/spock-single-module/build.gradle b/test-projects/spock-single-module/build.gradle index 5bceea1..0f16a23 100644 --- a/test-projects/spock-single-module/build.gradle +++ b/test-projects/spock-single-module/build.gradle @@ -26,7 +26,7 @@ createTestsExecutionReport { enabled = true script { config { - maxTextSize = 990 + maxTextSize = 2000 } src = 'https://cdn.jsdelivr.net/npm/mermaid@8.13.3/dist/mermaid.js' } @@ -34,4 +34,10 @@ createTestsExecutionReport { json { enabled = true } mermaid { enabled = true } } + marks { + totalTimeOfAllTests { + enabled = true + name = 'total time of all tests' + } + } } From e5e81b500ae269d544f45e68193f4292563b6205 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Tue, 30 May 2023 21:31:10 +0200 Subject: [PATCH 17/23] Allow # in reports --- .../mermaid/MermaidGanttDiagramFormatter.kt | 5 ++-- .../MermaidGanttDiagramFormatterTest.groovy | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt index 59a8664..e96bd30 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt @@ -39,10 +39,11 @@ internal class MermaidGanttDiagramFormatter { private fun escape(str: String): String { return str - // remove # before replacing other characters with entity containing # - .replace("#", "") + // warning: order of replacements below matters // replace ; before replacing other characters with entity containing ; .replace(";", "#semi;") + // replace # but not in #semi; + .replace(Regex("#(?!semi;)"), "#35;") .replace(":", "#colon;") // https://github.com/mermaid-js/mermaid/issues/742 } } diff --git a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy index d84810e..6a8e83d 100644 --- a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy +++ b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy @@ -43,4 +43,33 @@ milestone2 : milestone, 2023-04-13T18:13:17.400+0200, 0 cleanup: TimeZone.setDefault(getDefault) } + + def "should format report with special characters"() { + given: + def getDefault = TimeZone.getDefault() + TimeZone.setDefault(SimpleTimeZone.getTimeZone(ZoneOffset.ofHours(2))) + def diagramBuilder = new MermaidGanttDiagram.MermaidGanttDiagramBuilder() + diagramBuilder.addSection('Test # ; : 1') + diagramBuilder.addTask('test # ; : 1', 'active', 1681402397000, 1681402397100) + diagramBuilder.addMilestone('milestone # ; : 1', 1681402397100) + + MermaidGanttDiagram diagram = diagramBuilder.build("YYYY-MM-DDTHH:mm:ss.SSSZZ", "%H:%M:%S.%L") + + when: + def mermaidReport = new MermaidGanttDiagramFormatter().format(diagram, "yyyy-MM-dd'T'HH:mm:ss.SSSZ") + + + def indent = """gantt +dateFormat YYYY-MM-DDTHH:mm:ss.SSSZZ +axisFormat %H:%M:%S.%L +section Test #35; #semi; #colon; 1 +test #35; #semi; #colon; 1 :active, 2023-04-13T18:13:17.000+0200, 2023-04-13T18:13:17.100+0200 +milestone #35; #semi; #colon; 1 : milestone, 2023-04-13T18:13:17.100+0200, 0 +""" + then: + mermaidReport == indent + + cleanup: + TimeZone.setDefault(getDefault) + } } From 8d515e4c26e68a0816b5784b576182c989cf15e8 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Tue, 30 May 2023 21:35:02 +0200 Subject: [PATCH 18/23] Introduce mermaid.core package --- .../MermaidGanttDiagramFormatterToSvgConversionSpec.groovy | 2 ++ .../reporters/mermaid/TestExecutionMermaidDiagramFormatter.kt | 2 ++ .../reporters/mermaid/{ => core}/MermaidGanttDiagram.kt | 2 +- .../mermaid/{ => core}/MermaidGanttDiagramFormatter.kt | 2 +- .../mermaid/{ => core}/MermaidGanttDiagramFormatterTest.groovy | 2 +- 5 files changed, 7 insertions(+), 3 deletions(-) rename src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/{ => core}/MermaidGanttDiagram.kt (99%) rename src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/{ => core}/MermaidGanttDiagramFormatter.kt (99%) rename src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/{ => core}/MermaidGanttDiagramFormatterTest.groovy (99%) diff --git a/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy b/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy index 3033125..f5c837d 100644 --- a/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy +++ b/src/functionalTest/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterToSvgConversionSpec.groovy @@ -1,5 +1,7 @@ package io.github.platan.tests_execution_chart.reporters.mermaid +import io.github.platan.tests_execution_chart.reporters.mermaid.core.MermaidGanttDiagram +import io.github.platan.tests_execution_chart.reporters.mermaid.core.MermaidGanttDiagramFormatter import spock.lang.Retry import spock.lang.Specification import spock.lang.TempDir diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatter.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatter.kt index 577eb11..3104140 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatter.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/TestExecutionMermaidDiagramFormatter.kt @@ -1,6 +1,8 @@ package io.github.platan.tests_execution_chart.reporters.mermaid import io.github.platan.tests_execution_chart.report.TestExecutionScheduleReport +import io.github.platan.tests_execution_chart.reporters.mermaid.core.MermaidGanttDiagram +import io.github.platan.tests_execution_chart.reporters.mermaid.core.MermaidGanttDiagramFormatter class TestExecutionMermaidDiagramFormatter { diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagram.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagram.kt similarity index 99% rename from src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagram.kt rename to src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagram.kt index e22494e..3b8f27f 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagram.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagram.kt @@ -1,4 +1,4 @@ -package io.github.platan.tests_execution_chart.reporters.mermaid +package io.github.platan.tests_execution_chart.reporters.mermaid.core data class MermaidGanttDiagram( val dateFormat: String, diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagramFormatter.kt similarity index 99% rename from src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt rename to src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagramFormatter.kt index e96bd30..fe561b3 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatter.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagramFormatter.kt @@ -1,4 +1,4 @@ -package io.github.platan.tests_execution_chart.reporters.mermaid +package io.github.platan.tests_execution_chart.reporters.mermaid.core import java.time.Instant import java.time.ZoneId diff --git a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagramFormatterTest.groovy similarity index 99% rename from src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy rename to src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagramFormatterTest.groovy index 6a8e83d..e29e33d 100644 --- a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/MermaidGanttDiagramFormatterTest.groovy +++ b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagramFormatterTest.groovy @@ -1,4 +1,4 @@ -package io.github.platan.tests_execution_chart.reporters.mermaid +package io.github.platan.tests_execution_chart.reporters.mermaid.core import spock.lang.Specification From 8454bea96ce427f9d559db35218eadbb0493fc44 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Tue, 30 May 2023 23:11:25 +0200 Subject: [PATCH 19/23] Fix test - verify #35; in mermaid --- src/functionalTest/groovy/ReportsFunctionalTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/functionalTest/groovy/ReportsFunctionalTest.groovy b/src/functionalTest/groovy/ReportsFunctionalTest.groovy index bbcbee8..e9da80e 100644 --- a/src/functionalTest/groovy/ReportsFunctionalTest.groovy +++ b/src/functionalTest/groovy/ReportsFunctionalTest.groovy @@ -141,7 +141,7 @@ class ReportsFunctionalTest extends Specification { def mermaidGraph = new File("$projectDirRealPath/build/reports/tests-execution/mermaid/test.txt").text !mermaidGraph.contains("test with # character") !mermaidGraph.contains("test with : character") - mermaidGraph.contains("test with character") + mermaidGraph.contains("test with #35; character") mermaidGraph.contains("test with #colon; character") } From 20b76b1ef263fc9319e46ade7895ca507beec619 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Wed, 31 May 2023 21:12:39 +0200 Subject: [PATCH 20/23] exit with error on empty mark name --- .../groovy/ReportsFunctionalTest.groovy | 40 +++++++++++++++++-- .../TestsExecutionReportPlugin.kt | 6 +-- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/functionalTest/groovy/ReportsFunctionalTest.groovy b/src/functionalTest/groovy/ReportsFunctionalTest.groovy index e9da80e..c32d448 100644 --- a/src/functionalTest/groovy/ReportsFunctionalTest.groovy +++ b/src/functionalTest/groovy/ReportsFunctionalTest.groovy @@ -129,10 +129,10 @@ class ReportsFunctionalTest extends Specification { when: def result = GradleRunner.create() - .withProjectDir(testProjectDir) - .withArguments('test', 'createTestsExecutionReport') - .withPluginClasspath() - .build() + .withProjectDir(testProjectDir) + .withArguments('test', 'createTestsExecutionReport') + .withPluginClasspath() + .build() then: result.task(":createTestsExecutionReport").outcome == SUCCESS @@ -221,6 +221,38 @@ class ReportsFunctionalTest extends Specification { !new File("$projectDirRealPath/build/reports/tests-execution/").exists() } + def "exit with error on empty mark name"() { + given: + settingsFile << "rootProject.name = 'hello-world'" + buildFile << """ + plugins { + id 'groovy' + id 'io.github.platan.tests-execution-chart' + } + createTestsExecutionReport { + marks { + totalTimeOfAllTests { + name = '' + } + } + } + """ + + when: + def result = GradleRunner.create() + .withProjectDir(testProjectDir) + .withArguments('createTestsExecutionReport') + .withPluginClasspath() + .buildAndFail() + + then: + result.output.contains("marks.totalTimeOfAllTests.name cannot be blank") + result.output.contains('BUILD FAILED') + + and: + !new File("$projectDirRealPath/build/reports/tests-execution/").exists() + } + // @TempDir creates directories in /var, but on macOS /var is a link to /private/var // so we have to use toRealPath to get a real path which is logged private Path getProjectDirRealPath() { diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/TestsExecutionReportPlugin.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/TestsExecutionReportPlugin.kt index ac2c109..78b1910 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/TestsExecutionReportPlugin.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/TestsExecutionReportPlugin.kt @@ -54,8 +54,8 @@ class TestsExecutionReportPlugin : Plugin { task.getMarks().getTotalTimeOfAllTests().enabled.set( createTestsExecutionReportExtension.getMarks().getTotalTimeOfAllTests().enabled ) - task.getMarks().getTotalTimeOfAllTests().name.set( - createTestsExecutionReportExtension.getMarks().getTotalTimeOfAllTests().name - ) + val name = createTestsExecutionReportExtension.getMarks().getTotalTimeOfAllTests().name.get() + require(name.isNotBlank()) { "marks.totalTimeOfAllTests.name cannot be blank" } + task.getMarks().getTotalTimeOfAllTests().name.set(name) } } From cc17e352c4be371f660be302c1f6298745323795 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Thu, 1 Jun 2023 20:52:05 +0200 Subject: [PATCH 21/23] Remove default value of param in constructor --- .../tests_execution_chart/report/TestExecutionScheduleReport.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReport.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReport.kt index 500ed08..184bfa2 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReport.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/report/TestExecutionScheduleReport.kt @@ -7,7 +7,7 @@ import java.time.ZoneId import java.time.temporal.ChronoUnit @Serializable -data class TestExecutionScheduleReport(val results: List, val marks: List = emptyList()) { +data class TestExecutionScheduleReport(val results: List, val marks: List) { constructor(results: List) : this(results, emptyList()) From 20c8a3c33e5b42904e5e8a1c3f94e276374b0e66 Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Thu, 1 Jun 2023 21:06:24 +0200 Subject: [PATCH 22/23] Throw exception on empty name of task, section or mark --- .../mermaid/core/MermaidGanttDiagram.kt | 20 +++++++-- .../MermaidGanttDiagramBuilderTest.groovy | 42 +++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagramBuilderTest.groovy diff --git a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagram.kt b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagram.kt index 3b8f27f..a3233ac 100644 --- a/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagram.kt +++ b/src/main/kotlin/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagram.kt @@ -6,9 +6,23 @@ data class MermaidGanttDiagram( val entries: List ) { sealed interface Entry - data class Section(val name: String) : Entry - data class Task(val name: String, val type: String?, val start: Long, val end: Long) : Entry - data class Milestone(val name: String, val timestamp: Long) : Entry + data class Section(val name: String) : Entry { + init { + require(name.isNotBlank()) { "Section name cannot be blank" } + } + } + + data class Task(val name: String, val type: String?, val start: Long, val end: Long) : Entry { + init { + require(name.isNotBlank()) { "Task name cannot be blank" } + } + } + + data class Milestone(val name: String, val timestamp: Long) : Entry { + init { + require(name.isNotBlank()) { "Mark name cannot be blank" } + } + } class MermaidGanttDiagramBuilder { private val entries: MutableList = mutableListOf() diff --git a/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagramBuilderTest.groovy b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagramBuilderTest.groovy new file mode 100644 index 0000000..d5f39d0 --- /dev/null +++ b/src/test/groovy/io/github/platan/tests_execution_chart/reporters/mermaid/core/MermaidGanttDiagramBuilderTest.groovy @@ -0,0 +1,42 @@ +package io.github.platan.tests_execution_chart.reporters.mermaid.core + +import spock.lang.Specification + +class MermaidGanttDiagramBuilderTest extends Specification { + + def "should return error for blank mark name"() { + when: + new MermaidGanttDiagram.MermaidGanttDiagramBuilder().addMilestone(name, 0) + + then: + def e = thrown(IllegalArgumentException) + e.message == 'Mark name cannot be blank' + + where: + name << ['', ' '] + } + + def "should return error for blank task name"() { + when: + new MermaidGanttDiagram.MermaidGanttDiagramBuilder().addTask(name, 'active', 0, 1) + + then: + def e = thrown(IllegalArgumentException) + e.message == 'Task name cannot be blank' + + where: + name << ['', ' '] + } + + def "should return error for blank section name"() { + when: + new MermaidGanttDiagram.MermaidGanttDiagramBuilder().addSection(name) + + then: + def e = thrown(IllegalArgumentException) + e.message == 'Section name cannot be blank' + + where: + name << ['', ' '] + } +} From d4da5ef1e6355ac92c8c7ad93d2d551311c6cabd Mon Sep 17 00:00:00 2001 From: Marcin Mielnicki Date: Thu, 1 Jun 2023 21:13:20 +0200 Subject: [PATCH 23/23] Update changelog --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 2ee012a..ebebe4e 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,14 @@ Gradle can generate reports in JUnit XML format. But such reports cannot be used ## Unreleased +### Added + +- A new option `marks.totalTimeOfAllTests` allows to add mark showing total time of all tests + +### Changed + +- Do not remove `#` character from names of tasks/sections + ## 0.3.1 (29 March 2023) ### Added