diff --git a/kotlintest-assertions/src/jvmTest/kotlin/com/sksamuel/kotlintest/assertions/AssertionCounterTest.kt b/kotlintest-assertions/src/jvmTest/kotlin/com/sksamuel/kotlintest/assertions/AssertionCounterTest.kt index 338c763d1b3..9cb394d3a83 100644 --- a/kotlintest-assertions/src/jvmTest/kotlin/com/sksamuel/kotlintest/assertions/AssertionCounterTest.kt +++ b/kotlintest-assertions/src/jvmTest/kotlin/com/sksamuel/kotlintest/assertions/AssertionCounterTest.kt @@ -24,8 +24,8 @@ class AssertionCounterTest : FunSpec() { "AssertionMode.Error assertion mode should fail the test if no assertions were present" -> { execute(testCase) { when (it.status) { - TestStatus.Error, TestStatus.Failure -> complete(TestResult.success(it.durationMs)) - else -> complete(TestResult.error(RuntimeException("Should have failed"), it.durationMs)) + TestStatus.Error, TestStatus.Failure -> complete(TestResult.success(it.duration)) + else -> complete(TestResult.error(RuntimeException("Should have failed"), it.duration)) } } } diff --git a/kotlintest-core/src/commonMain/kotlin/io/kotlintest/TestResult.kt b/kotlintest-core/src/commonMain/kotlin/io/kotlintest/TestResult.kt index 6ab39dc93d7..adffd68f0c3 100644 --- a/kotlintest-core/src/commonMain/kotlin/io/kotlintest/TestResult.kt +++ b/kotlintest-core/src/commonMain/kotlin/io/kotlintest/TestResult.kt @@ -1,26 +1,30 @@ package io.kotlintest +import kotlin.time.Duration +import kotlin.time.ExperimentalTime + +@UseExperimental(ExperimentalTime::class) data class TestResult(val status: TestStatus, val error: Throwable?, val reason: String?, - val durationMs: Long, + val duration: Duration, val metaData: Map = emptyMap()) { - companion object { - fun success(durationMs: Long) = TestResult(TestStatus.Success, null, null, durationMs) - val Ignored = TestResult(TestStatus.Ignored, null, null, 0) - fun failure(e: AssertionError, durationMs: Long) = TestResult(TestStatus.Failure, e, null, durationMs) - fun error(t: Throwable, durationMs: Long) = TestResult(TestStatus.Error, t, null, durationMs) - fun ignored(reason: String?) = TestResult(TestStatus.Ignored, null, reason, 0) - } + companion object { + fun success(duration: Duration) = TestResult(TestStatus.Success, null, null, duration) + val Ignored = TestResult(TestStatus.Ignored, null, null, Duration.ZERO) + fun failure(e: AssertionError, duration: Duration) = TestResult(TestStatus.Failure, e, null, duration) + fun error(t: Throwable, duration: Duration) = TestResult(TestStatus.Error, t, null, duration) + fun ignored(reason: String?) = TestResult(TestStatus.Ignored, null, reason, Duration.ZERO) + } } enum class TestStatus { - // the test was skipped completely - Ignored, - // the test was successful - Success, - // the test failed because of some exception that was not an assertion error - Error, - // the test ran but an assertion failed - Failure + // the test was skipped completely + Ignored, + // the test was successful + Success, + // the test failed because of some exception that was not an assertion error + Error, + // the test ran but an assertion failed + Failure } diff --git a/kotlintest-runner/kotlintest-runner-console/src/jvmMain/kotlin/io/kotlintest/runner/console/MochaConsoleWriter.kt b/kotlintest-runner/kotlintest-runner-console/src/jvmMain/kotlin/io/kotlintest/runner/console/MochaConsoleWriter.kt index 0ed06d42f52..eedcb8dedd6 100644 --- a/kotlintest-runner/kotlintest-runner-console/src/jvmMain/kotlin/io/kotlintest/runner/console/MochaConsoleWriter.kt +++ b/kotlintest-runner/kotlintest-runner-console/src/jvmMain/kotlin/io/kotlintest/runner/console/MochaConsoleWriter.kt @@ -8,8 +8,9 @@ import io.kotlintest.TestResult import io.kotlintest.TestStatus import io.kotlintest.TestType import io.kotlintest.core.fromSpecClass -import java.time.Duration import kotlin.reflect.KClass +import kotlin.time.ExperimentalTime +import kotlin.time.milliseconds private val isWindows = System.getProperty("os.name").contains("win") @@ -45,6 +46,7 @@ class MochaConsoleWriter(private val term: TermColors, override fun hasErrors(): Boolean = errors + @UseExperimental(ExperimentalTime::class) private fun testLine(testCase: TestCase, result: TestResult): String { val name = when (result.status) { TestStatus.Failure, TestStatus.Error -> term.brightRed(testCase.name + " *** FAILED ***") @@ -57,7 +59,7 @@ class MochaConsoleWriter(private val term: TermColors, TestStatus.Ignored -> IgnoredSymbol } val duration = when (testCase.type) { - TestType.Test -> durationString(result.durationMs) + TestType.Test -> durationString(result.duration.toLongMilliseconds()) else -> "" } return "$margin${testCase.description.indent()} ${symbol.print(term)} $name $duration".padEnd(80, ' ') @@ -136,9 +138,10 @@ class MochaConsoleWriter(private val term: TermColors, private fun padNewLines(str: String, pad: String): String = str.lines().joinToString("\n") { "$pad$it" } + @UseExperimental(ExperimentalTime::class) override fun engineFinished(t: Throwable?) { - val duration = Duration.ofMillis(System.currentTimeMillis() - start) + val duration = (System.currentTimeMillis() - start).milliseconds val ignored = results.filter { it.value.status == TestStatus.Ignored } val failed = results.filter { it.value.status == TestStatus.Failure || it.value.status == TestStatus.Error } @@ -148,7 +151,7 @@ class MochaConsoleWriter(private val term: TermColors, val specDistinctCount = specs.distinct().size println() - println(term.brightWhite("${margin}KotlinTest completed in ${duration.seconds} seconds / ${duration.toMillis()} milliseconds")) + println(term.brightWhite("${margin}KotlinTest completed in ${duration.toLongMilliseconds()} seconds / ${duration.toLongMilliseconds()} milliseconds")) println("${margin}Executed $specDistinctCount specs containing ${failed.size + passed.size + ignored.size} tests") println("$margin${passed.size} passed, ${failed.size} failed, ${ignored.size} ignored") if (failed.isNotEmpty()) { diff --git a/kotlintest-runner/kotlintest-runner-console/src/jvmTest/kotlin/com/sksamuel/kotlintest/runner/console/BasicConsoleWriterTest.kt b/kotlintest-runner/kotlintest-runner-console/src/jvmTest/kotlin/com/sksamuel/kotlintest/runner/console/BasicConsoleWriterTest.kt index ca7fb207ae7..efc592125c0 100644 --- a/kotlintest-runner/kotlintest-runner-console/src/jvmTest/kotlin/com/sksamuel/kotlintest/runner/console/BasicConsoleWriterTest.kt +++ b/kotlintest-runner/kotlintest-runner-console/src/jvmTest/kotlin/com/sksamuel/kotlintest/runner/console/BasicConsoleWriterTest.kt @@ -7,7 +7,10 @@ import io.kotlintest.matchers.string.shouldContain import io.kotlintest.matchers.string.shouldContainInOrder import io.kotlintest.runner.console.BasicConsoleWriter import io.kotlintest.specs.FunSpec +import kotlin.time.Duration +import kotlin.time.ExperimentalTime +@UseExperimental(ExperimentalTime::class) class BasicConsoleWriterTest : FunSpec() { init { @@ -25,15 +28,15 @@ class BasicConsoleWriterTest : FunSpec() { writer.engineStarted(emptyList()) writer.beforeSpecClass(this@BasicConsoleWriterTest::class) writer.enterTestCase(test1) - writer.exitTestCase(test1, TestResult.success(0)) + writer.exitTestCase(test1, TestResult.success(Duration.ZERO)) writer.enterTestCase(test2) - writer.exitTestCase(test2, TestResult.error(RuntimeException("wibble boom"), 0)) + writer.exitTestCase(test2, TestResult.error(RuntimeException("wibble boom"), Duration.ZERO)) writer.enterTestCase(test3) - writer.exitTestCase(test3, TestResult.failure(AssertionError("wobble vablam"), 0)) + writer.exitTestCase(test3, TestResult.failure(AssertionError("wobble vablam"), Duration.ZERO)) writer.enterTestCase(test4) writer.exitTestCase(test4, TestResult.ignored("don't like it")) writer.enterTestCase(test5) - writer.exitTestCase(test5, TestResult.success(0)) + writer.exitTestCase(test5, TestResult.success(Duration.ZERO)) writer.afterSpecClass(this@BasicConsoleWriterTest::class, null) writer.engineFinished(null) } @@ -70,12 +73,12 @@ class BasicConsoleWriterTest : FunSpec() { writer.enterTestCase(test1) writer.enterTestCase(test2) writer.enterTestCase(test3) - writer.exitTestCase(test3, TestResult.failure(AssertionError("wobble vablam"), 0)) - writer.exitTestCase(test2, TestResult.error(RuntimeException("wibble boom"), 0)) - writer.exitTestCase(test1, TestResult.success(0)) + writer.exitTestCase(test3, TestResult.failure(AssertionError("wobble vablam"), Duration.ZERO)) + writer.exitTestCase(test2, TestResult.error(RuntimeException("wibble boom"), Duration.ZERO)) + writer.exitTestCase(test1, TestResult.success(Duration.ZERO)) writer.enterTestCase(test4) writer.enterTestCase(test5) - writer.exitTestCase(test5, TestResult.success(0)) + writer.exitTestCase(test5, TestResult.success(Duration.ZERO)) writer.exitTestCase(test4, TestResult.ignored("don't like it")) writer.afterSpecClass(this@BasicConsoleWriterTest::class, null) writer.engineFinished(null) diff --git a/kotlintest-runner/kotlintest-runner-console/src/jvmTest/kotlin/com/sksamuel/kotlintest/runner/console/TeamCityConsoleWriterTest.kt b/kotlintest-runner/kotlintest-runner-console/src/jvmTest/kotlin/com/sksamuel/kotlintest/runner/console/TeamCityConsoleWriterTest.kt index a1f8a623329..a59717d060e 100644 --- a/kotlintest-runner/kotlintest-runner-console/src/jvmTest/kotlin/com/sksamuel/kotlintest/runner/console/TeamCityConsoleWriterTest.kt +++ b/kotlintest-runner/kotlintest-runner-console/src/jvmTest/kotlin/com/sksamuel/kotlintest/runner/console/TeamCityConsoleWriterTest.kt @@ -18,7 +18,10 @@ import io.kotlintest.core.sourceRef import io.kotlintest.specs.FunSpec import io.kotlintest.tables.row import kotlin.reflect.KClass +import kotlin.time.Duration +import kotlin.time.ExperimentalTime +@ExperimentalTime class TeamCityConsoleWriterTest : FunSpec() { private val klass: KClass = TeamCityConsoleWriterTest::class @@ -78,7 +81,7 @@ class TeamCityConsoleWriterTest : FunSpec() { test("after test should write testSuiteFinished for container success") { captureStandardOut { - TeamCityConsoleWriter().afterTestCaseExecution(testCaseContainer, TestResult.success(0)) + TeamCityConsoleWriter().afterTestCaseExecution(testCaseContainer, TestResult.success(Duration.ZERO)) } shouldBe "\n##teamcity[testSuiteFinished name='my test container']\n" } @@ -86,7 +89,7 @@ class TeamCityConsoleWriterTest : FunSpec() { captureStandardErr { captureStandardOut { TeamCityConsoleWriter().afterTestCaseExecution(testCaseContainer, - TestResult.error(AssertionError("wibble"), 0)) + TestResult.error(AssertionError("wibble"), Duration.ZERO)) } shouldBe "\n" + "##teamcity[testStarted name='my test container ']\n" + "##teamcity[testFailed name='my test container ' message='wibble']\n" + @@ -103,7 +106,7 @@ class TeamCityConsoleWriterTest : FunSpec() { test("after test should write testFinished for test success") { captureStandardOut { - TeamCityConsoleWriter().afterTestCaseExecution(testCaseTest, TestResult.success(0)) + TeamCityConsoleWriter().afterTestCaseExecution(testCaseTest, TestResult.success(Duration.ZERO)) } shouldBe "\n##teamcity[testFinished name='my test case']\n" } @@ -111,7 +114,7 @@ class TeamCityConsoleWriterTest : FunSpec() { captureStandardOut { captureStandardErr { TeamCityConsoleWriter().afterTestCaseExecution(testCaseTest, - TestResult.error(AssertionError("wibble"), 0) + TestResult.error(AssertionError("wibble"), Duration.ZERO) ) } shouldStartWith "\njava.lang.AssertionError: wibble\n" + "\tat com.sksamuel.kotlintest.runner.console.TeamCityConsoleWriter" @@ -123,7 +126,7 @@ class TeamCityConsoleWriterTest : FunSpec() { captureStandardErr { TeamCityConsoleWriter().afterTestCaseExecution( testCaseTest, - TestResult.failure(AssertionError("wibble"), 0) + TestResult.failure(AssertionError("wibble"), Duration.ZERO) ) } shouldStartWith "\njava.lang.AssertionError: wibble\n" + "\tat com.sksamuel.kotlintest.runner.console.TeamCityConsoleWriter" @@ -148,7 +151,7 @@ class TeamCityConsoleWriterTest : FunSpec() { } captureStandardOut { - TeamCityConsoleWriter().afterTestCaseExecution(testCaseTest, TestResult.failure(error, 0)) + TeamCityConsoleWriter().afterTestCaseExecution(testCaseTest, TestResult.failure(error, Duration.ZERO)) } shouldBe "\n##teamcity[testFailed name='my test case' message='Test failed']\n" } } diff --git a/kotlintest-runner/kotlintest-runner-jvm/src/jvmMain/kotlin/io/kotlintest/runner/jvm/TestCaseExecutor.kt b/kotlintest-runner/kotlintest-runner-jvm/src/jvmMain/kotlin/io/kotlintest/runner/jvm/TestCaseExecutor.kt index 4b1476d37a2..be1fa3913aa 100644 --- a/kotlintest-runner/kotlintest-runner-jvm/src/jvmMain/kotlin/io/kotlintest/runner/jvm/TestCaseExecutor.kt +++ b/kotlintest-runner/kotlintest-runner-jvm/src/jvmMain/kotlin/io/kotlintest/runner/jvm/TestCaseExecutor.kt @@ -16,7 +16,9 @@ import kotlinx.coroutines.withContext import org.slf4j.LoggerFactory import java.util.concurrent.* import java.util.concurrent.atomic.AtomicReference +import kotlin.time.Duration import kotlin.time.ExperimentalTime +import kotlin.time.milliseconds /** * The [TestCaseExecutor] is responsible for preparing and executing a single [TestCase]. @@ -36,6 +38,7 @@ import kotlin.time.ExperimentalTime * * The executor can be shared between multiple tests as it is thread safe. */ +@UseExperimental(ExperimentalTime::class) class TestCaseExecutor(private val listener: TestEngineListener, private val executor: ExecutorService, private val scheduler: ScheduledExecutorService) { @@ -75,7 +78,7 @@ class TestCaseExecutor(private val listener: TestEngineListener, } catch (t: Throwable) { t.printStackTrace() - listener.exitTestCase(testCase, TestResult.error(t, System.currentTimeMillis() - start)) + listener.exitTestCase(testCase, TestResult.error(t, (System.currentTimeMillis() - start).milliseconds)) } } @@ -184,7 +187,7 @@ class TestCaseExecutor(private val listener: TestEngineListener, executor.shutdown() } - val result = buildTestResult(error.get(), emptyMap(), System.currentTimeMillis() - start) + val result = buildTestResult(error.get(), emptyMap(), (System.currentTimeMillis() - start).milliseconds) listener.afterTestCaseExecution(testCase, result) return result @@ -223,11 +226,11 @@ class TestCaseExecutor(private val listener: TestEngineListener, private fun buildTestResult(error: Throwable?, metadata: Map, - durationMs: Long): TestResult = when (error) { - null -> TestResult(TestStatus.Success, null, null, durationMs, metadata) - is AssertionError -> TestResult(TestStatus.Failure, error, null, durationMs, metadata) - is SkipTestException -> TestResult(TestStatus.Ignored, null, error.reason, durationMs, metadata) - else -> TestResult(TestStatus.Error, error, null, durationMs, metadata) + duration: Duration): TestResult = when (error) { + null -> TestResult(TestStatus.Success, null, null, duration, metadata) + is AssertionError -> TestResult(TestStatus.Failure, error, null, duration, metadata) + is SkipTestException -> TestResult(TestStatus.Ignored, null, error.reason, duration, metadata) + else -> TestResult(TestStatus.Error, error, null, duration, metadata) } } diff --git a/kotlintest-tests/kotlintest-tests-core/src/jvmTest/kotlin/com/sksamuel/kotlintest/extensions/TestCaseExtensionAroundAdviceTest.kt b/kotlintest-tests/kotlintest-tests-core/src/jvmTest/kotlin/com/sksamuel/kotlintest/extensions/TestCaseExtensionAroundAdviceTest.kt index 0abf3ba769a..2483b432fe7 100644 --- a/kotlintest-tests/kotlintest-tests-core/src/jvmTest/kotlin/com/sksamuel/kotlintest/extensions/TestCaseExtensionAroundAdviceTest.kt +++ b/kotlintest-tests/kotlintest-tests-core/src/jvmTest/kotlin/com/sksamuel/kotlintest/extensions/TestCaseExtensionAroundAdviceTest.kt @@ -5,46 +5,53 @@ import io.kotlintest.TestResult import io.kotlintest.extensions.SpecLevelExtension import io.kotlintest.extensions.TestCaseExtension import io.kotlintest.specs.StringSpec +import kotlin.time.Duration +import kotlin.time.ExperimentalTime // this tests that we can manipulate the result of a test case from an extension +@ExperimentalTime class TestCaseExtensionAroundAdviceTest : StringSpec() { - class WibbleException : RuntimeException() + class WibbleException : RuntimeException() - object MyExt : TestCaseExtension { - override suspend fun intercept(testCase: TestCase, execute: suspend (TestCase, suspend (TestResult) -> Unit) -> Unit, complete: suspend (TestResult) -> Unit) { - when { - testCase.description.name == "test1" -> complete(TestResult.Ignored) - testCase.description.name == "test2" -> execute(testCase) { - when (it.error) { - is WibbleException -> complete(TestResult.success(0)) - else -> complete(it) - } - } - testCase.description.name == "test3" -> if (testCase.config.enabled) throw RuntimeException() else execute(testCase) { complete(it) } - testCase.description.name == "test4" -> execute(testCase.copy(config = testCase.config.copy(enabled = false))) { complete(it) } - else -> execute(testCase) { complete(it) } + object MyExt : TestCaseExtension { + override suspend fun intercept(testCase: TestCase, + execute: suspend (TestCase, suspend (TestResult) -> Unit) -> Unit, + complete: suspend (TestResult) -> Unit) { + when { + testCase.description.name == "test1" -> complete(TestResult.Ignored) + testCase.description.name == "test2" -> execute(testCase) { + when (it.error) { + is WibbleException -> complete(TestResult.success(Duration.ZERO)) + else -> complete(it) + } + } + testCase.description.name == "test3" -> + if (testCase.config.enabled) throw RuntimeException() else execute(testCase) { complete(it) } + testCase.description.name == "test4" -> + execute(testCase.copy(config = testCase.config.copy(enabled = false))) { complete(it) } + else -> execute(testCase) { complete(it) } + } } - } - } + } - override fun extensions(): List = listOf(MyExt) + override fun extensions(): List = listOf(MyExt) - init { - // this exception should not be thrown as the extension will skip evaluation of the test - "test1" { - throw RuntimeException() - } - // this exception will be thrown but then the test extension will override the failed result to return a success - "test2" { - throw WibbleException() - } - // the config for this test should be carried through to the extension - "test3".config(enabled = false) { - } - // config for this test should be overriden so that the test is actually disabled, and therefore the exception will not be thrown - "test4".config(enabled = true) { - throw RuntimeException() - } - } + init { + // this exception should not be thrown as the extension will skip evaluation of the test + "test1" { + throw RuntimeException() + } + // this exception will be thrown but then the test extension will override the failed result to return a success + "test2" { + throw WibbleException() + } + // the config for this test should be carried through to the extension + "test3".config(enabled = false) { + } + // config for this test should be overriden so that the test is actually disabled, and therefore the exception will not be thrown + "test4".config(enabled = true) { + throw RuntimeException() + } + } } diff --git a/kotlintest-tests/kotlintest-tests-core/src/jvmTest/kotlin/com/sksamuel/kotlintest/runner/junit5/JUnitTestRunnerListenerTest.kt b/kotlintest-tests/kotlintest-tests-core/src/jvmTest/kotlin/com/sksamuel/kotlintest/runner/junit5/JUnitTestRunnerListenerTest.kt index 6cbdb1180df..dda3bd2ffa0 100644 --- a/kotlintest-tests/kotlintest-tests-core/src/jvmTest/kotlin/com/sksamuel/kotlintest/runner/junit5/JUnitTestRunnerListenerTest.kt +++ b/kotlintest-tests/kotlintest-tests-core/src/jvmTest/kotlin/com/sksamuel/kotlintest/runner/junit5/JUnitTestRunnerListenerTest.kt @@ -17,8 +17,9 @@ import org.junit.platform.engine.TestDescriptor import org.junit.platform.engine.TestExecutionResult import org.junit.platform.engine.UniqueId import org.junit.platform.engine.support.descriptor.EngineDescriptor +import kotlin.time.Duration import kotlin.time.ExperimentalTime -import kotlin.time.milliseconds +import kotlin.time.minutes @ExperimentalTime class JUnitTestRunnerListenerTest : WordSpec({ @@ -137,7 +138,7 @@ class JUnitTestRunnerListenerTest : WordSpec({ val spec = JUnitTestRunnerListenerTest() val tc = TestCase.container(spec.description().append("my test"), spec) { } - .copy(config = TestCaseConfig(invocations = 3, timeout = Duration.ofMinutes(2))) + .copy(config = TestCaseConfig(invocations = 3, timeout = 2.minutes)) listener.beforeSpecClass(spec::class) @@ -164,9 +165,9 @@ class JUnitTestRunnerListenerTest : WordSpec({ val spec = JUnitTestRunnerListenerTest() val tc1 = TestCase.container(spec.description().append("test1"), spec) { } - .copy(config = TestCaseConfig(timeout = Duration.ofMinutes(2))) + .copy(config = TestCaseConfig(timeout = 2.minutes)) val tc2 = TestCase.container(tc1.description.append("test2"), spec) { } - .copy(config = TestCaseConfig(timeout = Duration.ofMinutes(2))) + .copy(config = TestCaseConfig(timeout = 2.minutes)) listener.beforeSpecClass(spec::class) listener.enterTestCase(tc1) diff --git a/kotlintest-tests/kotlintest-tests-core/src/jvmTest/kotlin/com/sksamuel/kotlintest/specs/annotation/AnnotationSpecTest.kt b/kotlintest-tests/kotlintest-tests-core/src/jvmTest/kotlin/com/sksamuel/kotlintest/specs/annotation/AnnotationSpecTest.kt index 0b7c6303302..9fbdb5af34d 100644 --- a/kotlintest-tests/kotlintest-tests-core/src/jvmTest/kotlin/com/sksamuel/kotlintest/specs/annotation/AnnotationSpecTest.kt +++ b/kotlintest-tests/kotlintest-tests-core/src/jvmTest/kotlin/com/sksamuel/kotlintest/specs/annotation/AnnotationSpecTest.kt @@ -11,79 +11,84 @@ import io.kotlintest.assertions.fail import io.kotlintest.shouldBe import io.kotlintest.specs.AnnotationSpec import java.util.concurrent.atomic.AtomicInteger +import kotlin.time.Duration +import kotlin.time.ExperimentalTime +@ExperimentalTime class AnnotationSpecTest : AnnotationSpec() { - private class FooException : RuntimeException() - private class BarException : RuntimeException() - - private var count = 0 - - @Test - fun test1() { - count += 1 - } - - @Test - fun test2() { - count += 1 - } - - @Test - fun `!bangedTest`() { - throw FooException() // Test should pass as this should be banged - } - - @Test(expected = FooException::class) - fun test3() { - throw FooException() // This test should pass! - } - - @Test(expected = FooException::class) - fun test4() { - throw BarException() - } - - @Test(expected = FooException::class) - fun test5() { - // Throw nothing - } - - override fun afterSpec(spec: Spec) { - count shouldBe 2 - } - - override fun extensions(): List = listOf(IgnoreFailedTestExtension) - - private object IgnoreFailedTestExtension : TestCaseExtension { - - override suspend fun intercept(testCase: TestCase, execute: suspend (TestCase, suspend (TestResult) -> Unit) -> Unit, complete: suspend (TestResult) -> Unit) { - if (testCase.name !in listOf("test4", "test5")) return execute(testCase, complete) - - execute(testCase) { - if (it.error !is AssertionError) { - complete(TestResult.failure(AssertionError("Expecting an assertion error!"), 0)) - } - - val errorMessage = it.error!!.message - val wrongExceptionMessage = "Expected exception of class FooException, but BarException was thrown instead." - val noExceptionMessage = "Expected exception of class FooException, but no exception was thrown." - - when (testCase.name) { - "test4" -> if (errorMessage == wrongExceptionMessage) { - complete(TestResult.success(0)) - } else { - complete(TestResult.failure(AssertionError("Wrong message."), 0)) - } - "test5" -> if (errorMessage == noExceptionMessage) { - complete(TestResult.success(0)) - } else { - complete(TestResult.failure(AssertionError("Wrong message."), 0)) - } - } + private class FooException : RuntimeException() + private class BarException : RuntimeException() + + private var count = 0 + + @Test + fun test1() { + count += 1 + } + + @Test + fun test2() { + count += 1 + } + + @Test + fun `!bangedTest`() { + throw FooException() // Test should pass as this should be banged + } + + @Test(expected = FooException::class) + fun test3() { + throw FooException() // This test should pass! + } + + @Test(expected = FooException::class) + fun test4() { + throw BarException() + } + + @Test(expected = FooException::class) + fun test5() { + // Throw nothing + } + + override fun afterSpec(spec: Spec) { + count shouldBe 2 + } + + override fun extensions(): List = listOf(IgnoreFailedTestExtension) + + private object IgnoreFailedTestExtension : TestCaseExtension { + + override suspend fun intercept(testCase: TestCase, + execute: suspend (TestCase, suspend (TestResult) -> Unit) -> Unit, + complete: suspend (TestResult) -> Unit) { + if (testCase.name !in listOf("test4", "test5")) return execute(testCase, complete) + + execute(testCase) { + if (it.error !is AssertionError) { + complete(TestResult.failure(AssertionError("Expecting an assertion error!"), Duration.ZERO)) + } + + val errorMessage = it.error!!.message + val wrongExceptionMessage = "Expected exception of class FooException, but BarException was thrown instead." + val noExceptionMessage = "Expected exception of class FooException, but no exception was thrown." + + when (testCase.name) { + "test4" -> if (errorMessage == wrongExceptionMessage) { + complete(TestResult.success(Duration.ZERO)) + } else { + complete(TestResult.failure(AssertionError("Wrong message."), Duration.ZERO)) + } + "test5" -> if (errorMessage == noExceptionMessage) { + complete(TestResult.success(Duration.ZERO)) + } else { + complete(TestResult.failure(AssertionError("Wrong message."), Duration.ZERO)) + } + } + } } - } - } + } } @@ -169,26 +174,29 @@ class AnnotationSpecAnnotationsTest : AnnotationSpec() { override fun testCaseOrder() = TestCaseOrder.Sequential } +@ExperimentalTime class AnnotationSpecFailureTest : AnnotationSpec() { - class FooException: Exception() + class FooException : Exception() - private val thrownException = FooException() + private val thrownException = FooException() - @Test - fun foo() { - throw thrownException - } + @Test + fun foo() { + throw thrownException + } - override fun extensions() = listOf(ExceptionCaptureExtension()) + override fun extensions() = listOf(ExceptionCaptureExtension()) - inner class ExceptionCaptureExtension : TestCaseExtension { + inner class ExceptionCaptureExtension : TestCaseExtension { - override suspend fun intercept(testCase: TestCase, execute: suspend (TestCase, suspend (TestResult) -> Unit) -> Unit, complete: suspend (TestResult) -> Unit) { - execute(testCase) { - it.error shouldBe thrownException - complete(TestResult.success(0)) + override suspend fun intercept(testCase: TestCase, + execute: suspend (TestCase, suspend (TestResult) -> Unit) -> Unit, + complete: suspend (TestResult) -> Unit) { + execute(testCase) { + it.error shouldBe thrownException + complete(TestResult.success(Duration.ZERO)) + } } - } - } + } } diff --git a/kotlintest-tests/kotlintest-tests-timeout/src/jvmTest/kotlin/com/sksamuel/kotlintest/timeout/GlobalTimeoutTest.kt b/kotlintest-tests/kotlintest-tests-timeout/src/jvmTest/kotlin/com/sksamuel/kotlintest/timeout/GlobalTimeoutTest.kt index 6f9f15e3cb6..9b45b2756d1 100644 --- a/kotlintest-tests/kotlintest-tests-timeout/src/jvmTest/kotlin/com/sksamuel/kotlintest/timeout/GlobalTimeoutTest.kt +++ b/kotlintest-tests/kotlintest-tests-timeout/src/jvmTest/kotlin/com/sksamuel/kotlintest/timeout/GlobalTimeoutTest.kt @@ -8,7 +8,10 @@ import io.kotlintest.extensions.TestCaseExtension import io.kotlintest.specs.StringSpec import kotlinx.coroutines.delay import java.lang.RuntimeException +import kotlin.time.ExperimentalTime +import kotlin.time.milliseconds +@ExperimentalTime class GlobalTimeoutTest : StringSpec() { init { @@ -29,7 +32,7 @@ class GlobalTimeoutTest : StringSpec() { complete: suspend (TestResult) -> Unit) { execute(testCase) { when (it.status) { - TestStatus.Failure, TestStatus.Error -> complete(TestResult.success(1000)) + TestStatus.Failure, TestStatus.Error -> complete(TestResult.success(1000.milliseconds)) else -> throw RuntimeException("This should not occur") } } diff --git a/kotlintest-tests/kotlintest-tests-timeout/src/jvmTest/kotlin/com/sksamuel/kotlintest/timeout/TimeoutTest.kt b/kotlintest-tests/kotlintest-tests-timeout/src/jvmTest/kotlin/com/sksamuel/kotlintest/timeout/TimeoutTest.kt index 8e2f386394a..188fa14345f 100644 --- a/kotlintest-tests/kotlintest-tests-timeout/src/jvmTest/kotlin/com/sksamuel/kotlintest/timeout/TimeoutTest.kt +++ b/kotlintest-tests/kotlintest-tests-timeout/src/jvmTest/kotlin/com/sksamuel/kotlintest/timeout/TimeoutTest.kt @@ -31,7 +31,7 @@ class TimeoutTest : StringSpec() { complete: suspend (TestResult) -> Unit) { execute(testCase) { when (it.status) { - TestStatus.Failure, TestStatus.Error -> complete(TestResult.success(1000)) + TestStatus.Failure, TestStatus.Error -> complete(TestResult.success(1000.milliseconds)) else -> throw RuntimeException("${testCase.description} should fail") } }