BDD assertion library for Kotlin

Overview

Expekt Travic CI

Expekt is a (work in progress) BDD assertion library for Kotlin, inspired by Chai.js. It works with your favorite test runner such as JUnit and Spek.

class ExpektTest {
    @Test
    fun helloExpekt() {
        23.should.equal(23)
        "Kotlin".should.not.contain("Scala")
        listOf(1, 2, 3).should.have.size.above(1)
    }
}

Follow on Twitter for updates!

Getting started

Expekt is available via Maven Central. Just add the dependency to your Maven POM or Gradle build config.

Maven
<dependency>
    <groupId>com.winterbe</groupId>
    <artifactId>expekt</artifactId>
    <version>0.5.0</version>
    <scope>test</scope>
</dependency>
Gradle
testCompile "com.winterbe:expekt:0.5.0"

Introduction

Expekt let's you write assertions in natural english language by building fluent sentences in your JUnit tests.

It comes in two flavors should and expect, both exposing the same API. It's up to you which variant to use. The property should is available on any object (e.g. myObject.should), even on null. The function expect accepts any object as parameter (e.g. expect(myObject)) instead.

When using IntelliJ IDEA you can simply use expect and should from classpath. The IDE handles all imports for you. In case you have to handle imports manually, add one of those to your test file:

import com.winterbe.expekt.expect
import com.winterbe.expekt.should

The Expekt API consists of many chainable properties and functions. Properties like to, be and which are provided to improve readibility. They don't serve any semantical meaning. The property not is used to negate expectations. Depending on the type of the initial value plenty of properties and functions are available to assert different aspects of the value, e.g. you can assert that a collection contains some elements, that a number is within it's bounds or that a string matches a given regex pattern.

See API doc for all available assertion properties and functions.

What happens when expectations fail?

When an expectation fails Expekt throws a java.lang.AssertionError containing a readable message, so you can easily see what's going wrong.

class FailingTest {
    @Test
    fun thisTestFails() {
        3.4.should.be.closeTo(3.2, delta = 0.1)
    }
}

The above test fails, resulting in the following exception:

java.lang.AssertionError: 3.4 should be closeTo 3.2 ±0.1

	at com.winterbe.expekt.ExpectAny.fail(ExpectAny.kt:77)
	at com.winterbe.expekt.ExpectAny.verify(ExpectAny.kt:68)
	at com.winterbe.expekt.ExpectDouble.closeTo(ExpectDouble.kt:12)
	at com.example.ExampleTest.example1(ExampleTest.kt:10)

Examples

Example assertions using the should property:

23.should.equal(23)
null.should.be.`null`
"foo".should.not.equal("bar")
3.should.satisfy { it % 2 == 1 }
3.should.be.above(2).and.below(4)
"abc".should.contain("bc").and.startWith("a")
"abc".should.not.have.length.above(3)
"abc".should.not.match(Regex("[0-9]+"))
listOf(1, 2, 3).should.contain(3).and.have.length.above(2)
listOf(1, 2, 3).should.contain.any.elements(1, 3, 4)
listOf(1, 2, 3).should.have.all.elements(1, 2, 3)
mapOf("foo" to "bar", "bar" to "foo").should.contain("foo" to "bar")

Example assertions using the expect function:

expect(23).to.equal(23)
expect(null).to.be.`null`
expect("foo").not.to.equal("bar")
expect(3).not.to.satisfy { it % 2 == 1 }
expect(3).to.be.above(2).and.to.be.below(4)
expect("abc").to.contain("bc").and.to.startWith("a")
expect("abc").not.to.have.length.above(3)
expect("abc").not.to.match(Regex("[0-9]+"))
expect(listOf(1, 2, 3)).to.contain(3).and.to.have.length.above(2)
expect(listOf(1, 2, 3)).to.contain.any.elements(1, 3, 4)
expect(listOf(1, 2, 3)).to.have.all.elements(1, 2, 3)
expect(mapOf("foo" to "bar", "bar" to "foo")).to.contain("foo" to "bar")

License

MIT

Comments
  • (feat) Add expect() and should for Sequence<T>

    (feat) Add expect() and should for Sequence

    • It simply uses ExpectCollection(sequence.toList()).
    • It can not handle infinite sequences.
    • It needs a list instead of a sequence when using to.equal() or not.to.equal().

    Examples:

    expect(sequenceOf(1, 2, 3)).to.contain.any.elements(1, 2, 3)
    expect(sequenceOf(1, 2, 3)).to.contain.any.elements(1, 4)
    
    opened by hastebrot 2
  • Bump kotlin-stdlib from 1.0.3 to 1.6.0

    Bump kotlin-stdlib from 1.0.3 to 1.6.0

    Bumps kotlin-stdlib from 1.0.3 to 1.6.0.

    Release notes

    Sourced from kotlin-stdlib's releases.

    Kotlin 1.6.0

    Changelog

    Android

    • KT-48019 Bundle Kotlin Tooling Metadata into apk artifacts
    • KT-47733 JVM / IR: Android Synthetic don't generate _findCachedViewById function

    Compiler

    New Features

    • KT-47984 In-place arguments inlining for @​InlineOnly functions
    • KT-12794 Allow runtime retention repeatable annotations when compiling under Java 8
    • KT-43714 Support annotations on class type parameters (AnnotationTarget.TYPE_PARAMETER)
    • KT-45949 Kotlin/Native: Improve bound check elimination
    • KT-43919 Support loading Java annotations on base classes and implementing interfaces' type arguments
    • KT-48194 Try to resolve calls where we don't have enough type information, using the builder inference despite the presence of the annotation
    • KT-47736 Support conversion from regular functional types to suspending ones in JVM IR
    • KT-39055 Support property delegate created via synthetic method instead of field

    Performance Improvements

    • KT-45185 FIR2IR: get rid of IrBuiltIns usages
    • KT-47918 JVM / IR: Performance degradation with const-bound for-cycles
    • KT-33835 Bytecode including unnecessary null checks for safe calls where left-hand side is non-nullable
    • KT-41510 Compilation of kotlin html DSL is still too slow
    • KT-48211 We spend a lot of time in ExpectActual declaration checker when there is very small amount of actual/expect declaration
    • KT-39054 Optimize delegated properties which call get/set on the given KProperty instance on JVM
    • KT-46615 Don't generate nullability assertions in methods for directly invoked lambdas

    Fixes

    • KT-49613 JVM / IR: "Exception during IR lowering" with java fun interface and it's non-trivial usage
    • KT-49548 "ClassCastException: java.util.ArrayList$Itr cannot be cast to kotlin.collections.IntIterator" with Iterable inside let
    • KT-22562 Deprecate calls to "suspend" named functions with single dangling lambda argument
    • KT-47120 JVM IR: NoClassDefFoundError when there are an extension and a regular function with the same name
    • KT-49477 Has ran into recursion problem with two interdependant delegates
    • KT-49442 ClassCastException on reporting [EXPOSED_FROM_PRIVATE_IN_FILE] Deprecation: private-in-file class should not expose 'private-in-class'
    • KT-49371 JVM / IR: "NoSuchMethodError" with multiple inheritance
    • KT-44843 PSI2IR: "org.jetbrains.kotlin.psi2ir.generators.ErrorExpressionException: null: KtCallExpression" with delegate who has name or parameter with the same name as a property
    • KT-49294 Turning FlowCollector into 'fun interface' leads to AbstractMethodError
    • KT-18282 Companion object referencing it's own method during construction compiles successfully but fails at runtime with VerifyError
    • KT-25289 Prohibit access to class members in the super constructor call of its companion and nested object
    • KT-32753 Prohibit @​JvmField on property in primary constructor that overrides interface property
    • KT-43433 Suspend conversion is disabled message in cases where it is not supported and quickfix to update language version is suggested
    • KT-49399 Building repeatable annotation with Container nested class fails with ISE: "Repeatable annotation class should have a container generated"
    • KT-49209 Default upper bound for type variables should be non-null
    • KT-49335 NPE in RepeatedAnnotationLowering.wrapAnnotationEntriesInContainer when using @Repeatable annotation from different file
    • KT-48876 java.lang.UnsupportedOperationException: org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl@4a729df2

    ... (truncated)

    Changelog

    Sourced from kotlin-stdlib's changelog.

    1.6.0

    Android

    • KT-48019 Bundle Kotlin Tooling Metadata into apk artifacts
    • KT-47733 JVM / IR: Android Synthetic don't generate _findCachedViewById function

    Compiler

    New Features

    • KT-47984 In-place arguments inlining for @​InlineOnly functions
    • KT-12794 Allow runtime retention repeatable annotations when compiling under Java 8
    • KT-43714 Support annotations on class type parameters (AnnotationTarget.TYPE_PARAMETER)
    • KT-45949 Kotlin/Native: Improve bound check elimination
    • KT-43919 Support loading Java annotations on base classes and implementing interfaces' type arguments
    • KT-48194 Try to resolve calls where we don't have enough type information, using the builder inference despite the presence of the annotation
    • KT-47736 Support conversion from regular functional types to suspending ones in JVM IR
    • KT-39055 Support property delegate created via synthetic method instead of field

    Performance Improvements

    • KT-45185 FIR2IR: get rid of IrBuiltIns usages
    • KT-47918 JVM / IR: Performance degradation with const-bound for-cycles
    • KT-33835 Bytecode including unnecessary null checks for safe calls where left-hand side is non-nullable
    • KT-41510 Compilation of kotlin html DSL is still too slow
    • KT-48211 We spend a lot of time in ExpectActual declaration checker when there is very small amount of actual/expect declaration
    • KT-39054 Optimize delegated properties which call get/set on the given KProperty instance on JVM
    • KT-46615 Don't generate nullability assertions in methods for directly invoked lambdas

    Fixes

    • KT-49613 JVM / IR: "Exception during IR lowering" with java fun interface and it's non-trivial usage
    • KT-49548 "ClassCastException: java.util.ArrayList$Itr cannot be cast to kotlin.collections.IntIterator" with Iterable inside let
    • KT-22562 Deprecate calls to "suspend" named functions with single dangling lambda argument
    • KT-47120 JVM IR: NoClassDefFoundError when there are an extension and a regular function with the same name
    • KT-49477 Has ran into recursion problem with two interdependant delegates
    • KT-49442 ClassCastException on reporting [EXPOSED_FROM_PRIVATE_IN_FILE] Deprecation: private-in-file class should not expose 'private-in-class'
    • KT-49371 JVM / IR: "NoSuchMethodError" with multiple inheritance
    • KT-44843 PSI2IR: "org.jetbrains.kotlin.psi2ir.generators.ErrorExpressionException: null: KtCallExpression" with delegate who has name or parameter with the same name as a property
    • KT-49294 Turning FlowCollector into 'fun interface' leads to AbstractMethodError
    • KT-18282 Companion object referencing it's own method during construction compiles successfully but fails at runtime with VerifyError
    • KT-25289 Prohibit access to class members in the super constructor call of its companion and nested object
    • KT-32753 Prohibit @​JvmField on property in primary constructor that overrides interface property
    • KT-43433 Suspend conversion is disabled message in cases where it is not supported and quickfix to update language version is suggested
    • KT-49399 Building repeatable annotation with Container nested class fails with ISE: "Repeatable annotation class should have a container generated"
    • KT-49209 Default upper bound for type variables should be non-null
    • KT-49335 NPE in RepeatedAnnotationLowering.wrapAnnotationEntriesInContainer when using @Repeatable annotation from different file
    • KT-48876 java.lang.UnsupportedOperationException: org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl@4a729df2
    • KT-48131 IAE "Repeatable annotation container value must be a class reference" on using Kotlin-repeatable annotation from dependency

    ... (truncated)

    Commits
    • 829d1d8 Add changelog for 1.6.0
    • 99b69ae Merge KT-MR-4942: Mark packages for relocation to fix classpath interferring ...
    • 583488e [scripting] Fix NPE in aether.kt
    • 0d1f362 Fix PureAndroidAndJavaConsumeMppLibIT working with test project
    • 46af453 JVM KT-49613 don't generate indy reference to protected constructor
    • d5275aa Mark packages for relocation to fix classpath interferring in main-kts
    • a3820d4 JVM KT-49548 progression iterators can be tainted
    • 63044b1 Update -Xjvm-default description
    • e8e3c72 Update INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER message
    • ddd02fe JvmDefault. Allow non default inheritance with special flag
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump junit from 4.12 to 4.13.1

    Bump junit from 4.12 to 4.13.1

    Bumps junit from 4.12 to 4.13.1.

    Release notes

    Sourced from junit's releases.

    JUnit 4.13.1

    Please refer to the release notes for details.

    JUnit 4.13

    Please refer to the release notes for details.

    JUnit 4.13 RC 2

    Please refer to the release notes for details.

    JUnit 4.13 RC 1

    Please refer to the release notes for details.

    JUnit 4.13 Beta 3

    Please refer to the release notes for details.

    JUnit 4.13 Beta 2

    Please refer to the release notes for details.

    JUnit 4.13 Beta 1

    Please refer to the release notes for details.

    Commits
    • 1b683f4 [maven-release-plugin] prepare release r4.13.1
    • ce6ce3a Draft 4.13.1 release notes
    • c29dd82 Change version to 4.13.1-SNAPSHOT
    • 1d17486 Add a link to assertThrows in exception testing
    • 543905d Use separate line for annotation in Javadoc
    • 510e906 Add sub headlines to class Javadoc
    • 610155b Merge pull request from GHSA-269g-pwp5-87pp
    • b6cfd1e Explicitly wrap float parameter for consistency (#1671)
    • a5d205c Fix GitHub link in FAQ (#1672)
    • 3a5c6b4 Deprecated since jdk9 replacing constructor instance of Double and Float (#1660)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • .should.match not working with multiple line

    .should.match not working with multiple line

    Is there anyway you can support multi-line matching? :smile:

    """
        This is
        some multiline 123
        text
    """.trimIndent().should.match("some multiline \\d+".toRegex(RegexOption.MULTILINE))
    
    opened by theapache64 0
  • Not an issue, just a fan

    Not an issue, just a fan

    Apologies for the noise, but just wanted to voice my appreciation for this project.

    I've been using it for a long time (1.5 years?), and it's become central to all my tests. Thanks so much for your work.

    opened by martypitt 2
  • No way to validate thrown exceptions

    No way to validate thrown exceptions

    It seams that framwork doesn't provide any way to check that tested code throws exception of specific kind. I guess test code can use try/catch, do fail if rich the end of try and do assertions in the catch clause. However this seams clunky and won't give correct nice message in case of failure.

    I think the syntax for exceptions could be: expect(MyException::class).thrownBy {...} If thrownBy returns the exception following code can validate details about it (message, cause, etc.).

    Alternative syntax may be expect {...}.throws(MyException::class).

    opened by C06A 3
Releases(0.4.0)
Owner
Benjamin Winterberg
Software Engineer. Human Interface Designer. Kotlin, TypeScript, React, Postgres.
Benjamin Winterberg
Strikt is an assertion library for Kotlin intended for use with a test runner such as JUnit, Minutest, Spek, or KotlinTest.

Strikt is an assertion library for Kotlin intended for use with a test runner such as JUnit, Minutest, Spek, or KotlinTest.

Rob Fletcher 447 Dec 26, 2022
Selenium locators for Java/Kotlin that resemble the Testing Library (testing-library.com).

Selenium Testing Library Testing Library selectors available as Selenium locators for Kotlin/Java. Why? When I use Selenium, I don't want to depend on

Luís Soares 5 Dec 15, 2022
mocking library for Kotlin

Kotlin Academy articles Check the series of articles "Mocking is not rocket science" at Kt. Academy describing MockK from the very basics of mocking u

MockK 4.8k Jan 3, 2023
A Kotlin Android library for heuristics evasion that prevents your code from being tested.

EvadeMe An Android library for heuristics evasion that prevents your code from being tested. User Instructions Add the maven repository to your projec

Chris Basinger 29 Dec 26, 2022
Kotlin wrapper for React Test Renderer, which can be used to unit test React components in a Kotlin/JS project.

Kotlin API for React Test Renderer Kotlin wrapper for React Test Renderer, which can be used to unit test React components in a Kotlin/JS project. How

Xavier Cho 7 Jun 8, 2022
Android library that allows you to run your acceptance tests written in Gherkin in your Android instrumentation tests.

Green Coffee Green Coffee is a library that allows you to run your acceptance tests written in Gherkin in your Android instrumentation tests using the

Mauricio Togneri 227 Nov 21, 2022
Linkester is an Android library that aims to help Android developers test their deep links implementation.

Linkester Linkester is an Android library that aims to help Android developers test their deep links implementation. The idea is to have a new launche

Ahmad Melegy 79 Dec 9, 2022
Jitpack Library Tester

jitpack-library-test Repository for testing build from jitpack.io Red : Failed Green : Success / Pass Colaborator Very open to anyone, I'll write your

Faisal Amir 7 Dec 10, 2022
Turbine is a small testing library for kotlinx.coroutines Flow.

A small testing library for kotlinx.coroutines Flow

Cash App 1.8k Jan 5, 2023
A library that makes it easier to write high quality automated acceptance tests

Getting started with Serenity and Cucumber Serenity BDD is a library that makes it easier to write high quality automated acceptance tests, with power

ricardo larrahondo 1 Oct 20, 2021
An experimental library for dealing with legacy code

All Super experimental! no guarantees to the public API surface. At the moment, this project is the outcome of the limitations of my search skills. Bu

Ragunath Jawahar 5 Jan 18, 2022
Library to simplify and speed up the creation and work with adapters with payload.

Novalles Library to simplify and speed up the creation and work with adapters with payload. How to use Annotate your UI model with UIModel Annotation.

Бырна Алексей 3 Oct 11, 2022
Portable validations for Kotlin

Portable validations for Kotlin ✅ Type-safe DSL ?? Multi-platform support (JVM, JS) ?? Zero dependencies Installation For multiplatform projects: kotl

null 509 Dec 18, 2022
Powerful, elegant and flexible test framework for Kotlin with additional assertions, property testing and data driven testing

Kotest is a flexible and comprehensive testing tool for Kotlin with multiplatform support. To learn more about Kotest, visit kotest.io or see our quic

Kotest 3.8k Jan 3, 2023
Fixtures for Kotlin providing generated values for unit testing

A tool to generate well-defined, but essentially random, input following the idea of constrained non-determinism.

Appmattus Limited 191 Dec 21, 2022
Lightweight service for creating standalone mock, written in pure Kotlin with Netty container.

MockService The lightweight service for creating a standalone mock, written in pure Kotlin with Netty container. The service allows getting config fil

null 2 Oct 28, 2021
Proyecto de Kotlin y JPA sobre Hibernate, con algunos test usando JUnit 5 y Mockito.

Contactos Kotlin JPA Ejemplos de una aplicación de manejo de contactos con Kotlin y JPA. Usando para testear la aplicación JUnit 5 y Mockito. Almacena

José Luis González Sánchez 3 Sep 13, 2022
This is a sample API project for Rest Assured with Maven Kotlin DSL & JUnit 5

Kotlin-RestAssured Test Automation This is a sample API project for Rest Assured with Maven Kotlin DSL & JUnit 5 Introduction All the Test Cases kept

Dilshan Fernando 0 Dec 9, 2021
Android Sample Kotlin+ MVVM + Coroutines + Retrofit +Hilt+ Junit + Mockito

NTimes AppSample NY Times Most Popular Articles simple app to hit the NY Times Most Popular Articles API and show a list of articles, that shows detai

Amer Elsayed 0 Dec 27, 2021