Created
June 11, 2018 07:36
-
-
Save Lamartio/de6b3ab70084f5a6e91c9f077b22b526 to your computer and use it in GitHub Desktop.
Simplified Spek for creating tests without the need of additional dependencies
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private val Store<Car>.frontLeftWheel: Wheel | |
get() = getState().wheels.entries.first { it.key == Position.FRONT_LEFT }.value | |
class ChangeWheelFeature : Feature({ | |
lateinit var store: Store<Car> | |
given("the wheel is a 15 inch one") { | |
setUp { store = newStore() } | |
on("changing the wheel with a bigger one") { | |
WheelAction.Change(Position.FRONT_LEFT, 17).let(store::dispatch) | |
it("should have a wheel of 17 inch") { store.frontLeftWheel.size shouldBe 17 } | |
} | |
on("changing the wheel with a smaller one") { | |
WheelAction.Change(Position.FRONT_LEFT, 13).let(store::dispatch) | |
it("should have a wheel of 13 inch") { store.frontLeftWheel.size shouldBe 13 } | |
} | |
} | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.hamcrest.Matcher | |
import org.junit.Assert | |
import org.junit.Ignore | |
import org.junit.Test | |
@Ignore | |
open class Feature(private val block: Feature.() -> Unit = {}) : () -> Unit { | |
@Test | |
override fun invoke() { | |
block() | |
} | |
} | |
infix fun <T> T.shouldBe(expected: T) = Assert.assertEquals(expected, this) | |
infix fun <T> T.shouldBe(expected: Matcher<T>) = Assert.assertThat(this, expected) | |
fun given(text: String, block: Given.() -> Unit) { | |
Given(text, block) | |
} | |
class Given internal constructor( | |
text: String, | |
block: Given.() -> Unit = {} | |
) : FeatureComponent("\n\nGiven $text") { | |
private var setUp: Given.() -> Unit = {} | |
private var tearDown: Given.() -> Unit = {} | |
init { | |
block() | |
} | |
fun setUp(block: Given.() -> Unit) { | |
setUp = setUp.let { previous -> { previous(); block() } } | |
} | |
fun tearDown(block: Given.() -> Unit) { | |
tearDown = tearDown.let { previous -> { previous(); block() } } | |
} | |
fun on(text: String, block: On.() -> Unit = {}): On = | |
On(this, setUp, tearDown, text, block).also { conditions.add(it) } | |
override fun toString(): String = "$text\n\n${super.toString()}" | |
} | |
class On internal constructor( | |
private val given: Given, | |
setUp: Given.() -> Unit = {}, | |
tearDown: Given.() -> Unit = {}, | |
text: String, | |
block: On.() -> Unit = {} | |
) : FeatureComponent(text = "On $text") { | |
init { | |
given.run { | |
setUp() | |
block() | |
tearDown() | |
} | |
} | |
fun it(text: String, block: It.() -> Unit = {}): It = | |
It(this, text, block).also { conditions.add(it) } | |
override fun toString(): String = "$given\n$text\n${super.toString()}" | |
} | |
class It internal constructor( | |
private val on: On, | |
text: String, | |
block: It.() -> Unit = {} | |
) : FeatureComponent(text = "It $text") { | |
init { | |
try { | |
block() | |
} catch (error: AssertionError) { | |
throw AssertionError(toString(), error) | |
} | |
} | |
override fun toString(): String = "$on\n$text\n${super.toString()}" | |
} | |
open class FeatureComponent internal constructor( | |
protected val text: String, | |
private val depth: Int = 0 | |
) { | |
protected val conditions: MutableList<FeatureComponent> = mutableListOf() | |
fun and(text: String): FeatureComponent = | |
apply { conditions.add(FeatureComponent("And $text", depth + 1)) } | |
fun or(text: String): FeatureComponent = | |
apply { conditions.add(FeatureComponent("Or $text", depth + 1)) } | |
override fun toString(): String = | |
flattenConditions() | |
.toMutableList() | |
.also { it.add(this) } | |
.joinToString( | |
separator = "\n", | |
transform = { getIndent(it.depth) + it.text } | |
) | |
private fun getIndent(depth: Int) = | |
0.until(depth) | |
.map { "\t" } | |
.toMutableList() | |
.apply { add("") } | |
.reduce { acc, s -> acc + s } | |
private fun flattenConditions(): List<FeatureComponent> = | |
conditions + conditions.flatMap { | |
if (it.conditions.isNotEmpty()) it.flattenConditions() | |
else emptyList() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment