Migrating to 2.x
This section will guide you through migrating 1.x
tests to 2.x
.
Both versions implement (albeit differently) a JUnit Platform TestEngine
. 1.x
has an unique id (engine name) spek
while 2.x
has spek2
, this allows having 1.x
and 2.x
tests in the same project.
Sample configuration for a gradle based project
test { useJUnitPlatform { includeEngines 'spek', 'spek2', 'some-other-test-engine' } }
Maven coordinates¶
The table below shows the equivalent 1.x
and 2.x
artifacts.
1.x | 2.x |
---|---|
org.jetbrains.spek:spek-api |
org.spekframework.spek2:spek-dsl-jvm |
org.jetbrains.spek:spek-junit-platform-engine |
org.spekframework.spek2:spek-runner-junit5 |
Base package¶
The base package is now org.spekframework.spek2
, but since most of the API has change it's not easy as replacing
org.jetbrains.spek
with the new base package.
DSL changes¶
2.x
introduces two distinct and completely isolated testing styles: specification
and gherkin
, mixing and matching
different synonyms is not allowed.
describe, context, it¶
This 1.x
style is the most straightforward to migrate, adding an import to
org.spekframework.spek2.specification.describe
should work in most cases. However, a major difference is context
and it
are not allowed in the root
scope, you have to either wrap them in a describe
or for context
rename it to describe
.
object SetSpec: Spek({ val set by memoized { mutableSetOf<String>() } context("is empty") { it("should have a size of 0") { assertEquals(0, set.size) } it("should throw when first is invoked") { assertFailsWith(NoSuchElementException::class) { set.first() } } } })
For example, the 2.x
equivalent for the test above is:
import org.spekframework.spek2.style.specification.describe import org.spekframework.spek2.Spek object SetSpec: Spek({ describe("A set") { val set by memoized { mutableSetOf<String>() } context("is empty") { it("should have a size of 0") { assertEquals(0, set.size) } it("should throw when first is invoked") { assertFailsWith(NoSuchElementException::class) { set.first() } } } } })
given, on, it¶
2.x
introduces a complete gherkin like DSL and this style is roughly equivalent to it.
object SetSpek: Spek({ val set by memoized { ... } // testing side-effects given("an empty set)" { beforeEachTest { // assume(list.isEmpty()) } on("set.size") { val size = set.size it("should have a size of 0") { assertEquals(0, size) } } on("set.first()") { it("should throw an exception") { assertFailsWith(NoSuchElementException::class) { set.first() } } } on("adding items") { set.add("foo") it("should have a size of 1") { assertEquals(1, set.size) } it("should contain foo") { assertTrue(set.contains("foo")) } } } // testing a return value given("a set with one item") { val item = "foo" beforeEachTest { set.add(item) } on("getting the first item") { val result = set.first() it("should return the first item") { assertEquals(item, result) } } } })
The test above is equivalent to:
object SetFeature: Spek({ Feature("Set") { val set by memoized { mutableSetOf<String>() } Scenario("adding items") { When("adding foo") { set.add("foo") } Then("it should have a size of 1") { assertEquals(1, set.size) } Then("it should contain foo") { assertTrue(set.contains("foo")) } } Scenario("empty") { Given("an empty set") { // assume(set.isEmpty()) } Then("should have a size of 0") { assertEquals(0, set.size) } Then("should throw when first is invoked") { assertFailsWith(NoSuchElementException::class) { set.first() } } } Scenario("getting first item") { val item = "foo" Given("a non-empty set") { set.add(item) } lateinit var result: String When("getting the first item") { result = set.first() } Then("it should return the first item") { assertEquals(item, result) } } } })
Dropped extensions¶
Subjects¶
For tests not using include
, just replace subject { ... }
to memoized { ... }
.
object CalculatorTest: Spek({ val subject by memoized { Calculator() } ... })
If you do use include
, you can now use memoized
to reference scope values declared earlier.
object CalculatorSpecs: Spek({ fun Suite.behavesLikeACalculator() { val calculator by memoized<Calculator>() it("1 + 2 = 3") { assertEquals(3, calculator.add(1, 2)) } } describe("Calculator") { val calculator by memoized { Calculator() } behavesLikeACalculator() } describe("AdvancedCalculator") { val calculator by memoized { AdvancedCalculator() } behavesLikeACalculator() it("2 ^ 3 = 8") { assertEquals(8, calculator.pow(2, 3)) } } })