All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openbakery.test.TestResultParser.groovy Maven / Gradle / Ivy

Go to download

XCode-Plugin is a plugin to allow custom XCode projects to build as generated by CMake

There is a newer version: 0.0.201
Show newest version
package org.openbakery.test

import groovy.xml.MarkupBuilder
import org.apache.commons.configuration.plist.XMLPropertyListConfiguration
import org.openbakery.xcode.Destination
import org.slf4j.Logger
import org.slf4j.LoggerFactory

public class TestResultParser {

	private static Logger logger = LoggerFactory.getLogger(TestResultParser.class)


	def TEST_CASE_PATTERN = ~/^Test Case '(.*)'(.*)/

	def TEST_CLASS_PATTERN = ~/-\[([\w\.]*)\s(\w*)\]/

	def TEST_FAILED_PATTERN = ~/.*\*\* TEST FAILED \*\*/
	def TEST_SUCCEEDED_PATTERN = ~/.*\*\* TEST SUCCEEDED \*\*/

	def DURATION_PATTERN = ~/^\w+\s\((\d+\.\d+).*/


	File testSummariesDirectory
	List destinations

	def testResults = new HashMap>()

	public TestResultParser(File testSummariesDirectory, List destinations) {
		this.testSummariesDirectory = testSummariesDirectory
		this.destinations = destinations
	}

	public void parseAndStore(File outputDirectory) {
		parse()
		store(outputDirectory)
	}

	private void parse() {

		def testSummariesArray = testSummariesDirectory.list(
						[accept: { d, f -> f ==~ /.*TestSummaries.plist/ }] as FilenameFilter
		)

		if (testSummariesArray == null) {
			return
		}

		testSummariesArray.toList().each {
			def testResult = new XMLPropertyListConfiguration(new File(testSummariesDirectory, it))
			def identifier = testResult.getString("RunDestination.TargetDevice.Identifier")

			Destination destination = findDestinationForIdentifier(destinations, identifier)
			if (destination != null) {
				def resultList = processTestSummary(testResult.getList("TestableSummaries"))
				testResults.put(destination, resultList)
			}
		}
	}


	private void store(File outputDirectory) {
		logger.debug("store to test-result.xml")

		FileWriter writer = new FileWriter(new File(outputDirectory, "test-results.xml"))

		def xmlBuilder = new MarkupBuilder(writer)

		xmlBuilder.testsuites() {
			for (result in testResults) {
				String name = result.key.toPrettyString()

				def resultList = result.value
				int success = 0;
				int errors = 0;
				if (resultList != null) {
					success = numberSuccessInResultList(resultList);
					errors = numberErrorsInResultList(resultList);
				}

				testsuite(name: name, tests: success, errors: errors, failures: "0", skipped: "0") {

					for (TestClass testClass in resultList) {

						for (TestResult testResult in testClass.results) {
							logger.debug("testResult: {}", testResult)
							testcase(classname: testClass.name, name: testResult.method, time: testResult.duration) {
								if (!testResult.success) {
									error(type: "failure", message: "", testResult.output)
								}
								'system-out'(testResult.output)
							}
						}

					}

				}
			}
		}


	}

	Destination findDestinationForIdentifier(List destinations, String identifier) {
		for (destination in destinations) {
			if (destination.id == identifier) {
				return destination
			}
		}
		return null
	}


	HashMap> parseResult(File outputFile) {
		def testResults = new HashMap>()
		logger.debug("parse result from: {}", outputFile)
		if (!outputFile.exists()) {
			logger.info("No xcodebuild output file found!");
			return testResults;
		}
		boolean overallTestSuccess = true;

		def resultList = []

		int testRun = 0;
		boolean endOfDestination = false;

		StringBuilder output = new StringBuilder()

		outputFile.eachLine { line ->


			def matcher = TEST_CASE_PATTERN.matcher(line)
			if (matcher.matches()) {

				String message = matcher[0][2].trim()

				def nameMatcher = TEST_CLASS_PATTERN.matcher(matcher[0][1])
				if (!nameMatcher.matches()) {
					return
				}

				String testClassName = nameMatcher[0][1]
				String method = nameMatcher[0][2]

				if (message.startsWith("started")) {
					output = new StringBuilder()



					TestClass testClass = resultList.find { testClass -> testClass.name.equals(testClassName) }
					if (testClass == null) {
						testClass = new TestClass(name: testClassName);
						resultList << testClass
					}
					testClass.results << new TestResult(method: method)

				} else {
					//TestCase testCase = resultMap.get(testClass).find{ testCase -> testCase.method.equals(method) }
					TestClass testClass = resultList.find { testClass -> testClass.name.equals(testClassName) }
					if (testClass != null) {
						TestResult testResult = testClass.results.find { testResult -> testResult.method.equals(method) }

						if (testResult != null) {
							testResult.output = output.toString()

							testResult.success = !message.toLowerCase().startsWith("failed")
							if (!testResult.success) {
								logger.info("test + " + testResult + "failed!")
								overallTestSuccess = false;
							}

							def durationMatcher = DURATION_PATTERN.matcher(message)
							if (durationMatcher.matches()) {
								testResult.duration = Float.parseFloat(durationMatcher[0][1])
							}
						}
					} else {
						logger.info("No TestClass found for name: " + testClassName + " => " + line)
					}
				}
			}

			def testSuccessMatcher = TEST_SUCCEEDED_PATTERN.matcher(line)
			def testFailedMatcher = TEST_FAILED_PATTERN.matcher(line)

			if (testSuccessMatcher.matches() || testFailedMatcher.matches()) {
				testRun++;
				endOfDestination = true
			}

			if (testFailedMatcher.matches()) {
				overallTestSuccess = false;
			}


			if (endOfDestination) {
				Destination destination = destinations[(testRun - 1)]

				if (testResults.containsKey(destination)) {
					def destinationResultList = testResults.get(destination)
					destinationResultList.addAll(resultList);
				} else {
					testResults.put(destination, resultList)
				}

				resultList = []
				endOfDestination = false
			} else {
				if (output != null) {
					if (output.length() > 0) {
						output.append("\n")
					}
					output.append(line)
				}
			}
		}
		return testResults;
	}





	List processTestSummary(List list) {

		List resultList = []

		for (entry in list) {
			List testList = entry.getList("Tests")
			processTests(testList, resultList)
		}

		return resultList

	}

	List processTests(List list, List resultList) {
		for (entry in list) {
			List testList = entry.getList("Subtests")
			processSubtests(testList, resultList, entry.getString("TestName"))
		}


	}


	List processSubtests(List list, List resultList, String name) {

		TestClass testClass = null

		for (entry in list) {
			if (entry.getString("TestObjectClass") == "IDESchemeActionTestSummary") {
				if (testClass == null) {
					testClass = new TestClass(name: name);
					resultList << testClass
				}

				String method = entry.getString("TestName")
				TestResult testResult = new TestResult(method: method)
				testResult.success = entry.getString("TestStatus") == "Success"
				testClass.results << testResult

			} else if (entry.getString("TestObjectClass") == "IDESchemeActionTestSummaryGroup") {
				List testList = entry.getList("Subtests")
				processSubtests(testList, resultList, entry.getString("TestName"))
			}


		}

	}


	public int numberSuccess() {
		return numberSuccess(testResults)
	}


	public int numberSuccess(HashMap> results) {
		int success = 0;
		for (java.util.List list in results.values()) {
			success += numberSuccessInResultList(list);
		}
		return success;
	}

	public int numberErrors() {
		return numberErrors(testResults)
	}

	public int numberErrors(HashMap> results) {
		int errors = 0;
		for (java.util.List list in results.values()) {
			errors += numberErrorsInResultList(list);
		}
		return errors;
	}

	int numberSuccessInResultList(java.util.List results) {
		int success = 0;
		for (TestClass testClass in results) {
			success += testClass.numberSuccess()
		}
		return success
	}

	int numberErrorsInResultList(java.util.List results) {
		int errors = 0;
		for (TestClass testClass in results) {
			errors += testClass.numberErrors()
		}
		return errors
	}

	/*
	def storeJson() {
		logger.info("Saving test results")

		def list = [];
		for (Destination destination in project.xcodebuild.availableDestinations) {

			def resultList = testResults[destination]

			list << [
							destination:
											[
															name    : destination.name,
															platform: destination.platform,
															arch    : destination.arch,
															id      : destination.id,
															os      : destination.os
											],
							results    :
											resultList.collect {
												TestClass t ->
													[
																	name  : t.name,
																	result: t.results.collect {
																		TestResult r ->
																			[
																							method  : r.method,
																							success : r.success,
																							duration: r.duration,
																							output  : r.output.split("\n").collect {
																								String s -> escapeString(s)
																							}
																			]
																	}
													]
											}
			]

		}

		def builder = new groovy.json.JsonBuilder()
		builder(list)


		File outputDirectory = new File(project.getBuildDir(), "test");
		if (!outputDirectory.exists()) {
			outputDirectory.mkdirs()
		}

		new File(outputDirectory, "results.json").withWriter { out ->
			out.write(builder.toPrettyString())
		}
	}
	*/


	def escapeString(String string) {
		if (string == null) {
			return null;
		}
		StringBuffer buffer = new StringBuffer();

		for (int i = 0; i < string.length(); i++) {
			char ch = string.charAt(i);
			switch (ch) {
				case '"':
					buffer.append("\\\"");
					break;
				case '\\':
					buffer.append("\\\\");
					break;
				case '\b':
					buffer.append("\\b");
					break;
				case '\f':
					buffer.append("\\f");
					break;
				case '\n':
					buffer.append("\\n");
					break;
				case '\r':
					buffer.append("\\r");
					break;
				case '\t':
					buffer.append("\\t");
					break;
				case '/':
					buffer.append("\\/");
					break;
				default:
					buffer.append(ch);
					break;
			}
		}
		return buffer.toString();
	}

	void mergeResult(HashMap> fromPlist, HashMap> fromOutput) {

		fromPlist.each { destination, testClasses ->
			def secondDestinationClasses = fromOutput.get(destination)
			if (secondDestinationClasses != null) {
				mergeTestClasses(testClasses, secondDestinationClasses)
			}
		}
	}


	def mergeTestClasses(ArrayList fromPlist, ArrayList fromOutput) {
		fromPlist.each { testClass ->
			def testClassFromOutput = fromOutput.find { it.name == testClass.name }
			if (testClassFromOutput != null) {
				mergeTestResults(testClass.results, testClassFromOutput.results)
			}

		}

	}

	def mergeTestResults(List fromPlist, List fromOutput) {
		fromPlist.each { testResult ->
			def testResultFromOutput = fromOutput.find { it.method == testResult.method }
			if (testResultFromOutput != null) {
				testResult.duration = testResultFromOutput.duration
				testResult.output = testResultFromOutput.output
			}
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy