diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..5c977d9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +jdk: + - oraclejdk8 + - oraclejdk7 + - openjdk6 + +script: +- ./gradlew clean build \ No newline at end of file diff --git a/README.md b/README.md index b9eab70..4ee8c91 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,79 @@ +[![Build Status](https://travis-ci.org/marcingrzejszczak/gradle-test-profiler.svg)](https://travis-ci.org/marcingrzejszczak/gradle-test-profiler) + # gradle-test-profiler -## How to add it +Created with @AChudzik + +## Since version 0.1.0 + +### How to add it + +You have to add `jcenter` to buildscript repositories + +``` + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.blogspot.toomuchcoding:gradle-test-profiler:0.1.0' + } +} + +apply plugin: 'com.blogspot.toomuchcoding.testprofiler' + +``` + + +### How to run it + +It's enough to execute + +``` +./gradlew clean profileTests + +``` + + +### How to configure it + +You have a special section called `testprofiler` + +``` +testprofiler { + + // Separator of columns in the output report + separator = '\t' + + // Headers in the report + outputReportHeaders = "module${separator}test class name${separator}test name${separator}test execution time in [s]${separator}test class execution time in [s]\n" + + // Closure that will be converted to a Comparator to compare row entries + comparator = DefaultTestExecutionComparator.DEFAULT_TEST_EXECUTION_COMPARATOR + + // Closure that converts a reporter row entry to a single String + rowFromReport = ReportStorer.DEFAULT_ROW_FROM_REPORT_CONVERTER + + // Base directory where reports will be gathered. The parent of this directory is build dir of the project + reportOutputDir = "reports/test_profiling" + + // Filename of a single report + reportOutputCsvFilename = "testsProfile.csv" + + // Base directory where merged summary of reports will be kept. The parent of directory is the top root project dir + mergedSummaryDir = "reports/test_profiling" + + // Filename of a merged summary of reports + mergedSummaryFileName = "summary.csv" +} + +``` + + +## Deprecated (up till version 0.0.4) + +### How to add it For the time being just enter in your project @@ -10,7 +83,7 @@ if (project.hasProperty('testsProfiling')) { } ``` -## How to run it? +### How to run it? Execute diff --git a/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/ProfiledTest.groovy b/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/ProfiledTest.groovy index 166c5e9..0793ba3 100644 --- a/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/ProfiledTest.groovy +++ b/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/ProfiledTest.groovy @@ -2,6 +2,7 @@ package com.blogspot.toomuchcoding.testprofiler import groovy.transform.CompileStatic import groovy.transform.PackageScope import groovy.util.logging.Slf4j +import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.testing.Test import java.util.concurrent.ConcurrentHashMap @@ -12,6 +13,8 @@ import java.util.concurrent.ConcurrentHashMap class ProfiledTest extends Test { TestProfilerPluginExtension testProfilerPluginExtension + @OutputDirectory File reportDir + @OutputDirectory File mergedTestProfilingSummaryDir ProfiledTest() { Set testExecutionResults = Collections.newSetFromMap(new ConcurrentHashMap()) @@ -22,7 +25,7 @@ class ProfiledTest extends Test { private Closure storeReport(Set testExecutionResults) { return { log.debug("Stored results are $testExecutionResults") - new ReportStorer(testProfilerPluginExtension, project).storeReport(testExecutionResults) + new ReportStorer(getTestProfilerPluginExtension(), project, getReportDir(), getMergedTestProfilingSummaryDir()).storeReport(testExecutionResults) } } diff --git a/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/ReportMerger.groovy b/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/ReportMerger.groovy index c03b642..13b4465 100644 --- a/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/ReportMerger.groovy +++ b/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/ReportMerger.groovy @@ -1,9 +1,42 @@ package com.blogspot.toomuchcoding.testprofiler - -import groovy.transform.PackageScope import groovy.transform.CompileStatic +import groovy.transform.PackageScope +import groovy.util.logging.Slf4j +import org.gradle.api.DefaultTask +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction @PackageScope @CompileStatic -class ReportMerger { +@Slf4j +class ReportMerger extends DefaultTask { + + TestProfilerPluginExtension testProfilerPluginExtension + @OutputDirectory File mergedTestProfilingSummaryDir + + @TaskAction + void testsProfileSummaryReport() { + getMergedTestProfilingSummaryDir().mkdirs() + File mergedTestProfilingSummary = new File(getMergedTestProfilingSummaryDir(), getTestProfilerPluginExtension().mergedSummaryFileName) + log.debug("Will store merged test profiling summary in [${mergedTestProfilingSummary}]") + String fileContent = mergedTestProfilingSummary.text + log.debug("Saving file [$mergedTestProfilingSummary] content [$fileContent]") + mergedTestProfilingSummary.text = getTestProfilerPluginExtension().outputReportHeaders + Set reportRows = new TreeSet(getTestProfilerPluginExtension().comparator as Comparator) + appendReportRow(fileContent, reportRows) + mergedTestProfilingSummary << reportRows.collect(rowFromReport()).join('\n') + println "Your combined report is available here [$mergedTestProfilingSummary]" + } + + private void appendReportRow(String fileContent, Set reportRows) { + fileContent.split('\n').findAll { !it.contains(getTestProfilerPluginExtension().getOutputReportHeaders()) }.each { String string -> + String[] row = string.split(getTestProfilerPluginExtension().separator) + log.debug("Converting row $row") + reportRows << new ReportRow(row[0], new TestExecutionResult(row[1], row[2], row[3] as Double), row[4] as Double) + } + } + + Closure rowFromReport() { + return getTestProfilerPluginExtension().rowFromReport.curry(getTestProfilerPluginExtension()) + } } diff --git a/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/ReportStorer.groovy b/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/ReportStorer.groovy index 0764000..c5f6f5e 100644 --- a/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/ReportStorer.groovy +++ b/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/ReportStorer.groovy @@ -16,10 +16,18 @@ class ReportStorer { private final TestProfilerPluginExtension testProfilerPluginExtension private final Project project + private final File reportDir + private final File mergedTestProfilingSummaryDir - ReportStorer(TestProfilerPluginExtension testProfilerPluginExtension, Project project) { + ReportStorer(TestProfilerPluginExtension testProfilerPluginExtension, Project project, File reportDir, File mergedTestProfilingSummaryDir) { this.testProfilerPluginExtension = testProfilerPluginExtension this.project = project + this.reportDir = reportDir + this.mergedTestProfilingSummaryDir = mergedTestProfilingSummaryDir + } + + ReportStorer(TestProfilerPluginExtension testProfilerPluginExtension) { + this.testProfilerPluginExtension = testProfilerPluginExtension } public void storeReport(Set testExecutionResults) { @@ -36,10 +44,10 @@ class ReportStorer { } private void appendTestExecutionResultToMergedTestSummary(String testExecutionResult) { - File mergedTestProfilingSummaryDir = new File(testProfilerPluginExtension.mergedSummaryDir) mergedTestProfilingSummaryDir.mkdirs() - File mergedTestProfilingSummary = new File(testProfilerPluginExtension.mergedSummaryFileName) + File mergedTestProfilingSummary = new File(mergedTestProfilingSummaryDir, testProfilerPluginExtension.mergedSummaryFileName) mergedTestProfilingSummary << testExecutionResult << '\n' + log.debug("Stored [$testExecutionResult] in [$mergedTestProfilingSummary]") } private File appendTestExecutionResultToFile(File report, String testExecutionResult) { diff --git a/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/TestProfilerPlugin.groovy b/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/TestProfilerPlugin.groovy index 99a6b44..f503289 100644 --- a/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/TestProfilerPlugin.groovy +++ b/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/TestProfilerPlugin.groovy @@ -6,10 +6,12 @@ import org.gradle.api.Task class TestProfilerPlugin implements Plugin { - @PackageScope static final String TEST_PROFILER_TASK_NAME = "testprofiler" + @PackageScope static final String TEST_PROFILER_TASK_NAME = "calculateTestExecutionTime" + @PackageScope static final String SUMMARY_REPORT_TASK_NAME = "profileTests" void apply(Project project) { TestProfilerPluginExtension extension = project.extensions.create(TEST_PROFILER_TASK_NAME, TestProfilerPluginExtension) + createSummaryReportTask(project, extension) createProfiledTestTask(project, extension) } @@ -19,6 +21,19 @@ class TestProfilerPlugin implements Plugin { task.description = "Prepares a report with execution time of your tests and performs custom logic upon profiling" task.conventionMapping.with { testProfilerPluginExtension = { extension } + reportDir = { new File(project.buildDir, extension.reportOutputDir) } + mergedTestProfilingSummaryDir = { new File(project.rootDir, extension.mergedSummaryDir) } + } + } + + private void createSummaryReportTask(Project project, TestProfilerPluginExtension extension) { + Task task = project.tasks.create(SUMMARY_REPORT_TASK_NAME, ReportMerger) + task.group = 'Verification' + task.description = "Combines the reports into a single a file" + task.dependsOn(TEST_PROFILER_TASK_NAME) + task.conventionMapping.with { + testProfilerPluginExtension = { extension } + mergedTestProfilingSummaryDir = { new File(project.rootDir, extension.mergedSummaryDir) } } } } \ No newline at end of file diff --git a/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/TestProfilerPluginExtension.groovy b/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/TestProfilerPluginExtension.groovy index 32c28c6..f6cdaa4 100644 --- a/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/TestProfilerPluginExtension.groovy +++ b/src/main/groovy/com/blogspot/toomuchcoding/testprofiler/TestProfilerPluginExtension.groovy @@ -1,15 +1,48 @@ package com.blogspot.toomuchcoding.testprofiler import groovy.transform.CompileStatic +import groovy.transform.ToString @CompileStatic +@ToString class TestProfilerPluginExtension { + /** + * Separator of columns in the output report + */ String separator = '\t' + + /** + * Headers in the report + */ String outputReportHeaders = "module${separator}test class name${separator}test name${separator}test execution time in [s]${separator}test class execution time in [s]\n" + + /** + * Closure that will be converted to a Comparator to compare row entries + */ Closure comparator = DefaultTestExecutionComparator.DEFAULT_TEST_EXECUTION_COMPARATOR + + /** + * Closure that converts a reporter row entry to a single String + */ Closure rowFromReport = ReportStorer.DEFAULT_ROW_FROM_REPORT_CONVERTER + + /** + * Base directory where reports will be gathered. The parent of this directory is build dir of the project + */ String reportOutputDir = "reports/test_profiling" + + /** + * Filename of a single report + */ String reportOutputCsvFilename = "testsProfile.csv" - String mergedSummaryDir = "build/reports/test_profiling" + + /** + * Base directory where merged summary of reports will be kept. The parent of directory is the top root project dir + */ + String mergedSummaryDir = "reports/test_profiling" + + /** + * Filename of a merged summary of reports + */ String mergedSummaryFileName = "summary.csv" }