unit-tests: Allow user to run tests repeatedly.

This commit is contained in:
Ilya Matveev
2017-09-26 12:21:22 +03:00
committed by ilmat192
parent 1b8fc1a40b
commit c8cd94c99f
4 changed files with 54 additions and 12 deletions
@@ -9,6 +9,12 @@ class GTestLogger : TestLoggerWithStatistics() {
println("[----------] Global test environment set-up.") println("[----------] Global test environment set-up.")
} }
override fun startIteration(runner: TestRunner, iteration: Int) {
if (runner.iterations != 1) {
println("\nRepeating all tests (iteration $iteration) . . .\n")
}
}
private fun printResults(timeMillis: Long) = with (statistics) { private fun printResults(timeMillis: Long) = with (statistics) {
println("[----------] Global test environment tear-down") // Just hack to deal with the Clion parser. println("[----------] Global test environment tear-down") // Just hack to deal with the Clion parser.
println("[==========] $total tests from $totalSuites test cases ran. ($timeMillis ms total)") println("[==========] $total tests from $totalSuites test cases ran. ($timeMillis ms total)")
@@ -4,6 +4,9 @@ interface TestListener {
fun startTesting(runner: TestRunner) fun startTesting(runner: TestRunner)
fun finishTesting(runner: TestRunner, timeMillis: Long) fun finishTesting(runner: TestRunner, timeMillis: Long)
fun startIteration(runner: TestRunner, iteration: Int)
fun finishIteration(runner: TestRunner, iteration: Int, timeMillis: Long)
fun startSuite(suite: TestSuite) fun startSuite(suite: TestSuite)
fun finishSuite(suite: TestSuite, timeMillis: Long) fun finishSuite(suite: TestSuite, timeMillis: Long)
fun ignoreSuite(suite: TestSuite) fun ignoreSuite(suite: TestSuite)
@@ -17,6 +20,8 @@ interface TestListener {
open class BaseTestListener: TestListener { open class BaseTestListener: TestListener {
override fun startTesting(runner: TestRunner) {} override fun startTesting(runner: TestRunner) {}
override fun finishTesting(runner: TestRunner, timeMillis: Long) {} override fun finishTesting(runner: TestRunner, timeMillis: Long) {}
override fun startIteration(runner: TestRunner, iteration: Int) {}
override fun finishIteration(runner: TestRunner, iteration: Int, timeMillis: Long) {}
override fun startSuite(suite: TestSuite) {} override fun startSuite(suite: TestSuite) {}
override fun finishSuite(suite: TestSuite, timeMillis: Long) {} override fun finishSuite(suite: TestSuite, timeMillis: Long) {}
override fun ignoreSuite(suite: TestSuite) {} override fun ignoreSuite(suite: TestSuite) {}
@@ -29,6 +29,8 @@ open class TestLoggerWithStatistics: BaseTestLogger() {
protected val statistics = MutableTestStatistics() protected val statistics = MutableTestStatistics()
override fun startTesting(runner: TestRunner) = statistics.reset() override fun startTesting(runner: TestRunner) = statistics.reset()
override fun startIteration(runner: TestRunner, iteration: Int) = statistics.reset()
override fun finishSuite(suite: TestSuite, timeMillis: Long) = statistics.registerSuite() override fun finishSuite(suite: TestSuite, timeMillis: Long) = statistics.registerSuite()
override fun pass(testCase: TestCase, timeMillis: Long) = statistics.registerPass() override fun pass(testCase: TestCase, timeMillis: Long) = statistics.registerPass()
override fun fail(testCase: TestCase, e: Throwable, timeMillis: Long) = statistics.registerFail(testCase) override fun fail(testCase: TestCase, e: Throwable, timeMillis: Long) = statistics.registerFail(testCase)
@@ -44,6 +46,10 @@ class SimpleTestLogger: BaseTestLogger() {
override fun startTesting(runner: TestRunner) = println("Starting testing") override fun startTesting(runner: TestRunner) = println("Starting testing")
override fun finishTesting(runner: TestRunner, timeMillis: Long) = println("Testing finished") override fun finishTesting(runner: TestRunner, timeMillis: Long) = println("Testing finished")
override fun startIteration(runner: TestRunner, iteration: Int) = println("Starting iteration: $iteration")
override fun finishIteration(runner: TestRunner, iteration: Int, timeMillis: Long) =
println("Iteration finished: $iteration")
override fun startSuite(suite: TestSuite) = println("Starting test suite: $suite") override fun startSuite(suite: TestSuite) = println("Starting test suite: $suite")
override fun finishSuite(suite: TestSuite, timeMillis: Long) = println("Test suite finished: $suite") override fun finishSuite(suite: TestSuite, timeMillis: Long) = println("Test suite finished: $suite")
override fun ignoreSuite(suite: TestSuite) = println("Test suite ignored: $suite") override fun ignoreSuite(suite: TestSuite) = println("Test suite ignored: $suite")
@@ -12,6 +12,7 @@ object TestRunner {
get() = suites_ get() = suites_
var logger: TestLogger = GTestLogger() var logger: TestLogger = GTestLogger()
var iterations = 1
val listeners = mutableSetOf<TestListener>() val listeners = mutableSetOf<TestListener>()
val filters = mutableListOf<(TestCase) -> Boolean>() val filters = mutableListOf<(TestCase) -> Boolean>()
@@ -42,8 +43,9 @@ object TestRunner {
* --gtest_list_tests * --gtest_list_tests
* --ktest_list_tests - Show all available tests. * --ktest_list_tests - Show all available tests.
* *
* --gtest_filter=POSTIVE_PATTERNS[-NEGATIVE_PATTERNS] - Run only the tests whose name matches one of the * --gtest_filter=POSTIVE_PATTERNS[-NEGATIVE_PATTERNS]
* --ktest_filter=POSTIVE_PATTERNS[-NEGATIVE_PATTERNS] positive patterns but none of the negative patterns. * --ktest_filter=POSTIVE_PATTERNS[-NEGATIVE_PATTERNS] - Run only the tests whose name matches one of the
* positive patterns but none of the negative patterns.
* '?' matches any single character; '*' matches any * '?' matches any single character; '*' matches any
* substring; ':' separates two patterns. * substring; ':' separates two patterns.
* *
@@ -53,6 +55,10 @@ object TestRunner {
* --ktest_negative_regex_filter=PATTERN - Run only the tests whose name doesn't match the pattern. * --ktest_negative_regex_filter=PATTERN - Run only the tests whose name doesn't match the pattern.
* The pattern is a Kotlin regular expression. * The pattern is a Kotlin regular expression.
* *
* --gtest_repeat=COUNT
* --ktest_repeat=COUNT - Run the tests repeatedly.
* Use a negative count to repeat forever.
*
* --ktest_logger=GTEST|TEAMCITY|SIMPLE|SILENT - Use the specified output format. The default one is GTEST. * --ktest_logger=GTEST|TEAMCITY|SIMPLE|SILENT - Use the specified output format. The default one is GTEST.
*/ */
fun useArgs(args: Array<String>): Boolean { fun useArgs(args: Array<String>): Boolean {
@@ -67,13 +73,14 @@ object TestRunner {
private fun parseArgs(args: Array<String>): Boolean { private fun parseArgs(args: Array<String>): Boolean {
var result = true var result = true
args.filter { args.filter {
it.startsWith("--gtest_") || it.startsWith("--ktest_") || it == "--help" it.startsWith("--gtest_") || it.startsWith("--ktest_") || it == "--help" || it == "-h"
}.forEach { }.forEach {
val arg = it.split('=') val arg = it.split('=')
when (arg.size) { when (arg.size) {
1 -> when (arg[0]) { 1 -> when (arg[0]) {
"--gtest_list_tests", "--gtest_list_tests",
"--ktest_list_tests" -> { logger.logTestList(this); result = false } "--ktest_list_tests" -> { logger.logTestList(this); result = false }
"-h",
"--help" -> { logger.log(help); result = false } "--help" -> { logger.log(help); result = false }
else -> throw IllegalArgumentException("Unknown option: $it\n$help") else -> throw IllegalArgumentException("Unknown option: $it\n$help")
} }
@@ -84,8 +91,11 @@ object TestRunner {
"--ktest_logger" -> setLoggerFromArg(value) "--ktest_logger" -> setLoggerFromArg(value)
"--gtest_filter", "--gtest_filter",
"--ktest_filter" -> setGTestFilterFromArg(value) "--ktest_filter" -> setGTestFilterFromArg(value)
"--ktest_regex_filter"-> setRegexFilterFromArg(value, true) "--ktest_regex_filter" -> setRegexFilterFromArg(value, true)
"--ktest_negative_regex_filter" -> setRegexFilterFromArg(value, false) "--ktest_negative_regex_filter" -> setRegexFilterFromArg(value, false)
"--ktest_repeat",
"--gtest_repeat" -> iterations = value.toIntOrNull() ?:
throw IllegalArgumentException("Cannot parse number: $value")
else -> throw IllegalArgumentException("Unknown option: $it\n$help") else -> throw IllegalArgumentException("Unknown option: $it\n$help")
} }
} }
@@ -167,6 +177,9 @@ object TestRunner {
| |
|--ktest_negative_regex_filter=PATTERN - Run only the tests whose name doesn't match the pattern. |--ktest_negative_regex_filter=PATTERN - Run only the tests whose name doesn't match the pattern.
| The pattern is a Kotlin regular expression. | The pattern is a Kotlin regular expression.
|--gtest_repeat=COUNT
|--ktest_repeat=COUNT - Run the tests repeatedly.
| Use a negative count to repeat forever.
| |
|--ktest_logger=GTEST|TEAMCITY|SIMPLE|SILENT - Use the specified output format. The default one is GTEST. |--ktest_logger=GTEST|TEAMCITY|SIMPLE|SILENT - Use the specified output format. The default one is GTEST.
""".trimMargin() """.trimMargin()
@@ -196,6 +209,22 @@ object TestRunner {
doAfterClass() doAfterClass()
} }
private fun runIteration(iteration: Int) {
sendToListeners { startIteration(this@TestRunner, iteration) }
val iterationTime = measureTimeMillis {
suites.forEach {
if (it.ignored) {
sendToListeners { ignoreSuite(it) }
} else {
sendToListeners { startSuite(it) }
val time = measureTimeMillis { it.run() }
sendToListeners { finishSuite(it, time) }
}
}
}
sendToListeners { finishIteration(this@TestRunner, iteration, iterationTime) }
}
fun run(args: Array<String>): Int { fun run(args: Array<String>): Int {
return if (useArgs(args)) { return if (useArgs(args)) {
run() run()
@@ -207,14 +236,10 @@ object TestRunner {
fun run(): Int { fun run(): Int {
sendToListeners { startTesting(this@TestRunner) } sendToListeners { startTesting(this@TestRunner) }
val totalTime = measureTimeMillis { val totalTime = measureTimeMillis {
suites.forEach { var i = 1
if (it.ignored) { while (i <= iterations || iterations < 0) {
sendToListeners { ignoreSuite(it) } runIteration(i)
} else { i++
sendToListeners { startSuite(it) }
val time = measureTimeMillis { it.run() }
sendToListeners { finishSuite(it, time) }
}
} }
} }
sendToListeners { finishTesting(this@TestRunner, totalTime) } sendToListeners { finishTesting(this@TestRunner, totalTime) }