expect-kt
expect-kt is a set of fluent assertions for Kotlin, for a better readability of your code than using kotlin.test
. Each type has a set
of extension functions that allow you to check certain specifics that relate to that type.
This project is a fork of https://github.com/kouphax/expect.kt. That project was abandoned (since 2012 without commits) and lacking a way to use with Gradle/maven. I updated it so I can use on some projects, and hope to improve some areas and add new features (like better messages and new extensions).
This is too a way for me to understand Kotlin and explore its features. The original project was inspired by FluentAssertions for .NET and now I’m inpired by AssertJ too.
- Gradle dependency
- Syntax
- Chaining
- Standard Assertions
- Logic Assertions
- String Assertions
- toBeEmpty/beEmpty
- toNotBeEmpty/beNotEmpty
- toHaveLength/haveLength
- toBeBlank/beBlank
- toNotBeBlank/notBeBlank
- toBeEquivalentTo/beEquivalentTo
- toStartWith/startWith
- toStartWithEquivalent/startWithEquivalent
- toEndWith/endWith
- toEndWithEquivalent/endWithEquivalent
- toContain/contain
- toContainEquivalent/containEquivalent
- toNotContain/notContain
- toNotContainEquivalent/notContainEquivalent
- toMatch/match
- Numeric Assertions (currently Int, Long, Double, Float)
- Collection Assertions (currently List)
- Extending expect-kt
Syntax
expect-kt allows you to use two different approaches to define an assertion:
Expect Syntax
Expect syntax offers typical expect(something).toBeInACertainState
style of grammar that everybody uses. Like this:
expect("james").toBe("james")
Fluent Syntax
It is also possible to use a more fluent syntax (some kind of BDD) to make the same assertion
"james".should.be("james")
Chaining
expect-kt allows you to chain assertions to keep things really neat and tidy.
expect("james").toStartWith("j").and.toEndWith("s")
Or, in fluent syntax.
"james".should.startWith("j").and.endWith("s")
Or using blocks, because sometimes you want lots of checks.
expect("james") {
toStartWith("j")
toEndWith("s")
}
"james".should {
startWith("j")
endWith("s")
}
Standard Assertions
There are a few assertions that can be used on any type
toBe/be
Assert that the value should be equal to the other
expect("james").toBe("james")
"james".should.be("james")
toNotBe/notBe
Assert that the value should NOT be equal the other
expect("james").toNotBe("jaime")
"james".should.notBe("jaime")
toNotBeNull/notBeNull
Assert that the value is NOT null
expect("james").toNotBeNull()
"james".should.notBeNull()
toBeInstanceOf/beInstanceOf
Assert that the value should of some class.
expect("james").toBeInstanceOf(String::class)
expect(SomeTestClass()).toBeInstanceOf(SomeTestClass::class)
"james".should.beInstanceOf(String::class)
It does not work very well with numbers (Int, Float, …)
Logic Assertions
toNotBeTrue/notBeTrue
Assert that the value is NOT true
expect(false).toNotBeTrue()
false.should.notBeTrue()
toNotBeFalse/notBeFalse
Assert that the value is NOT false
expect(true).toNotBeFalse()
true.should.notBeFalse()
String Assertions
toNotBeEmpty/beNotEmpty
Assert that a string is NOT empty ("")
expect(" ").toNotBeEmpty()
" ".should.beNotEmpty()
toHaveLength/haveLength
Assert that a string is of a certain length
expect("james").toHaveLength(5)
"james".should.haveLength(5)
toBeBlank/beBlank
Assert that a string is blank, in that it is empty or contains only whitespace
expect(" ").toBeBlank()
" ".should.beBlank()
toNotBeBlank/notBeBlank
Assert that a string is not blank, in that it isn’t empty or contains more than whitespace
expect("james").toNotBeBlank()
"james".should.notBeBlank()
toBeEquivalentTo/beEquivalentTo
Assert that a string is equal to another string regardless of case (ignore case comparation)
expect("JAMES").toBeEquivalentTo("james")
"JAMES".should.beEquivalentTo("james")
toStartWith/startWith
Assert that a string starts with another string.
expect("james").toStartWith("j")
"james".should.startWith("j")
toStartWithEquivalent/startWithEquivalent
Assert that a string starts with another string regardless of case.
expect("james").toStartWithEquivalent("JA")
"james".should.startWithEquivalent("JA")
toEndWith/endWith
Assert that a string ends with another string
expect("James").toEndWith("es")
"James".should.endWith("es")
toEndWithEquivalent/endWithEquivalent
Assert that a string ends with another string regardless of case
expect("JAMES").toEndWithEquivalent("es")
"JAMES".should.endWithEquivalent("es")
toContain/contain
Assert that a string contains another string
expect("james").toContain("am")
"james".should.contain("am")
toContainEquivalent/containEquivalent
Assert that a string contains another string regardless of case.
expect("JAMES").toContainEquivalent("am")
"JAMES".should.containEquivalent("am")
toNotContain/notContain
Assert that a string doesn’t contain another string.
expect("james").toNotContain("ei")
"james".should.notContain("ei")
toNotContainEquivalent/notContainEquivalent
Assert that a string doesn’t contain another string regardless of case.
expect("JAMES").toNotContainEquivalent("ei")
"JAMES".should.notContainEquivalent("ei")
toMatch/match
Assert that a string matches the given regex.
expect("james").toMatch(Regex("^james$"))
"james".should.match(Regex("^james$"))
Numeric Assertions (currently Int, Long, Double, Float)
toBeGreaterOrEqualTo/beGreaterOrEqualTo
Assert that a number is greater than or equal to another
expect(2).toBeGreaterOrEqualTo(1)
2.should.beGreaterOrEqualTo(1)
toBeGreaterThan/beGreaterThan
Assert that a number is greater than to another
expect(2).toBeGreaterThan(1)
2.should.beGreaterThan(1)
toBeLessOrEqualTo/beLessOrEqualTo
Assert that a number is less than or equal to another
expect(1).toBeLessOrEqualTo(2)
1.should.beLessOrEqualTo(2)
toBeLessThan/beLessThan
Assert that a number is less than to another
expect(1).toBeLessThan(2)
1.should.beLessThan(2)
toBeInRange/beInRange
Assert that a number is within the lower and upper bounds passed in
expect(2).toBeInRange(1, 3)
2.should.beInRange(1, 3)
toBeApproximately/beApproximately
Assert that a number is approximately another - the level of error is defined by the tolerance value (+/- tolerance)
expect(2f).toBeApproximately(2.1f, 0.1f)
2f.should.beApproximately(2.1f, 0.1f)
Collection Assertions (currently List)
toBeEmpty
Assert that the list don’t have any items
expect(listOf<String>()).toBeEmpty()
listOf<String>().should.beEmpty()
toNotBeEmpty
Assert that the list contain items
expect(listOf("james")).toNotBeEmpty()
listOf("james").should.notBeEmpty()
toHaveSize
Assert that the list contains x items
expect(listOf("james", "cindy")).toHaveSize(2)
listOf("james", "cindy").should.haveSize(2)
toHaveSameSizeAs
Assert that the list contains the same of items as other list (same type or not)
expect(listOf("james", "cindy")).toHaveSameSizeAs(listOf(1, 2))
listOf("james", "cindy").should.haveSameSizeAs(listOf(1, 2))
toContain
Assert that the list contains this item
expect(listOf("james", "cindy")).toContain("james")
listOf("james", "cindy").should.contain("james")
toContainAll
Assert that the list contains all this items
expect(listOf("james", "cindy")).toContainAll(listOf("james"))
listOf("james", "cindy").should.containAll(listOf("james"))
toContainNull
Assert that the list contains a null value
expect(listOf("james", null)).toContainNull()
listOf("james", null).should.containNull()
toNotContainNull
Assert that the list does not contain null
expect(listOf("james", "cindy")).toNotContainNull()
listOf("james", "cindy").should.notContainNull()
toNotContain
Assert that the list does not contain this item
expect(listOf("james", "cindy")).toNotContain("tsu")
listOf("james", "cindy").should.notContain("tsu")
toNotContainAny
Assert that the list does not contain any of these items
expect(listOf("james", "cindy")).toNotContainAny(listOf("tsu"))
listOf("james", "cindy").should.notContainAny(listOf("tsu"))
anyToMatchLambda
Assert that the list contains any item that matches the lambda (predicate)
expect(listOf(1, 2)).anyToMatchLambda { it > 1 }
listOf(1, 2).should.anyMatchLambda { it > 1 }
allToMatchLambda
Assert that all items in the list matches the lambda (predicate)
expect(listOf(2, 4, 6)).allToMatchLambda { it.mod(2) == 0 }
listOf(2, 4, 6).should.allMatchLambda { it.mod(2) == 0 }
noneToMatchLambda
Assert that the list does not have any item that matches the lambda (predicate)
expect(listOf(1, 2)).noneToMatchLambda { it > 2 }
listOf(1, 2).should.noneMatchLambda { it > 2 }
toStartWith
Assert that the list first item is this
expect(listOf("james", "cindy")).toStartWith("james")
listOf("james", "cindy").should.startWith("james")
toEndWith
Assert that the list last item is this
expect(listOf("james", "cindy")).toEndWith("cindy")
listOf("james", "cindy").should.endWith("cindy")
toHaveItemAt
Assert that the list have a specific item at a position
expect(listOf("james", "cindy")).toHaveItemAt("cindy", 1)
listOf("james", "cindy").should.haveItemAt("cindy", 1)
toHaveInstanceOfItemAt
Assert that the list contains an instance of this class at that index
expect(listOf("james", 1)).toHaveInstanceOfItemAt(String::class, 0)
listOf("james", 1).should.haveInstanceOfItemAt(String::class, 0)
toNotContainDuplicates
Assert that the list does not contains duplicated items
expect(listOf("james", "cindy")).toNotContainDuplicates()
listOf("james", "cindy").should.notContainDuplicates()
toBeSubsetOf
Assert that this list is a subset of another list
expect(listOf("james", "cindy")).toBeSubsetOf(listOf("james", "cindy", "tsu", "aphrodite"))
listOf("james", "cindy").should.beSubsetOf(listOf("james", "cindy", "tsu", "aphrodite"))
Extending expect-kt
Expectations in expect-kt are extension functions to Expectation
and Should
. If you want a expectation function that don’t already exist, you can create one in your files as this:
fun Expectation<Type>.toBeSomething(something: Type): ExpectationChain<Type> {
assertTrue(target.doSomething())
return ExpectationChain(this)
}
fun Should<Type>.beSomething(something: Type): ShouldChain<Type> {
expectation.toBeSomething(value)
return ShouldChain(this)
}
Where:
-
Type
is the class you are testing. For example: Int, String, User (your own class), List<T> -
target
is the object ofType
that your expectation will run against -
Your method should return a ExpectationChain/ShouldChain for that type, so you can chain your calls
-
Your method can receive any number and any type of parameters
-
Should
extensions usually just callExpectation
methods becauseShould
is a sugar aroundExpectation
anyway.
You can check CustomExpectationTests.kt to see an example.