Created
December 19, 2014 07:05
-
-
Save ithena/51c7497234e4c4cdf261 to your computer and use it in GitHub Desktop.
Generate report (incl. historical information) on test case and suite duration starting from a dir with jUnit xml test reports
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Grab(group = 'net.sf.opencsv', module = 'opencsv', version = '2.3') | |
| import groovy.io.* | |
| import groovy.json.* | |
| import au.com.bytecode.opencsv.CSVWriter | |
| dateFormat = 'dd/MM/yyyy HH:mm' | |
| String testReportsDir = '/Users/rverlind/Projects/Doccle/ap_awl_trunk_only/mci/mci-front-end/mci-euui/target/test-reports' | |
| String reportOuputDir = '/Users/rverlind/Projects/Doccle/' | |
| String reportOutputBaseName = 'euui-test-report' | |
| Date executionDate = new Date() | |
| List testReports = findAllTestReports(testReportsDir) | |
| def (testSuites, testCases) = readLatestReport(reportOuputDir, reportOutputBaseName) | |
| // Uncomment the line below if you would like to start from scratch | |
| //def (testSuites, testCases) = [[],[]] | |
| // Read all test reports one file at a time | |
| for(testReport in testReports) { | |
| testReport.withInputStream { | |
| String type = testReport.name.startsWith('TEST-functional') ? 'FUNC' : testReport.name.startsWith('TEST-integration') ? 'INTE' : 'UNIT' | |
| def rootNode = new XmlParser(false, false).parse(it) | |
| // Read the test suite execution | |
| def testSuite = findTestSuite(testSuites, type, rootNode.@name) | |
| if (!testSuite) { | |
| testSuite = new TestSuite(type: type, name: rootNode.@name) | |
| testSuites << testSuite | |
| } | |
| testSuite.executions << new SuiteExecution(time: new BigDecimal(rootNode.@time), tests: rootNode.@tests?.toInteger(), executionDate: executionDate) | |
| rootNode?.testcase?.each { testcase -> | |
| def result = findTestResult(testCases, type, testcase.@name, testcase.@classname) | |
| if (!result) { | |
| result = new TestResult(type: type, name: testcase.@name, testClass: testcase.@classname) | |
| testCases << result | |
| } | |
| result.executions << new TestExecution(executionDate: executionDate, time: new BigDecimal(testcase.@time), success: testcase.success) | |
| } | |
| } | |
| } | |
| // Write JSON to file | |
| String reportName = "${reportOutputBaseName}-${createReportNameDatePart(executionDate)}" | |
| new File("${reportOuputDir}${reportName}.json").withWriter { | |
| writeResultToJson(testSuites, testCases, executionDate).writeTo(it) | |
| } | |
| new File("${reportOuputDir}${reportName}.csv").withWriter { | |
| def rows = createCsvReportLines(testSuites, testCases) | |
| new CSVWriter(it).writeAll(rows) | |
| } | |
| class TestResult { | |
| String name | |
| String testClass | |
| String type | |
| List executions = [] | |
| String toString() { | |
| "${type}: ${name}; executions: ${executions} }" | |
| } | |
| } | |
| class TestExecution { | |
| Date executionDate | |
| BigDecimal time | |
| boolean success = true | |
| String toString() { | |
| "[${executionDate?.format("dd/MM/yyyy HH:mm")};${time};${success ? 'SUCC' : 'FAIL'}]" | |
| } | |
| } | |
| class TestSuite { | |
| String type | |
| String name | |
| List executions = [] | |
| boolean equals(TestSuite suite) { | |
| type?.equals(suite?.type) && name?.equals(suite?.name) | |
| } | |
| int hashCode() { | |
| "${type}${name}".hashCode() | |
| } | |
| String toString() { | |
| "${type} ${name}; executions: ${executions}" | |
| } | |
| } | |
| class SuiteExecution { | |
| Date executionDate | |
| BigDecimal time | |
| int tests | |
| String toString() { | |
| "[${executionDate?.format("dd/MM/yyyy HH:mm")};${time};${tests}]" | |
| } | |
| } | |
| def readLatestReport(reportOutputDir, reportOutputBaseName) { | |
| def testSuites = [] | |
| def testCases = [] | |
| File report = findLatestReport(reportOutputDir, reportOutputBaseName) | |
| if (!report) { return [[],[]] } | |
| report.withReader { | |
| def result = new JsonSlurper().parse(it) | |
| result.report.suites.each { ts -> | |
| def suite = new TestSuite(type: ts.type, name: ts.name) | |
| ts.executions.each { exec -> | |
| suite.executions << new SuiteExecution( | |
| executionDate: new Date().parse(dateFormat, exec.executionDate), | |
| time: new BigDecimal(exec.time), | |
| tests: exec.tests?.toInteger()) | |
| } | |
| testSuites << suite | |
| } | |
| result.report.tests.each { tc -> | |
| def tcase = new TestResult(type: tc.type, name: tc.name, testClass: tc.suite) | |
| tc.executions.each { exec -> | |
| tcase.executions << new TestExecution( | |
| executionDate: new Date().parse(dateFormat, exec.executionDate), | |
| time: new BigDecimal(exec.time), | |
| success: exec.success) | |
| } | |
| testCases << tcase | |
| } | |
| } | |
| [testSuites, testCases] | |
| } | |
| File findLatestReport(reportOutputDir, reportOutputBaseName) { | |
| List reports = [] | |
| new File(reportOutputDir).eachFile(FileType.FILES) { | |
| if (it.name.startsWith(reportOutputBaseName)) { | |
| reports << it | |
| } | |
| } | |
| reports = reports.sort { it.name } | |
| reports ? reports.last() : null | |
| } | |
| TestSuite findTestSuite(testSuites, type, name) { | |
| testSuites?.find { type == it?.type && name == it.name} | |
| } | |
| TestResult findTestResult(testCases, type, name, classname) { | |
| testCases?.find { type == it?.type && name == it.name && it.testClass == classname} | |
| } | |
| List findAllTestReports(String baseDir) { | |
| def tmpList = [] | |
| new File(baseDir).eachFileRecurse(FileType.FILES) { | |
| if (it.name.endsWith('.xml') && it.name.startsWith('TEST-')) { | |
| tmpList << it | |
| } | |
| } | |
| tmpList | |
| } | |
| JsonBuilder writeResultToJson(testSuites, testCases, reportDate) { | |
| def builder = new groovy.json.JsonBuilder() | |
| builder.report { | |
| creationDate reportDate.format(dateFormat) | |
| suites testSuites.collect { ts -> | |
| [type: ts.type, | |
| name: ts.name, | |
| executions: ts.executions.collect { exec -> | |
| [executionDate: exec.executionDate?.format(dateFormat), time: String.valueOf(exec.time.doubleValue()), tests: exec.tests] } | |
| ] | |
| } | |
| tests testCases.collect { tc -> | |
| [type: tc.type, | |
| name: tc.name, | |
| suite: tc.testClass, | |
| executions: tc.executions.collect { exec -> | |
| [executionDate: exec.executionDate?.format(dateFormat), time: String.valueOf(exec.time.doubleValue()), success: exec.success]} | |
| ] | |
| } | |
| } | |
| builder | |
| } | |
| def createCsvReportLines(testSuites, testCases) { | |
| List<String[]> rows = [] | |
| SortedSet executionDateColumns = findAllExecutionDates(testSuites, testCases) | |
| rows << createCsvHeaderRow(executionDateColumns) | |
| testSuites.each { ts -> | |
| rows << createTestSuiteCsvRow(ts, executionDateColumns) | |
| } | |
| testCases.each { tc -> | |
| rows << createTestCaseCsvRow(tc, executionDateColumns) | |
| } | |
| rows | |
| } | |
| SortedSet findAllExecutionDates(testSuites, testCases) { | |
| new TreeSet((testSuites*.executions*.executionDate + testCases*.executions*.executionDate).flatten()) | |
| } | |
| def createCsvHeaderRow(SortedSet executionDateColumns) { | |
| List<String> headerRow = ['REPORT TYPE', 'TYPE', 'NAME'] | |
| for(executionDateColumn in executionDateColumns) { | |
| headerRow << executionDateColumn | |
| headerRow << '#tests' | |
| } | |
| headerRow as String[] | |
| } | |
| def createTestSuiteCsvRow(ts, executionDateColumns) { | |
| List<String> tsRow = ['SUITE', ts.type, ts.name] | |
| executionDateColumns.each { date -> | |
| def exec = ts.executions.find { it.executionDate == date} | |
| def time = exec?.time | |
| tsRow << time ? String.valueOf(time.doubleValue()) : '' | |
| tsRow << exec?.tests | |
| } | |
| tsRow as String[] | |
| } | |
| def createTestCaseCsvRow(tc, executionDateColumns) { | |
| List<String> tcRow = ['TEST', tc.type, "${tc.testClass}.${tc.name}"] | |
| executionDateColumns.each { date -> | |
| def time = tc.executions.find { it.executionDate == date}?.time | |
| if (time == null) { | |
| tcRow << '' | |
| } else { | |
| tcRow << String.valueOf(time.doubleValue()) | |
| } | |
| tcRow << '' // 2nd column only used for tests suites | |
| } | |
| tcRow as String[] | |
| } | |
| String createReportNameDatePart(Date reportDate = new Date()) { | |
| reportDate.format('yyyy-MM-dd_HH-mm') | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment