• Stars
    star
    753
  • Rank 60,280 (Top 2 %)
  • Language
    Kotlin
  • License
    MIT License
  • Created over 7 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

assertions for kotlin inspired by assertj

assertk

CircleCI Maven Central Sonatype Snapshot

assertk is a fluent assertion library for Kotlin inspired by AssertJ.

Why another assertion library?

You might be asking, "If AssertJ already exists, why create another library?". It's true, assertk is very similar to AssertJ. But assertk is written in Kotlin so it has one major advantage: extension methods. This makes adding your own assertion methods far simpler.

See Custom Assertions below to find out how to do this.

Setup

repositories {
  mavenCentral()
}

dependencies {
  testImplementation("com.willowtreeapps.assertk:assertk:0.26.1")
}

assertk has full multiplatform support and it can be used in jvm, js, or native projects. For example to set it up using the multiplatform plugin:

plugins {
  kotlin("multiplatform")
}

kotlin {
  sourceSets {
    val commonTest by getting {
      dependencies {
        implementation("com.willowtreeapps.assertk:assertk:0.26.1")
      }
    }
  }
}

Usage

Simple usage is to wrap the value or property you are testing in assertThat() and call assertion methods on the result.

import assertk.assertThat
import assertk.assertions.*

class PersonTest {
    val person = Person(name = "Bob", age = 18)

    @Test
    fun testName() {
        assertThat(person.name).isEqualTo("Alice")
        // -> expected:<["Alice"]> but was:<["Bob"]>
    }

    @Test
    fun testAge() {
        assertThat(person.age, "age").isGreaterThan(20)
        // -> expected [age] to be greater than:<20> but was:<18>
    }

    @Test
    fun testNameProperty() {
        assertThat(person::name).isEqualTo("Alice")
        // -> expected [name]:<["Alice"]> but was:<["Bob"]>
    }
}

You can see all built-in assertions in the docs.

Nullability

Since null is a first-class concept in kotlin's type system, you need to be explicit in your assertions.

val nullString: String? = null
assertThat(nullString).hasLength(4)

will not compile, since hasLength() only makes sense on non-null values. You can chain isNotNull() to handle this.

val nullString: String? = null
assertThat(nullString).isNotNull().hasLength(4)
// -> expected to not be null

This will first ensure the string is not null before running any other checks.

Multiple assertions

You can assert multiple things on a single value by providing a lambda as the second argument. All assertions will be run even if the first one fails.

val string = "Test"
assertThat(string).all {
    startsWith("L")
    hasLength(3)
}
// -> The following 2 assertions failed:
//    - expected to start with:<"L"> but was:<"Test">
//    - expected to have length:<3> but was:<"Test"> (4)

You can wrap multiple assertions in an assertAll to ensure all of them get run, not just the first one.

assertAll {
    assertThat(false).isTrue()
    assertThat(true).isFalse()
}
// -> The following 2 assertions failed:
//    - expected to be true
//    - expected to be false

Iterable/List Assertions

You can assert on the contents of an Iterable/List with the various contains* functions. They have different semantics as follows:

Assertion Description
containsAll Asserts the iterable contains all the expected elements, in any order. The collection may also contain additional elements.
containsSubList Asserts that a collection contains a subset of items the same order, but may have additional elements in the list.
containsOnly Asserts the iterable contains only the expected elements, in any order. Duplicate values in the expected and actual are ignored.
containsExactlyInAnyOrder Asserts the iterable contains exactly the expected elements, in any order. Each value in expected must correspond to a matching value in actual, and visa-versa.
containsExactly Asserts the list contains exactly the expected elements. They must be in the same order and there must not be any extra elements.
containsNone Asserts the iterable does not contain any of the expected elements

Extracting data

There's a few ways you extract the data you want to assert on. While you can do this yourself before calling the assertion, these methods will add the extra context to the failure message which can be helpful.

The simplest way is with prop(). It will take a property (or function, or a name and a lambda) and return an assertion on that property.

val person = Person(age = 22)
assertThat(person).prop(Person::age).isEqualTo(20)

// -> expected [age]:<2[0]> but was:<2[2]> (Person(age=22))

For collections, you can use index() to pull a specific index from a list, and key() to pull a specific value from a map.

assertThat(listOf(1, 2, 3)).index(1).isEqualTo(1)

// -> expected: [[1]]:<1> but was:<2> ([1, 2, 3])

assertThat(mapOf("one" to 1, "two" to 2, "three" to 3)).key("two").isEqualTo(1)

// -> expected: [["two"]]:<1> but was:<2> ({"one"=1, "two"=2, "three"=3})

You can also extract a property from a collection using extracting().

val people = listOf(Person(name = "Sue"), Person(name = "Bob"))
assertThat(people)
    .extracting(Person::name)
    .containsExactly("Sue", "Bob")

Exceptions

If you expect an exception to be thrown, you can use assertFailure which takes a lambda.

assertFailure {
    throw Exception("error")
}.hasMessage("wrong")
// -> expected [message] to be:<["wrong"]> but was:<["error"]>

Table Assertions

If you have multiple sets of values you want to test with, you can create a table assertion.

tableOf("a", "b", "result")
    .row(0, 0, 1)
    .row(1, 2, 4)
    .forAll { a, b, result ->
        assertThat(a + b).isEqualTo(result)
    }
// -> the following 2 assertions failed:
//    on row:(a=<0>,b=<0>,result=<1>)
//    - expected:<[1]> but was:<[0]>
//    on row:(a=<1>,b=<2>,result=<4>)
//    - expected:<[4]> but was:<[3]>

Up to 4 columns are supported.

Custom Assertions

One of the goals of this library is to make custom assertions easy to make. All assertions are just extension methods.

fun Assert<Person>.hasAge(expected: Int) {
    prop(Person::age).isEqualTo(expected)
}

assertThat(person).hasAge(20)
// -> expected [age]:<2[0]> but was:<2[2]> (Person(age=22))

For completely custom assertions, you have a few building blocks. given will give you the actual value to assert on, and expected() and show() will help you format your failure message.

fun Assert<Person>.hasAge(expected: Int) = given { actual ->
    if (actual.age == expected) return
    expected("age:${show(expected)} but was age:${show(actual.age)}")
}

assertThat(person).hasAge(20)
// -> expected age:<20> but was age:<22>

You can also build assertions that chain by using transform. This allows you to both assert on the actual value, and return something more specific that additional assertions can be chained on.

fun Assert<Person>.hasMiddleName(): Assert<String> = transform(appendName("middleName", separator = ".")) { actual ->
   if (actual.middleName != null) {
       actual.middleName
   } else {
       expected("to not be null")
   }
}

assertThat(person).hasMiddleName().isEqualTo("Lorie")

// -> expected [middleName]:to not be null

Note: this is a bit of a contrived example as you'd probably want to build this out of existing assertions instead.

fun Assert<Person>.hasMiddleName(): Assert<String> = prop(Person::middleName).isNotNull()

The general rule of thumb is to prefer building out of the existing assertions unless you can give a more meaningful error message.

Contributing to assertk

Contributions are more than welcome! Please see the Contributing Guidelines and be mindful of our Code of Conduct.

More Repositories

1

spruce-android

Spruce Animation Library
Java
3,716
star
2

spruce-ios

Swift library for choreographing animations on the screen.
Swift
3,438
star
3

Hyperion-iOS

In-app design review tool to inspect measurements, attributes, and animations.
Objective-C
2,047
star
4

Hyperion-Android

App Debugging & Inspection Tool for Android
Java
1,946
star
5

sign-in-with-apple-button-android

An Android library for Sign In with Apple
Kotlin
280
star
6

vocable-android

Vocable for Android
Kotlin
115
star
7

OAK

Library to address common hurdles in Android development
Java
110
star
8

android-instant-apps-demo

Java
108
star
9

fuzzywuzzy-kotlin

Fuzzy string matching for Kotlin (JVM, native, JS, Web Assembly) - port of Fuzzy Wuzzy Python lib
Kotlin
78
star
10

vocable-ios

Vocable AAC for iOS - Empowering people to communicate with care takers and loved ones.
Swift
78
star
11

cordux

Swift
61
star
12

scratch

Easy app data clearing and relaunching
Java
57
star
13

ukor

A Roku build tool with support for build flavors
Brightscript
49
star
14

ouroboros

Infinitely scrolling carousel for tvOS
Swift
48
star
15

wist

A linter for BrightScript
C++
43
star
16

rocute

beautiful ui components for roku development
Brightscript
37
star
17

rootx

Wrap sqlx in even more convenience
Go
37
star
18

PinkyPromise

A tiny Promises library.
Swift
33
star
19

trafficcop

Monitor your Android apps' data usage so you can take action if it's over a threshold.
Java
27
star
20

BlurredVideo-iOS

Applying a blur to a HTTP live stream
Swift
27
star
21

SimpleRecyclerViewDemo

A simple Android application demonstrating the RecyclerView/Adapter/ViewHolder pattern.
Java
26
star
22

react-formable

React Forms
TypeScript
25
star
23

lottie-player

A mac based player for Lottie
Swift
22
star
24

opentest4k

kotlin multiplatform implementation/bindings of opentest4j
Kotlin
20
star
25

android-svg-test

Android SVG sample project to demonstrate OAK's AnimatedSvgView
Java
17
star
26

hello-shared-kotlin

Shared kotlin lib between android and ios
Kotlin
16
star
27

WillowTreeScrollingTabController

Tab based container implementation for iOS written in Swift
Swift
12
star
28

catalyst-slack-service

Unconscious gender bias has been fueling the gender gap for far too long. Weโ€™re releasing the #BiasCorrect code in hopes that coders around the world will adapt it for whatever chat-based platforms they use in order to give more people access to this tool for change.
Java
12
star
29

tablediff

Swift
11
star
30

hinoki

A Language Server Protocol implementation for BrightScript
TypeScript
10
star
31

rokul-runnings

Roku Automation, written in TypeScript
TypeScript
10
star
32

wombats-api

Wombats API
Clojure
10
star
33

grove

Swift
8
star
34

WillowTreeReachability

Simple Swift class for monitoring network reachability.
Swift
6
star
35

fastlane-plugin-msbuild

MSBuild / Xamarin actions for Fastlane
Ruby
6
star
36

conductor-mobile

Conductor Mobile is a port of the Conductor Web Framework for iOS and Android
Java
6
star
37

dockertestapp

basic android app for usage in docker
Kotlin
5
star
38

vscode-ide-brightscript

Brightscript support for vscode
TypeScript
5
star
39

Sweetgum

A simple REST client built in C# using Avalonia
C#
5
star
40

palette-vs-the-dress

Java
4
star
41

wombats-web-client

Web Client for Wombats
Clojure
4
star
42

catalyst-bias-correct-service

A bias correction service
Java
4
star
43

acorn

Provides helper functionality for writing code generators (specifically for Go, in Go)
Go
4
star
44

bark

Swift
4
star
45

namegame_ios

The Name Game for iOS
3
star
46

wat-test-project

A bare skeleton for prospective WAT members to pick at.
3
star
47

xambuild

Build Xamarin projects outside of Visual Studio!
Python
3
star
48

intro-to-core-ml

An introduction to Core ML.
Swift
3
star
49

ios-google-home-demo

Swift
3
star
50

IntroiOSExamples

A group of examples that are used for the WillowTree Intro to iOS Course
Swift
3
star
51

atom-ide-brightscript

TypeScript
3
star
52

iot-android-things-robot-arm

Kotlin
2
star
53

namegame_android

2
star
54

Sweetgum.Client

Sweetgum assists in the development and testing of APIs and applications that utilize APIs.
TypeScript
2
star
55

AXComponentKit

Experimental framework for more reliable iOS automation tests
Swift
2
star
56

capwic_event_info

Swift
1
star
57

slacksnax-server

JavaScript
1
star
58

friday-shots

Friday Shots rules, game runner, and results data
Python
1
star
59

battlebots-swift-front-end

A swift framework for building a BattleBots front-end.
Swift
1
star
60

smart-speaker-detector-sample-android

Finds an assortment of smart speakers
Kotlin
1
star
61

android-bootcamp

Sample app for Android bootcamp and associated issue tracking
Java
1
star
62

wombats-ios

iOS Frontend client for Wombats
Swift
1
star
63

namegame-cs

Name Game skeleton project for C#
1
star
64

slacksnax-slackCommand

JavaScript
1
star
65

wta-lighthouse-logger

JavaScript
1
star
66

code-analysis-web

HTML
1
star
67

maple-mosaic

Our in-office Lego wall - scripts for building out the images and printouts.
JavaScript
1
star
68

wombats-documentation

Wombat's API Documentation
JavaScript
1
star