diff --git a/build.gradle b/build.gradle index 89dd0212..e00e0ddc 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.1.+' + ext.kotlin_version = '1.2.+' ext.spek_version = "1.0.+" ext.mockito_version = "1.5.+" repositories { @@ -110,3 +110,9 @@ publishing { } } } + +compileTestKotlin { + kotlinOptions { + apiVersion = "1.2" + } +} diff --git a/docs/DefineOwn.md b/docs/DefineOwn.md new file mode 100644 index 00000000..549d2ee1 --- /dev/null +++ b/docs/DefineOwn.md @@ -0,0 +1,18 @@ +# Define own assertions + +Starting with Kluent 1.32, a generic `should` method was added to build domain specific assertions. + +When the receiver function passed to `should` returns `false` *or* throws an exception, it will fail with an optional failure message. + +## Example + +```kt +data class Person(val name: String, val surname: String) + +fun Person.shouldHaveUppercaseName() = this.should("The name of $this should be uppercase") { + name[0].isUpperCase() +} + + +Person("Pan", "Peter").shouldHaveUppercaseName() +``` \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index f702b759..efc505fa 100644 --- a/docs/README.md +++ b/docs/README.md @@ -25,6 +25,8 @@ It uses the [Infix-Notations](https://kotlinlang.org/docs/reference/functions.ht [FileSystem](FileSystem.md) +[Define own assertions](DefineOwn.md) + ## Using backticks Every method that is included in Kluent also has a "backtick version", to make it feel more like a describing sentence. @@ -33,13 +35,18 @@ Some examples: ### assertEquals ## "hello" shouldEqual "hello" + "hello".shouldEqual("hello") "hello" `should equal` "hello" ### assertNotEquals ## "hello" shouldNotEqual "world" + "hello".shouldNotEqual("world") "hello" `should not equal` "world" # Changelog +# 1.32 (WIP) +* Support lambda logic assertion | [Issue](https://github.com/MarkusAmshove/Kluent/issues/77) | [PR](https://github.com/MarkusAmshove/Kluent/pull/81) | Issue by [@goreRatzete](https://github.com/goreratzete) + # 1.31 * Expect an Exception instance to be thrown compared by equals | [PR](https://github.com/MarkusAmshove/Kluent/pull/78) | thanks to [@nhellwig](https://github.com/nhellwig) diff --git a/src/main/kotlin/org/amshove/kluent/Basic.kt b/src/main/kotlin/org/amshove/kluent/Basic.kt index 10cd62e8..a62b67c1 100644 --- a/src/main/kotlin/org/amshove/kluent/Basic.kt +++ b/src/main/kotlin/org/amshove/kluent/Basic.kt @@ -5,7 +5,7 @@ import kotlin.reflect.KClass infix fun Any?.shouldEqual(theOther: Any?) = assertEquals(theOther, this) -infix fun Any?.shouldNotEqual(theOther: Any?) = assertNotEquals(theOther, this) +infix fun Any?.shouldNotEqual(theOther: Any?) = assertNotEquals(theOther, this) infix fun Any?.shouldBe(theOther: Any?) = assertSame(theOther, this) @@ -25,8 +25,21 @@ fun Any?.shouldNotBeNull() = assertNotNull(this) fun Boolean.shouldBeTrue() = assertTrue(this) -fun Boolean.shouldBeFalse() = assertFalse(this) +fun Boolean.shouldBeFalse() = assertFalse(this) fun Boolean.shouldNotBeTrue() = this.shouldBeFalse() fun Boolean.shouldNotBeFalse() = this.shouldBeTrue() + +infix fun T.should(assertion: T.() -> Boolean) = should("Expected the assertion to return true, but returned false", assertion) + +fun T.should(message: String, assertion: T.() -> Boolean) = try { + if (assertion()) Unit else fail(message) +} catch (e: Exception) { + fail("""$message + | + | An exception occured: + | ${e::class.qualifiedName}: ${e.message} + | ${"\tat "}${e.stackTrace.joinToString("\n\tat ")} + """.trimMargin()) +} diff --git a/src/test/kotlin/org/amshove/kluent/tests/assertions/ShouldTests.kt b/src/test/kotlin/org/amshove/kluent/tests/assertions/ShouldTests.kt new file mode 100644 index 00000000..d319aaac --- /dev/null +++ b/src/test/kotlin/org/amshove/kluent/tests/assertions/ShouldTests.kt @@ -0,0 +1,54 @@ +package org.amshove.kluent.tests.assertions + +import org.amshove.kluent.should +import org.amshove.kluent.shouldEqual +import org.amshove.kluent.tests.helpclasses.Person +import org.jetbrains.spek.api.Spek +import kotlin.test.assertFails + +class ShouldTests : Spek({ + given("the should method") { + on("passing a lambda that returns true") { + it("should pass") { + Person("", "") should { name.length == 0 } + } + } + on("passing a lambda that returns false") { + it("should fail") { + assertFails { + Person("", "").should { + name.length > 0 + } + } + } + } + + on("defining a domain specific assertion method") { + fun Person.shouldHaveUppercaseName() = this.should("The name of $this should be uppercase") { + name[0].isUpperCase() + } + + it("should pass when returning true") { + Person("Pan", "Peter").shouldHaveUppercaseName() + } + it("should fail when returning false") { + assertFails { + Person("pan", "peter").shouldHaveUppercaseName() + } + } + it("should fail with the provided message") { + val peter = Person("pan", "peter") + try { + peter.shouldHaveUppercaseName() + } catch (e: AssertionError) { + e.message.shouldEqual("The name of $peter should be uppercase") + } + } + it("should fail when an exception occurs") { + assertFails { + Person("", "").shouldHaveUppercaseName() + } + } + } + } +}) \ No newline at end of file