unit-tests: Allow user to run tests repeatedly.
This commit is contained in:
@@ -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) }
|
||||||
|
|||||||
Reference in New Issue
Block a user