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 focused and pending groups #27

Merged
merged 1 commit into from
Apr 16, 2016
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 7 additions & 6 deletions kspec-core/src/main/kotlin/io/polymorphicpanda/kspec/KSpec.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ abstract class KSpec: Spec {

open fun configure(config: KSpecConfig) {}

override fun group(description: String, block: () -> Unit) {
override fun group(description: String, tags: Set<Tag>, block: () -> Unit) {
invokeIfNotDisabled {
val context = ExampleGroupContext(description, current)
val context = ExampleGroupContext(description, current, tags)
current = context
block()
current = current.parent ?: current
Expand Down Expand Up @@ -60,13 +60,14 @@ abstract class KSpec: Spec {
}
}

override fun <T: Any> group(subject: KClass<T>, description: String, block: SubjectSpec<T>.() -> Unit) {
override fun <T: Any> group(subject: KClass<T>, description: String, tags: Set<Tag>,
block: SubjectSpec<T>.() -> Unit) {
invokeIfNotDisabled {
val context = ExampleGroupContext(description.format(subject), current) {
val context = ExampleGroupContext(description.format(subject), current, tags, {
val constructor =
subject.constructors.firstOrNull { it.parameters.isEmpty() } ?: throw IllegalArgumentException()
subject.constructors.firstOrNull { it.parameters.isEmpty() } ?: throw InstantiationException()
constructor.call()
}
})
current = context
SubjectKSpec<T>(this, context).apply(block)
current = current.parent ?: current
Expand Down
4 changes: 2 additions & 2 deletions kspec-core/src/main/kotlin/io/polymorphicpanda/kspec/Spec.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import io.polymorphicpanda.kspec.tag.Tag
import kotlin.reflect.KClass

interface Spec {
fun group(description: String, block: () -> Unit)
fun <T: Any> group(subject: KClass<T>, description: String = "", block: SubjectSpec<T>.() -> Unit)
fun group(description: String, tags: Set<Tag>, block: () -> Unit)
fun <T: Any> group(subject: KClass<T>, description: String = "", tags: Set<Tag>, block: SubjectSpec<T>.() -> Unit)
fun example(description: String, tags: Set<Tag>, block: () -> Unit)
fun before(action: () -> Unit)
fun after(action: () -> Unit)
Expand Down
54 changes: 46 additions & 8 deletions kspec-core/src/main/kotlin/io/polymorphicpanda/kspec/Terms.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,58 @@ import io.polymorphicpanda.kspec.tag.focus
import io.polymorphicpanda.kspec.tag.pending
import kotlin.reflect.KClass

fun Spec.describe(description: String, action: () -> Unit) {
group("describe: $description", action)
fun Spec.describe(description: String, vararg tags: Tag, action: () -> Unit) {
group("describe: $description", setOf(*tags),action)
}

fun <T: Any> Spec.describe(subject: KClass<T>, description: String = "%s", action: SubjectSpec<T>.() -> Unit) {
group(subject, "describe: $description", action)
fun <T: Any> Spec.describe(subject: KClass<T>, description: String = "%s",
vararg tags: Tag, action: SubjectSpec<T>.() -> Unit) {
group(subject, "describe: $description", setOf(*tags), action)
}

fun Spec.context(description: String, action: () -> Unit) {
group("context: $description", action)
fun Spec.context(description: String, vararg tags: Tag, action: () -> Unit) {
group("context: $description", setOf(*tags), action)
}

fun <T: Any> Spec.context(subject: KClass<T>, description: String = "%s", action: SubjectSpec<T>.() -> Unit) {
group(subject, "context: $description", action)
fun <T: Any> Spec.context(subject: KClass<T>, description: String = "%s",
vararg tags: Tag, action: SubjectSpec<T>.() -> Unit) {
group(subject, "context: $description", setOf(*tags), action)
}

fun Spec.fdescribe(description: String, vararg tags: Tag, action: () -> Unit) {
group("describe: $description", setOf(focus(), *tags),action)
}

fun <T: Any> Spec.fdescribe(subject: KClass<T>, description: String = "%s",
vararg tags: Tag, action: SubjectSpec<T>.() -> Unit) {
group(subject, "describe: $description", setOf(focus(), *tags), action)
}

fun Spec.fcontext(description: String, vararg tags: Tag, action: () -> Unit) {
group("context: $description", setOf(focus(), *tags), action)
}

fun <T: Any> Spec.fcontext(subject: KClass<T>, description: String = "%s",
vararg tags: Tag, action: SubjectSpec<T>.() -> Unit) {
group(subject, "context: $description", setOf(focus(), *tags), action)
}

fun Spec.xdescribe(description: String, reason: String? = null, action: () -> Unit) {
group("describe: $description", setOf(pending(reason ?: "No reason provided")),action)
}

fun <T: Any> Spec.xdescribe(subject: KClass<T>, description: String = "%s",
reason: String? = null, action: SubjectSpec<T>.() -> Unit) {
group(subject, "describe: $description", setOf(pending(reason ?: "No reason provided")), action)
}

fun Spec.xcontext(description: String, reason: String? = null, action: () -> Unit) {
group("context: $description", setOf(pending(reason ?: "No reason provided")), action)
}

fun <T: Any> Spec.xcontext(subject: KClass<T>, description: String = "%s",
reason: String? = null, action: SubjectSpec<T>.() -> Unit) {
group(subject, "context: $description", setOf(pending(reason ?: "No reason provided")), action)
}

fun Spec.it(description: String, vararg tags: Tag, action: () -> Unit) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.polymorphicpanda.kspec.config

import io.polymorphicpanda.kspec.context.ExampleContext
import io.polymorphicpanda.kspec.context.Context
import io.polymorphicpanda.kspec.hook.AroundHook
import io.polymorphicpanda.kspec.hook.Chain
import io.polymorphicpanda.kspec.hook.SimpleHook
Expand All @@ -22,15 +22,15 @@ class KSpecConfig {

val filter = FilterConfig()

fun before(vararg tags: Tag, block: (ExampleContext) -> Unit) {
fun before(vararg tags: Tag, block: (Context) -> Unit) {
_before.add(SimpleHook(block, setOf(*tags)))
}

fun after(vararg tags: Tag, block: (ExampleContext) -> Unit) {
fun after(vararg tags: Tag, block: (Context) -> Unit) {
_after.add(SimpleHook(block, setOf(*tags)))
}

fun around(vararg tags: Tag, block: (ExampleContext, Chain) -> Unit) {
fun around(vararg tags: Tag, block: (Context, Chain) -> Unit) {
_around.add(AroundHook(block, setOf(*tags)))
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package io.polymorphicpanda.kspec.context

import io.polymorphicpanda.kspec.tag.Tag
import io.polymorphicpanda.kspec.tag.Taggable
import java.util.*

open class Context(val description: String)
open class Context(val description: String, parent: Taggable?, tags: Set<Tag>): Taggable(parent, tags)

class ExampleGroupContext(description: String,
val parent: ExampleGroupContext?,
tags: Set<Tag> = setOf<Tag>(),
var subjectFactory: () -> Any? = { throw UnsupportedOperationException() })
: Context(description) {
: Context(description, parent, tags) {
internal val children = LinkedList<Context>()

private var subjectInstance: Any? = null
Expand Down Expand Up @@ -41,7 +43,6 @@ class ExampleGroupContext(description: String,
subjectInstance = null
}


companion object {
private fun doVisit(visitor: ContextVisitor, context: Context): ContextVisitResult {
when(context) {
Expand Down Expand Up @@ -70,9 +71,7 @@ class ExampleGroupContext(description: String,

class ExampleContext(description: String, val parent: ExampleGroupContext,
val action: (() -> Unit)?, tags: Set<Tag> = setOf<Tag>())
: Context(description) {

val tags = HashSet<Tag>(tags)
: Context(description, parent, tags) {

init {
parent.children.add(this)
Expand All @@ -82,10 +81,4 @@ class ExampleContext(description: String, val parent: ExampleGroupContext,
parent.reset()
action!!()
}

fun contains(vararg tags: Tag): Boolean = this.tags.any { tags.contains(it) }

fun contains(tags: Collection<Tag>): Boolean = this.tags.any { tags.contains(it) }

operator fun get(tag: String): Tag? = tags.firstOrNull { it.name == tag }
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package io.polymorphicpanda.kspec.filter

import io.polymorphicpanda.kspec.config.KSpecConfig
import io.polymorphicpanda.kspec.context.ContextVisitResult
import io.polymorphicpanda.kspec.context.ContextVisitor
import io.polymorphicpanda.kspec.context.ExampleContext
import io.polymorphicpanda.kspec.context.ExampleGroupContext
import io.polymorphicpanda.kspec.context.*
import io.polymorphicpanda.kspec.extension.Extension
import io.polymorphicpanda.kspec.tag.Ignored
import io.polymorphicpanda.kspec.tag.Tag
Expand All @@ -19,9 +16,9 @@ object Filter: Extension {
val match = config.filter.match

if (match.isNotEmpty() && hasMatch(match, root)) {
config.around { example, chain ->
if (example.contains(match)) {
chain.next(example)
config.around { context, chain ->
if (context.contains(match) || (context is ExampleGroupContext && hasMatch(match, context))) {
chain.next(context)
} else {
chain.stop("Not matching include filter")
}
Expand All @@ -31,9 +28,9 @@ object Filter: Extension {
val includes = config.filter.includes

if (includes.isNotEmpty()) {
config.around { example, chain ->
if (example.contains(includes)) {
chain.next(example)
config.around { context, chain ->
if (context.contains(includes) || (context is ExampleGroupContext && hasMatch(includes, context))) {
chain.next(context)
} else {
chain.stop("Not matching include filter")
}
Expand All @@ -43,11 +40,11 @@ object Filter: Extension {
val excludes = config.filter.excludes

if (excludes.isNotEmpty()) {
config.around { example, chain ->
if (!example.contains(excludes)) {
chain.next(example)
config.around { context, chain ->
if (!context.contains(excludes) || (context is ExampleGroupContext && hasMatch(excludes, context))) {
chain.next(context)
} else {
val ignored = example.tags.filterIsInstance(Ignored::class.java).firstOrNull()
val ignored = context.tags.filterIsInstance(Ignored::class.java).firstOrNull()
if (ignored != null) {
chain.stop(ignored.reason)
} else {
Expand All @@ -62,21 +59,20 @@ object Filter: Extension {
fun hasMatch(tags: Set<Tag>, root: ExampleGroupContext): Boolean {
val check = object: ContextVisitor {
var match = false
override fun preVisitExampleGroup(context: ExampleGroupContext): ContextVisitResult {
return ContextVisitResult.CONTINUE
}
override fun preVisitExampleGroup(context: ExampleGroupContext) = hasMatch(context)

override fun postVisitExampleGroup(context: ExampleGroupContext) = ContextVisitResult.CONTINUE

override fun onVisitExample(context: ExampleContext): ContextVisitResult {
override fun onVisitExample(context: ExampleContext) = hasMatch(context)

private fun hasMatch(context: Context): ContextVisitResult {
match = tags.any {
context.contains(it)
}

if (match) {
return ContextVisitResult.TERMINATE
}

return ContextVisitResult.CONTINUE
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package io.polymorphicpanda.kspec.hook

import io.polymorphicpanda.kspec.context.ExampleContext
import io.polymorphicpanda.kspec.context.Context
import io.polymorphicpanda.kspec.tag.Tag

/**
* @author Ranie Jade Ramiso
*/
class AroundHook(val block: (ExampleContext, Chain) -> Unit, tags: Set<Tag>): Hook(tags) {
fun execute(example: ExampleContext, chain: Chain) {
block(example, chain)
class AroundHook(val block: (Context, Chain) -> Unit, tags: Set<Tag>): Hook(tags) {
fun execute(context: Context, chain: Chain) {
block(context, chain)
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package io.polymorphicpanda.kspec.hook

import io.polymorphicpanda.kspec.context.ExampleContext
import io.polymorphicpanda.kspec.context.Context

/**
* @author Ranie Jade Ramiso
*/
abstract class Chain(val list: List<AroundHook>) {
var iterator = list.iterator()

fun next(example: ExampleContext) {
iterator.next().execute(example, this)
fun next(context: Context) {
iterator.next().execute(context, this)
}

abstract fun stop(reason: String)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package io.polymorphicpanda.kspec.hook

import io.polymorphicpanda.kspec.context.ExampleContext
import io.polymorphicpanda.kspec.context.Context
import io.polymorphicpanda.kspec.tag.Tag

/**
* @author Ranie Jade Ramiso
*/
abstract class Hook(val tags: Set<Tag>) {
fun handles(example: ExampleContext): Boolean {
return example.tags.containsAll(tags)
fun handles(context: Context): Boolean {
return context.tags.containsAll(tags)
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package io.polymorphicpanda.kspec.hook

import io.polymorphicpanda.kspec.context.ExampleContext
import io.polymorphicpanda.kspec.context.Context
import io.polymorphicpanda.kspec.tag.Tag

/**
* @author Ranie Jade Ramiso
*/
class SimpleHook(val block: (ExampleContext) -> Unit, tags: Set<Tag>): Hook(tags) {
fun execute(example: ExampleContext) {
block(example)
class SimpleHook(val block: (Context) -> Unit, tags: Set<Tag>): Hook(tags) {
fun execute(context: Context) {
block(context)
}
}