Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement test timeouts #647

Merged
merged 11 commits into from
Apr 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions gradle/common/dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ allprojects {

add(mainConfigurationName, 'org.mockito:mockito-core:2.23.4')
add(mainConfigurationName, 'org.mockito:mockito-inline:2.23.4')
add(mainConfigurationName, 'org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.1.1')
add(mainConfigurationName, 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1')
add(mainConfigurationName, 'org.jetbrains.kotlinx:kotlinx-coroutines-native:1.1.1')
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ import org.spekframework.spek2.Spek

object DefaultPackageTest: Spek({
test("test in a default package") {}
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.spekframework.spek2.integration

import org.spekframework.spek2.Spek
import org.spekframework.spek2.meta.Ignore

// remove @Ignore to test if timeouts are working.
@Ignore
raniejade marked this conversation as resolved.
Show resolved Hide resolved
object TimeoutTest: Spek({
test("default timeout") {
while (true) {}
}

test("custom timeout", timeout = 2000) {
while (true) {}
}
})
1 change: 1 addition & 0 deletions integration-test/src/nativeTest/kotlin/Test.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.spekframework.spek2.runtime.discovery.DiscoveryContext

fun main(args: Array<String>) {
val discoveryContext = DiscoveryContext.builder()
.addTest { DefaultPackageTest }
.addTest { CalculatorSpecs }
.addTest { EmptyGroupTest }
.addTest { CalculatorSpecs }
Expand Down
3 changes: 2 additions & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pluginManagement {
}

enableFeaturePreview('STABLE_PUBLISHING')
enableFeaturePreview('GRADLE_METADATA')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

required by the coroutines library.


rootProject.name = 'spek'

Expand All @@ -29,4 +30,4 @@ if (!hasProperty("excludeIdePlugins")) {
include 'spek-ide-plugin:intellij-base-jvm'
include 'spek-ide-plugin:intellij-idea'
include 'spek-ide-plugin:android-studio'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ interface ScopeBody {

@SpekDsl
interface TestContainer {
val defaultTimeout: Long

@Synonym(type = SynonymType.TEST)
@Descriptions(Description(DescriptionLocation.VALUE_PARAMETER, 0))
fun test(description: String, skip: Skip = Skip.No, body: TestBody.() -> Unit)
fun test(description: String, skip: Skip = Skip.No, timeout: Long = defaultTimeout, body: TestBody.() -> Unit)
}

@SpekDsl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ class Suite(val delegate: GroupBody) : LifecycleAware by delegate {

@Synonym(SynonymType.TEST)
@Descriptions(Description(DescriptionLocation.VALUE_PARAMETER, 0))
fun it(description: String, skip: Skip = Skip.No, body: TestBody.() -> Unit) {
delegate.createTest(description, skip, body)
fun it(description: String, skip: Skip = Skip.No, timeout: Long = delegate.defaultTimeout, body: TestBody.() -> Unit) {
delegate.createTest(description, skip, timeout, body)
}

@Synonym(SynonymType.TEST, excluded = true)
@Descriptions(Description(DescriptionLocation.VALUE_PARAMETER, 0))
fun xit(description: String, reason: String = "", body: TestBody.() -> Unit) {
delegate.createTest(description, Skip.Yes(reason), body)
fun xit(description: String, reason: String = "", timeout: Long = delegate.defaultTimeout, body: TestBody.() -> Unit) {
delegate.createTest(description, Skip.Yes(reason), timeout, body)
}

fun before(cb: () -> Unit) {
Expand Down Expand Up @@ -81,6 +81,6 @@ private fun GroupBody.createSuite(description: String, skip: Skip, body: Suite.(
}
}

private fun GroupBody.createTest(description: String, skip: Skip, body: TestBody.() -> Unit) {
test(description, skip, body)
private fun GroupBody.createTest(description: String, skip: Skip, timeout: Long, body: TestBody.() -> Unit) {
test(description, skip, timeout, body)
}
13 changes: 12 additions & 1 deletion spek-runtime/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ kotlin {
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib')
api project(':spek-dsl')
implementation kotlin('stdlib')
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-common'
}
}

Expand All @@ -40,6 +41,7 @@ kotlin {
implementation kotlin('stdlib-jdk8')
implementation kotlin('reflect')
implementation 'io.github.classgraph:classgraph'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core'
}
}

Expand All @@ -49,14 +51,23 @@ kotlin {

linuxMain {
dependsOn nativeMain
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.1.1'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dependencies.gradle does not work here for some reason.

}
}

macOSMain {
dependsOn nativeMain
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.1.1'
}
}

windowsMain {
dependsOn nativeMain
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.1.1'
}
}

nativeTest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ class Collector(
val root: GroupScopeImpl,
private val lifecycleManager: LifecycleManager,
private val fixtures: FixturesAdapter,
override val defaultCachingMode: CachingMode
override val defaultCachingMode: CachingMode,
override val defaultTimeout: Long
) : Root {

private val ids = linkedMapOf<String, Int>()
Expand Down Expand Up @@ -52,7 +53,7 @@ class Collector(
} else {
defaultCachingMode
}
val collector = Collector(group, lifecycleManager, fixtures, cachingMode)
val collector = Collector(group, lifecycleManager, fixtures, cachingMode, defaultTimeout)
try {
body.invoke(collector)
} catch (e: Throwable) {
Expand All @@ -62,6 +63,7 @@ class Collector(
idFor("Group Failure"),
root.path.resolve("Group Failure"),
root,
defaultTimeout,
{},
skip,
lifecycleManager
Expand All @@ -71,11 +73,12 @@ class Collector(

}

override fun test(description: String, skip: Skip, body: TestBody.() -> Unit) {
override fun test(description: String, skip: Skip, timeout: Long, body: TestBody.() -> Unit) {
val test = TestScopeImpl(
idFor(description),
root.path.resolve(description),
root,
defaultTimeout,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you want to use the argument here instead

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, already fixed in master.

Copy link

@boylenssen boylenssen May 24, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so I have this:

class ResponseTest : Spek({

    setArchTaskExecutor()

    timeout(15000)

but that doesn't work. How to I set it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defaultTimeout = xxx

body,
skip,
lifecycleManager
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
package org.spekframework.spek2.runtime

import kotlinx.coroutines.*
import org.spekframework.spek2.dsl.Skip
import org.spekframework.spek2.runtime.execution.ExecutionListener
import org.spekframework.spek2.runtime.execution.ExecutionRequest
import org.spekframework.spek2.runtime.execution.ExecutionResult
import org.spekframework.spek2.runtime.scope.GroupScopeImpl
import org.spekframework.spek2.runtime.scope.ScopeImpl
import org.spekframework.spek2.runtime.scope.TestScopeImpl
import kotlin.coroutines.CoroutineContext

class Executor {
class Executor: CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Default + job

fun execute(request: ExecutionRequest) {
request.executionListener.executionStart()
request.roots.forEach { execute(it, request.executionListener) }
request.executionListener.executionFinish()
job.cancel()
}

private fun execute(scope: ScopeImpl, listener: ExecutionListener) {
Expand All @@ -24,11 +30,26 @@ class Executor {

val result = executeSafely {
try {
scope.before()
scope.execute()
when (scope) {
is GroupScopeImpl -> {
scope.before()
scope.getChildren().forEach { execute(it, listener) }
}
is TestScopeImpl -> {
doRunBlocking {
// this needs to be here, in K/N the event loop
// is started during a runBlocking call. Calling
// any builders outside that will throw an exception.
val job = [email protected] {
scope.before()
scope.execute()
}

if (scope is GroupScopeImpl) {
scope.getChildren().forEach { execute(it, listener) }
withTimeout(scope.timeout) {
job.join()
}
}
}
}
} finally {
scope.after()
Expand Down Expand Up @@ -64,3 +85,5 @@ class Executor {
is TestScopeImpl -> listener.testIgnored(scope, reason)
}
}

expect fun doRunBlocking(block: suspend CoroutineScope.() -> Unit)
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.spekframework.spek2.runtime.lifecycle.LifecycleManager
import org.spekframework.spek2.runtime.scope.*
import org.spekframework.spek2.runtime.util.ClassUtil

private const val DEFAULT_TIMEOUT = 10000L
class SpekRuntime {
fun discover(discoveryRequest: DiscoveryRequest): DiscoveryResult {
val scopes = discoveryRequest.context.getTests()
Expand Down Expand Up @@ -46,7 +47,7 @@ class SpekRuntime {
className
}
val classScope = GroupScopeImpl(ScopeId(ScopeType.Class, qualifiedName), path, null, Skip.No, lifecycleManager, false)
val collector = Collector(classScope, lifecycleManager, fixtures, CachingMode.TEST)
val collector = Collector(classScope, lifecycleManager, fixtures, CachingMode.TEST, DEFAULT_TIMEOUT)

try {
instance.root.invoke(collector)
Expand All @@ -56,6 +57,7 @@ class SpekRuntime {
ScopeId(ScopeType.Scope, "Discovery failure"),
path.resolve("Discovery failure"),
classScope,
DEFAULT_TIMEOUT,
{},
Skip.No,
lifecycleManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class TestScopeImpl(
id: ScopeId,
path: Path,
override val parent: GroupScope,
val timeout: Long,
private val body: TestBody.() -> Unit,
skip: Skip,
lifecycleManager: LifecycleManager
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.spekframework.spek2.runtime

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.runBlocking

actual fun doRunBlocking(block: suspend CoroutineScope.() -> Unit) {
runBlocking {
block()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.spekframework.spek2.runtime

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.runBlocking

actual fun doRunBlocking(block: suspend CoroutineScope.() -> Unit) {
runBlocking {
block()
}
}