diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index b36bac6358..b8d2b934a4 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -31,14 +31,14 @@ By participating, you are expected to uphold this code. Please report unacceptab
- Missing a feature?
[Create a feature request](https://github.com/robstoll/atrium/issues/new?template=feature_request.md&title=[Feature]).
-- You would like to write an assertion function but you're having trouble starting?
+- You would like to write an expectation function but you are having trouble starting?
Please read the section [Your First Code Contribution](#your-first-code-contribution).
If you still have trouble starting, then contact us on
[slack](https://kotlinlang.slack.com/messages/D3CL4DDLG/)
([Invite yourself](https://slack.kotlinlang.org/) in case you do not have an account yet)
and we will try to give you some additional hints.
-- You do not have a particular assertion function in mind but would like to contribute with code?
+- You do not have a particular expectation function in mind but would like to contribute with code?
Please have a look at the [help wanted issues](https://github.com/robstoll/atrium/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22)
-- ping us on
[Slack](https://kotlinlang.slack.com/messages/C887ZKGCQ)
@@ -54,7 +54,7 @@ By participating, you are expected to uphold this code. Please report unacceptab
- Found spelling mistakes?
Nice catch :mag: Please fix it and create a pull request.
-- You wrote an assertion function and would like to contribute it to Atrium?
+- You wrote an expectation function and would like to contribute it to Atrium?
Awesome :+1: please review the [pull request checklist](#pull-request-checklist) and create a pull request
- You would like to support the project financially?
diff --git a/README.md b/README.md
index 4b1675ef11..09fff900af 100644
--- a/README.md
+++ b/README.md
@@ -17,14 +17,14 @@
-->
#
-Atrium is an open-source multiplatform assertion library for Kotlin with support for JVM, JS and Android.
+Atrium is an open-source multiplatform expectation/assertion library for Kotlin with support for JVM, JS and Android.
It is designed to support multiple [APIs](#api-styles), different error reporting styles and [Internationalization](#internationalization-1) (i18n).
The project was inspired by AssertJ at first but moved on and provides now more
flexibility, features and hints to its users (so to you 😉).
Atrium is designed to be extensible as well as configurable
-and allows you to extend it with your own assertion functions, customise reporting
-or even replace core components with your own implementation in an easy way.
+and allows you to extend it with your own expectation functions, customise reporting
+or even replace core components with your own implementation easily.
Atrium currently provides two [API Styles](#api-styles):
pure fluent and infix where both of them have their design focus on usability in conjunction with code completion functionality provided by your IDE.
@@ -44,33 +44,33 @@ For instance, the [README of v0.18.0](https://github.com/robstoll/atrium/tree/v0
- [Android](#android)
- [Common](#common)
- [Examples](#examples)
- - [Your First Assertion](#your-first-assertion)
- - [Define Single Assertions or Assertion Groups](#define-single-assertions-or-assertion-groups)
+ - [Your First Expectation](#your-first-expectation)
+ - [Define Single Expectations or an Expectation-Group](#define-single-expectations-or-an-expectation-group)
- [Expect an Exception](#expect-an-exception)
- - [Feature Assertions](#feature-assertions)
+ - [Feature Extractors](#feature-extractors)
- [Property and Method](#property-and-methods)
- [Arbitrary Features](#arbitrary-features)
- - [Type Assertions](#type-assertions)
+ - [Type Expectations](#type-expectations)
- [Nullable Types](#nullable-types)
- - [Collection Assertions](#collection-assertions)
+ - [Collection Expectations](#collection-expectations)
- [Shortcut Functions](#shortcut-functions)
- - [Sophisticated Assertion Builders](#sophisticated-assertion-builders)
- - [Map Assertions](#map-assertions)
+ - [Sophisticated Expectation Builders](#sophisticated-expectation-builders)
+ - [Map Expectations](#map-expectations)
- [Shortcut Functions](#shortcut-functions-1)
- - [Sophisticated Assertion Builders](#sophisticated-assertion-builders-1)
+ - [Sophisticated Expectation Builders](#sophisticated-expectation-builders-1)
- [Others](#others)
- - [Path Assertions](#path-assertions)
+ - [Path Expectations](#path-expectations)
- [Attaching a Reason](#attaching-a-reason)
- [Data Driven Testing](#data-driven-testing)
- [Further Examples](#further-examples)
- [Sample Projects](#sample-projects)
- [Third-party Extensions](#third-party-extensions)
-- [How is Atrium different from other Assertion Libraries](#how-is-atrium-different-from-other-assertion-libraries)
-- [Write own Assertion Functions](#write-own-assertion-functions)
- - [Boolean based Assertions](#boolean-based-assertions)
- - [Compose Functions](#compose-assertion-functions)
+- [How is Atrium different from other Expectation/Assertion Libraries](#how-is-atrium-different-from-other-expectationassertion-libraries)
+- [Write own Expectation Functions](#write-own-expectation-functions)
+ - [Boolean based Expectation Functions](#boolean-based-expectation-functions)
+ - [Compose Functions](#compose-expectation-functions)
- [Enhanced Reporting](#enhanced-reporting)
- - [Own Sophisticated Assertion Builders](#own-sophisticated-assertion-builders)
+ - [Own Sophisticated Expectation Builders](#own-sophisticated-expectation-builders)
- [Use own Expectation Verb](#use-own-expectation-verb)
- [Use own Components](#use-own-components)
- [Internationalization](#internationalization-1)
@@ -106,7 +106,7 @@ Have a look at the [JVM sample projects](https://github.com/robstoll/atrium/tree
[Maven sample project](https://github.com/robstoll/atrium/tree/main/samples/maven) if you prefer Maven to Gradle.
We currently provide the following extensions for the JVM platform:
-- kotlin_1_3: assertion functions for Kotlin 1.3 specific types (e.g. for [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)).
+- kotlin_1_3: expectation functions for Kotlin 1.3 specific types (e.g. for [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)).
You can enable them as follows:
```
@@ -179,7 +179,7 @@ which are executed on the JS platform as well
[build.gradle -> useJupiter](https://github.com/robstoll/atrium/tree/main/build.gradle#L342)).
We currently provide the following extensions for the JS platform:
- - kotlin_1_3: assertion functions for Kotlin 1.3 specific types (e.g. for [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)).
+ - kotlin_1_3: expectation functions for Kotlin 1.3 specific types (e.g. for [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)).
You can enable them as follows:
```
@@ -214,8 +214,8 @@ That is all, you are all set. Jump to [Examples](#examples) which shows how to u
## Android
-Starting with 0.12.0 we no longer deliver a dedicated `-android` jar. Instead you can use the same setup as shown in [JVM setup](#jvm).
-We start adding one again in case we have Android specific assertion functions.
+Starting with 0.12.0 we no longer deliver a dedicated `-android` jar. Instead, you can use the same setup as shown in [JVM setup](#jvm).
+We start adding one again in case we have Android specific expectation functions.
Also take a look at [Third-party Extensions](#third-party-extensions) which might come in handy as well.
@@ -238,7 +238,7 @@ Have a look at
[apis/differences.md](https://github.com/robstoll/atrium/tree/main/apis/differences.md)
to see how the infix API looks like, how they differ respectively.
-## Your First Assertion
+## Your First Expectation
We start off with a simple example:
@@ -258,11 +258,12 @@ I expected subject: 10 (kotlin.Int <1234789>)
```
-The statement can be read as "I expect x to equal nine" where an equality check is used (for an identity check, you have to use `toBeTheSameInstace`).
+The statement can be read as "I expect x to equal nine" where an equality check is used (for an identity check, you would have to use `toBeTheSameInstace`).
Since this is false, an `AssertionError` is thrown with a corresponding message as shown in the [Output](#ex-first)
-where `◆ ...` represents a single assertion for the subject (`10` in the above example) of the assertion.
-In this sense the report can be read as `I expected the subject of the assertion, which was 10, to equal 9`
--- and needless to say, this assertion is wrong and thus the thrown error.
+where on the first line the actual subject (`10` in the above example) is shown and on following lines which start with,
+`◆ ...` (here only one) we see the expectations we had about the subject
+In this sense the report can be read as `I expected the subject of the expectation, which was 10, to equal 9`
+-- and needlessly to say, this expectation was not met and thus the thrown error.
We are using the bundle [atrium-fluent-en_GB](https://github.com/robstoll/atrium/tree/main/bundles/fluent-en_GB/atrium-fluent-en_GB/build.gradle)
and the predefined expectation verb `expect` in the examples.
@@ -272,13 +273,13 @@ We will omit the `import` statements in the remaining examples for brevity.
**You want to run the examples yourself?**
Have a look at the [Installation](#installation) section which explains how to set up a dependency to Atrium.
-The next section shows how you can define multiple assertions for the same subject.
+The next section shows how you can define multiple expectations for the same subject.
-## Define Single Assertions or Assertion Groups
+## Define Single Expectations or an Expectation-Group
```kotlin
-// two single assertions, only first evaluated
+// two single expectations, only first evaluated
expect(4 + 6).toBeLessThan(5).toBeGreaterThan(10)
```
↑ [Example](https://github.com/robstoll/atrium/tree/main/misc/tools/readme-examples/src/main/kotlin/readme/examples/MostExamplesSpec.kt#L24) ↓ [Output](#ex-single)
@@ -289,9 +290,9 @@ I expected subject: 10 (kotlin.Int <1234789>)
```
-Atrium allows you to chain assertions or in other words
-you only need to write the `expect(...)` part once and can make several single assertions for the same subject.
-The expression which determines the subject of the assertion (`4 + 6` in the above example) is evaluated only once.
+Atrium allows you to chain expectations or in other words
+you only need to write the `expect(...)` part once and can state several single expectations for the same subject.
+The expression which determines the subject of the expectations (`4 + 6` in the above example) is evaluated only once.
In this sense we could have written it also as follows (which is only the same because `4 + 6` does not have side effects).
@@ -303,16 +304,16 @@ expect(4 + 6).toBeGreaterThan(10)
```
-Correspondingly, the first `expect` statement (which does not hold) throws an `AssertionError`.
+The first `expect` statement throws an `AssertionError` as it does not hold.
In the above example, `toBeLessThan(5)` is already wrong and thus `toBeGreaterThan(10)` was not evaluated at all
and correspondingly not reported.
-If you want that both assertions are evaluated together, then use the assertion group syntax as follows:
+If you want that both expectations are evaluated together, then use the expectation-group syntax as follows:
```kotlin
-// assertion group with two assertions, both evaluated
+// expectation-group with two expectations, both evaluated
expect(4 + 6) {
toBeLessThan(5)
toBeGreaterThan(10)
@@ -327,10 +328,11 @@ I expected subject: 10 (kotlin.Int <1234789>)
```
-An assertion group throws an `AssertionError` at the end of its block; hence reports that both assertions do not hold.
-The reporting can be read as `I expected the subject of the assertion, which was 10, to be less than 5 and to be greater than 10`
+An expectation-group throws an `AssertionError` at the end of its block (i.e. at the closing `}`);
+hence reports that both expectations do not hold.
+The reporting can be read as `I expected the subject of the expectation, which was 10, to be less than 5 and to be greater than 10`
-You can use `and` as filling element between single assertions and assertion group blocks:
+You can use `and` as filling element between single expectations and expectation-groups:
@@ -350,7 +352,7 @@ expect(5) {
```kotlin
expect {
- // this block does something but eventually...
+ // this lambda does something but eventually...
throw IllegalArgumentException("name is empty")
}.toThrow()
```
@@ -370,16 +372,17 @@ I expected subject: () -> kotlin.Nothing (readme.examples.MostExamplesSpe
```
-You can also pass a lambda to `expect` and then use `toThrow` to make the assertion that
+You can also pass a lambda to `expect` and then use `toThrow` to state the expectation that
invoking the lambda throws a certain exception (`IllegalStateException` in the example above).
As with all narrowing functions, there are two overloads:
-- the first is parameterless and turns only the subject into the expected type;
+- the first expects an `assertionCreator`-lambda in which you can define sub-expectations.
+ An `assertionCreator`-lambda has always the semantic of an [expectation-group](#define-single-expectations-or-an-expectation-group).
+ It has also the benefit, that Atrium can show those sub-expectations in error reporting,
+ even if a failure happens before, giving some additional context to a failure.
+- the second overload expects all the parameters except the `assertionCreator`-lambda and turns the subject into the expected type;
failing to do so cannot include additional information in error reporting though.
-- the second expects an `assertionCreator`-lambda in which you can define sub-assertions.
- An `assertionCreator`-lambda has always the semantic of an [assertion group block](#define-single-assertions-or-assertion-groups).
- It has also the benefit, that Atrium can provide those sub-assertions in error reporting,
- showing some additional context in case of a failure.
+
The following example uses the first overload
@@ -388,7 +391,9 @@ The following example uses the first overload
```kotlin
expect {
throw IllegalArgumentException()
-}.toThrow().message.toStartWith("firstName")
+}.toThrow {
+ message { toStartWith("firstName") }
+}
```
↑ [Example](https://github.com/robstoll/atrium/tree/main/misc/tools/readme-examples/src/main/kotlin/readme/examples/MostExamplesSpec.kt#L71) ↓ [Output](#ex-toThrow2)
@@ -397,33 +402,32 @@ I expected subject: () -> kotlin.Nothing (readme.examples.MostExamplesSpe
◆ ▶ thrown exception when called: java.lang.IllegalArgumentException
◾ ▶ message: null
◾ to be an instance of type: String (kotlin.String) -- Class: java.lang.String
+ » to start with: "firstName" <1234789>
```
-And this one uses the second overload; notice the difference in reporting.
+And this one uses the second overload; notice the difference in reporting,
+this one does not include what sub-expectations would have been made if the narrowing succeeded
```kotlin
expect {
throw IllegalArgumentException()
-}.toThrow {
- message { toStartWith("firstName") }
-}
+}.toThrow().message.toStartWith("firstName")
```
-↑ [Example](https://github.com/robstoll/atrium/tree/main/misc/tools/readme-examples/src/main/kotlin/readme/examples/MostExamplesSpec.kt#L77) ↓ [Output](#ex-toThrow3)
+↑ [Example](https://github.com/robstoll/atrium/tree/main/misc/tools/readme-examples/src/main/kotlin/readme/examples/MostExamplesSpec.kt#L79) ↓ [Output](#ex-toThrow3)
```text
I expected subject: () -> kotlin.Nothing (readme.examples.MostExamplesSpec$1$9$1 <1234789>)
◆ ▶ thrown exception when called: java.lang.IllegalArgumentException
◾ ▶ message: null
◾ to be an instance of type: String (kotlin.String) -- Class: java.lang.String
- » to start with: "firstName" <1234789>
```
As side notice, `message` is a shortcut for `feature(Throwable::message).notToEqualNull`,
-which creates a feature assertion (see next section) about `Throwable::message`.
+which creates a feature extractor (see next section) about `Throwable::message`.
There is also the counterpart of `toThrow` named `notToThrow`:
@@ -458,16 +462,17 @@ Notice that stacks are filtered so that you only see what is of interest.
You can [use your own](#use-own-components)
[AtriumErrorAdjuster](https://docs.atriumlib.org/latest#/doc/ch.tutteli.atrium.reporting/-atrium-error-adjuster/index.html)
to adjust the filtering.
-Stack frames of Atrium and of test runners (Spek, Kotlintest and JUnit for JVM, mocha and jasmine for JS) are excluded per default.
+Stack frames of Atrium and of test runners (Spek, Kotest, and JUnit for JVM, mocha and jasmine for JS) are excluded per default.
[Create a Feature Request](https://github.com/robstoll/atrium/issues/new?template=feature_request.md&title=[Feature])
in case you use a different runner, we can add yours to the list as well.
-## Feature Assertions
-Many times you are only interested in certain features of the subject and want to make assertions about them.
+
+## Feature Extractors
+Many times you are only interested in certain features of the subject and want to state expectations about them.
-There are different use cases for feature assertions.
+There are different use cases for feature extractors.
We will start of with properties and method calls and go on with more complicated scenarios.
### Property and Methods
@@ -488,7 +493,7 @@ val myPerson = Person("Robert", "Stoll", false)
```
-The simplest way of defining assertions for a property of an instance or for the return value of a method call is by
+The simplest way of defining expectations for a property of an instance or for the return value of a method call is by
using the extension method `its`.
@@ -508,40 +513,39 @@ I expected subject: Person(firstName=Robert, lastName=Stoll, isStudent=false)
```
-In the above example we created two assertions, one for the property `isStudent` of `myPerson`
+In the above example we created two expectations, one for the property `isStudent` of `myPerson`
and a second one for the return value of calling `fullName()` on `myPerson`.
-A feature assertion is indicated as follows in reporting:
+A feature extractor is indicated as follows in reporting:
It starts with a `▶` followed by the feature's description and its actual value.
So the above output can be read as
-> I expected the subject of the assertion, which was actually the Person(...),
+> I expected the subject of the expectation, which was actually Person(...),
> respectively its property which was defined in FeatureExtractorSpec.kt on line 43,
> which was actually `false`, to equal `true`.
-The second feature is not shown in reporting as the first already failed, and we have chosen to use [single assertions](#define-single-assertions-or-assertion-groups)
+The second feature is not shown in reporting as the first expectation about the property `isStudent` already failed,
+and we have chosen to use [single expectations](#define-single-expectations-or-an-expectation-group)
which have fail-fast semantic.
-Feature assertions follow the common pattern of having two overloads:
-- the first expects only the extractor-lambda.
- This overload narrows the subject to the feature,
+Feature extractors follow the common pattern of having two overloads:
+- the first expects an `assertionCreator`-lambda, in which you can define sub-expectations for the feature.
+ An `assertionCreator`-lambda has always the semantic of an [expectation-group](#define-single-expectations-or-an-expectation-group)
+ or in other words, not-fail fast. It has also the benefit, that Atrium can provide those sub-expectations in error reporting.
+ Moreover, the subject stays the same so that subsequent calls are still about the same subject
+- the second overload expects all the parameters except the `assertionCreator`-lambda and changes the subject to the feature,
meaning a subsequent call in the fluent chain is about the feature and not the previous subject.
-- the second expects an `assertionCreator`-lambda in addition, in which you can define sub-assertions for the feature.
- An `assertionCreator`-lambda has always the semantic of an [assertion group block](#define-single-assertions-or-assertion-groups) or in other words, not-fail fast.
- It has also the benefit, that Atrium can provide those sub-assertions in error reporting,
- Moreover, the subject stays the same so that subsequent calls are still about the same subject.
-
```kotlin
- expect(myPerson) { // forms an assertion group block
+ expect(myPerson) { // forms an expectation-group
- its({ firstName }) { // forms an assertion group block
+ its({ firstName }) { // forms an expectation-group
toStartWith("Pe") // fails
toEndWith("er") // is evaluated nonetheless
} // fails as a whole
- // still evaluated, as it is in outer assertion group block
+ // still evaluated, as it is in outer expectation-group
its { lastName }.toEqual("Dummy")
}
```
@@ -584,8 +588,8 @@ I expected subject: Person(firstName=Robert, lastName=Stoll, isStudent=false)
The report reads much nicer now:
-> I expected the subject of the assertion,
-> which was actually the Person(...), respectively its property `isStudent`,
+> I expected the subject of the expectation,
+> which was actually Person(...), respectively its property `isStudent`,
> which was actually `false`, to equal `true`
The drawback of `feature` compared to `its` is its syntax. Certainly, one has to get used to it first. Another is that
@@ -595,22 +599,24 @@ you might run into [Ambiguity Problems](#ambiguity-problems) due to Kotlin bugs.
Creating a `MetaFeature` is done via the function `f` by passing in a
[bounded reference](https://kotlinlang.org/docs/reference/reflection.html#bound-function-and-property-references-since-11)
of the corresponding property or method (including arguments if required).
-`it` within the `MetaFeature`-provider-lambda refers to the subject of the assertion (`myPerson` in the above example).
+`it` within the `MetaFeature`-provider-lambda refers to the subject of the expectation (`myPerson` in the above example).
-Also `feature` follows the common pattern of having two overloads where the second expects an `assertionCreator`-lambda.
+Also `feature` follows the common pattern of having two overloads where the first expects an `assertionCreator`-lambda and
+the second has the same parameters except the `assertionCreator`-lambda and changes the subject to the feature,
+meaning a subsequent call in the fluent chain is about the feature and not the previous subject.
Following the second example rewritten from `its` to `feature`:
```kotlin
-expect(myPerson) { // forms an assertion group block
+expect(myPerson) { // forms an expectation-group
- feature({ f(it::firstName) }) { // forms an assertion group block
+ feature({ f(it::firstName) }) { // forms an expectation-group
toStartWith("Pe") // fails
toEndWith("er") // is evaluated nonetheless
} // fails as a whole
- // still evaluated, as it is in outer assertion group block
+ // still evaluated, as it is in outer expectation-group
feature { f(it::lastName) }.toEqual("Dummy")
}
```
@@ -633,23 +639,23 @@ Please [open a feature request](https://github.com/robstoll/atrium/issues/new?te
💬 <- _this icon signifies answers/input for advanced users, you might want to skip them if you are new to Atrium._
-💬 Wrap each property into an assertion function?
+💬 Provide a feature extractor for each property?
-You might be asking yourself whether it is better to [write an own assertion function](#write-own-assertion-functions) or use `feature`.
+You might be asking yourself whether it is better to [write an own feature extractor](#write-own-expectation-functions) or use `feature`.
The only drawback of using an existing property is that a few more keystrokes are required compared to
-[writing an own assertion function](#write-own-assertion-functions) once and then reuse it (as we did with `message`).
-Yet, we do not recommend writing an own assertion function for every single property.
+[writing an own feature extractor](#write-own-expectation-functions) once and then reuse it (as we did with `message`).
+Yet, we do not recommend writing an own feature extractor for every single property.
We think it makes sense to add one if you use it a lot and (preferably) it is a stable API.
-Why not always? Because one quickly forgets to rename the assertion function
+Why not always? Because one quickly forgets to rename the feature extractor
if the property as such is renamed (e.g., as part of an IDE refactoring).
-As you can see, you would need to keep the property name and the name of the assertion function in sync to be meaningful
+As you can see, you would need to keep the property name and the name of the feature extractor in sync to be meaningful
(otherwise one gets quickly confused or has to remember two names for the same thing).
-Writing assertion functions for methods is a different story though, especially due to [overload bugs in Kotlin](https://github.com/robstoll/atrium/wiki/Kotlin-Bugs-and-missing-features).
+Writing feature extractors for method calls is a different story though, especially due to [overload bugs in Kotlin](https://github.com/robstoll/atrium/wiki/Kotlin-Bugs-and-missing-features).
Also, code completion is not yet as good as it should be when it comes to methods.
Last but not least, in case it is not always safe to call a method (e.g. `List.get` => IndexOutOfBound) then it makes
-sense to wrap it into an assertion function and use `_logic.extractFeature` instead.
+sense to wrap it into an own feature extractor and use `_logic.extractFeature`.
@@ -680,16 +686,16 @@ Please [open a feature request](https://github.com/robstoll/atrium/issues/new?te
in case you miss a shortcut.
-💬 Write own feature assertion functions with additional checks.
+💬 Write own feature extractors with additional checks.
-Atrium provides a feature extractor which allows making feature assertions in a safe way in case the extraction is only valid for certain subjects.
+Atrium provides a feature extractor which allows to extract in a safe way in case the extraction is only valid for certain subjects.
It is inter alia used for [`List.get`](https://github.com/robstoll/atrium/tree/main/logic/atrium-logic-common/src/main/kotlin/ch/tutteli/atrium/logic/impl/DefaultListAssertions.kt#L13)
### Arbitrary Features
A feature does not necessarily have to be directly related to the subject as properties or method calls do.
-Either use `its` the overload of `feature` which expects a feature description in form of a `String` as first argument.
+Either use `its` or the overload of `feature` which expects a feature description in form of a `String` as first argument.
Following an example using `feature`.
@@ -715,23 +721,21 @@ I expected subject: Family(members=[FamilyMember(name=Robert)]) (readme.e
Also, this version of `feature` provides two different kind of overloads:
-- the first expects a feature description and a feature-provider-lambda
- This overload narrows the subject to the feature,
+- the first expects a feature description, a feature-provider-lambda and an `assertionCreator`-lambda, in which you can define sub-expectations for the feature.
+ An `assertionCreator`-lambda has always the semantic of an [expectation-group](#define-single-expectations-or-an-expectation-group) or in other words, not-fail fast.
+ It has also the benefit, that Atrium can provide those sub-expectations in error reporting,
+ Moreover, the subject stays the same so that subsequent calls are still about the same subject.
+- the second overload expects all the parameters except the `assertionCreator`-lambda and changes the subject to the feature,
meaning a subsequent call in the fluent chain is about the feature and not the previous subject.
-- the second expects an `assertionCreator`-lambda in addition, in which you can define sub-assertions for the feature.
- An `assertionCreator`-lambda has always the semantic of an [assertion group block](#define-single-assertions-or-assertion-groups) or in other words, not-fail fast.
- It has also the benefit, that Atrium can provide those sub-assertions in error reporting,
- Moreover, the subject stays the same so that subsequent calls are still about the same subject.
-
-As you can see, Atrium provides a generic way to postulate assertions about features.
-Yet, if you use such feature assertion often or it gets more complicated,
-then it might be worth to [write an own assertion function](#write-own-assertion-functions) where we recommend to
+As you can see, Atrium provides a generic way to postulate expectations about features.
+Yet, if you extract the same feature over and over again or it gets more complicated,
+then it might be worth to [write an own expectation function](#write-own-expectation-functions) where we recommend to
use `feature` over `its`.
-### Within Assertion Functions
+### Within Expectation Functions / Feature Extractors
-In case you write an own assertion function, then we discourage two things:
+In case you write an own expectation function, then we discourage two things:
- using `its` because the reporting reads less nice and it is also less efficient than `feature`
- using `feature` with a `MetaFeature`-provider-lambda (as shown in [Property and Methods](#property-and-methods))
@@ -741,7 +745,7 @@ This has the benefit, that we can always show the feature name, also in case a p
transformation failed.
Following an example:
-
+
```kotlin
fun > Expect.firstToBeDoneWrong(expected: F) =
@@ -755,8 +759,8 @@ expect(listOf(1 to "a", 2 to "b")).get(10) {
firstToBe(1)
}
```
-↑ [Example](https://github.com/robstoll/atrium/tree/main/misc/tools/readme-examples/src/main/kotlin/readme/examples/FeatureExtractorSpec.kt#L118) ↓ [Output](#ex-within-assertion-functions)
-
+↑ [Example](https://github.com/robstoll/atrium/tree/main/misc/tools/readme-examples/src/main/kotlin/readme/examples/FeatureExtractorSpec.kt#L118) ↓ [Output](#ex-within-expectation-functions)
+
```text
I expected subject: [(1, a), (2, b)] (java.util.Arrays.ArrayList <1234789>)
◆ ▶ get(10): ❗❗ index out of bounds
@@ -765,7 +769,7 @@ I expected subject: [(1, a), (2, b)] (java.util.Arrays.ArrayList <1234789
» ▶ first:
◾ to equal: 1 (kotlin.Int <1234789>)
```
-
+
Also, this version of `feature` provides two kind of overloads, one without and one with `assertionCreator`-lambda.
(see for instance [Arbitrary Features](#arbitrary-features) for more information).
@@ -828,9 +832,9 @@ expect(a)
.startsWith(...)
```
-## Type Assertions
+## Type Expectations
-
+
```kotlin
interface SuperType
@@ -839,65 +843,65 @@ data class SubType1(val number: Int) : SuperType
data class SubType2(val word: String, val flag: Boolean) : SuperType
val x: SuperType = SubType2("hello", flag = true)
-expect(x).toBeAnInstanceOf()
- .feature { f(it::number) }
- .toEqual(2)
+expect(x).toBeAnInstanceOf {
+ feature { f(it::word) }.toEqual("goodbye")
+ feature { f(it::flag) }.toEqual(false)
+}
```
-↑ [Example](https://github.com/robstoll/atrium/tree/main/misc/tools/readme-examples/src/main/kotlin/readme/examples/MostExamplesSpec.kt#L92) ↓ [Output](#ex-type-assertions-1)
-
+↑ [Example](https://github.com/robstoll/atrium/tree/main/misc/tools/readme-examples/src/main/kotlin/readme/examples/MostExamplesSpec.kt#L92) ↓ [Output](#ex-type-expectations-1)
+
```text
I expected subject: SubType2(word=hello, flag=true) (readme.examples.SubType2 <1234789>)
-◆ to be an instance of type: SubType1 (readme.examples.SubType1)
+◆ ▶ word: "hello" <1234789>
+ ◾ to equal: "goodbye" <1234789>
+◆ ▶ flag: true
+ ◾ to equal: false
```
-
+
-You can narrow a type with the `toBeA` function.
-On one hand it checks that the subject of the current assertion (`x` in the above example) is actually the expected type
+You can narrow the type of the subject with the `toBeAnInstanceOf` function.
+On one hand it checks that the subject of the current expectation (`x` in the above example) is actually the expected type
and on the other hand it turns the subject into this type.
-This way you can make specific assertions which are only possible for the corresponding type
+This way you can make specific expectations which are only possible for the corresponding type
-- for instance, considering the above example, `number` is not available on `SuperType` but only on `SubType1`.
-
+
```kotlin
-expect(x).toBeAnInstanceOf {
- feature { f(it::word) }.toEqual("goodbye")
- feature { f(it::flag) }.toEqual(false)
-}
+expect(x).toBeAnInstanceOf()
+ .feature { f(it::number) }
+ .toEqual(2)
```
-↑ [Example](https://github.com/robstoll/atrium/tree/main/misc/tools/readme-examples/src/main/kotlin/readme/examples/MostExamplesSpec.kt#L98) ↓ [Output](#ex-type-assertions-2)
-
+↑ [Example](https://github.com/robstoll/atrium/tree/main/misc/tools/readme-examples/src/main/kotlin/readme/examples/MostExamplesSpec.kt#L99) ↓ [Output](#ex-type-expectations-2)
+
```text
I expected subject: SubType2(word=hello, flag=true) (readme.examples.SubType2 <1234789>)
-◆ ▶ word: "hello" <1234789>
- ◾ to equal: "goodbye" <1234789>
-◆ ▶ flag: true
- ◾ to equal: false
+◆ to be an instance of type: SubType1 (readme.examples.SubType1)
```
-
+
-There are two `toBeA` overloads:
-- the first (shown in the first example) is parameterless and turns only the subject into the expected type;
+There are two `toBeAnInstanceOf` overloads:
+- the first (shown in the first example) expects an `assertionCreator`-lambda in which you can define sub-expectations.
+ An `assertionCreator`-lambda has always the semantic of an [expectation-group](#define-single-expectations-or-an-expectation-group)
+ -- as a recapitulation, expectations in an expectation-group are all evaluated and failures are reported at the end of the block.
+ It has also the benefit, that Atrium can provide those sub-expectations in error reporting,
+ showing some additional context in case of a failure.
+- the second overload (shown in the second example) is parameterless and turns only the subject into the expected type;
failing to do so cannot include additional information in error reporting though.
-- the second (shown in the second example) expects an `assertionCreator`-lambda in which you can define sub-assertions.
- An `assertionCreator`-lambda has always the semantic of an [assertion group block](#define-single-assertions-or-assertion-groups)
- -- as a recapitulation, assertions in an assertion group block are all evaluated and failures are reported at the end of the block.
- It has also the benefit, that Atrium can provide those sub-assertions in error reporting,
- showing some additional context in case of a failure.
## Nullable Types
-Let us look at the case where the subject of the assertion has a [nullable type](https://kotlinlang.org/docs/reference/null-safety.html).
+Let us look at the case where the subject of the expectation has a [nullable type](https://kotlinlang.org/docs/reference/null-safety.html).
```kotlin
-val slogan1: String? = "postulating assertions made easy"
+val slogan1: String? = "postulating expectations made easy"
expect(slogan1).toEqual(null)
```
↑ [Example](https://github.com/robstoll/atrium/tree/main/misc/tools/readme-examples/src/main/kotlin/readme/examples/MostExamplesSpec.kt#L106) ↓ [Output](#ex-nullable-1)
```text
-I expected subject: "postulating assertions made easy" <1234789>
+I expected subject: "postulating expectations made easy" <1234789>
◆ to equal: null
```
@@ -906,20 +910,20 @@ I expected subject: "postulating assertions made easy" <1234789>
```kotlin
val slogan2: String? = null
-expect(slogan2).toEqual("postulating assertions made easy")
+expect(slogan2).toEqual("postulating expectations made easy")
```
↑ [Example](https://github.com/robstoll/atrium/tree/main/misc/tools/readme-examples/src/main/kotlin/readme/examples/MostExamplesSpec.kt#L110) ↓ [Output](#ex-nullable-2)
```text
I expected subject: null
-◆ to equal: "postulating assertions made easy" <1234789>
+◆ to equal: "postulating expectations made easy" <1234789>
```
On one hand, you can use `toEqual` and pass the same type --
`String?` in the above example, so in other words either `null` as in the first example or a `String` as in the second example.
On the other hand, you can use `notToEqualNull` to turn the subject into its non-null version.
-This is a shortcut for `toBeA` where `Xy` is the non-nullable type (see [Type Assertions](#type-assertions)).
+This is a shortcut for `toBeAnInstanceOf` where `Xy` is the non-nullable type (see [Type Expectations](#type-expectations)).
Following an example:
@@ -939,7 +943,7 @@ I expected subject: null
Since `notToEqualNull` delegates to `toBeAnInstanceOf`, it also provides two overloads:
one without (example above) and one with `assertionCreator`-lambda (example below); see
-[Type Assertions](#type-assertions) for more information on the difference of the overloads.
+[Type Expectations](#type-expectations) for more information on the difference of the overloads.
@@ -968,13 +972,13 @@ then you can skip now to the next section (otherwise click on the arrow to expan
-## Collection Assertions
+## Collection Expectations
-Atrium provides assertion builders which allow to make sophisticated `toContain` assertions for `Iterable`.
-Such a building process allows you to define very specific assertions, where the process is guided by a fluent builder pattern.
+Atrium provides expectation builders which allow to state sophisticated `toContain` expectations about `Iterable`.
+Such a building process allows you to define very specific expectations, where the process is guided by a fluent builder pattern.
You can either use such an
-[Assertion Builder](#sophisticated-assertion-builders)
-to create a specific assertion or use one of the
+[Expectation Builder](#sophisticated-expectation-builders)
+to create a specific expectation or use one of the
[Shortcut Functions](#shortcut-functions) in case you have kind of a common case.
The following sub sections show both use cases by examples.
@@ -995,15 +999,15 @@ I expected subject: [1, 2, 2, 4] (java.util.Arrays.ArrayList <1234789>)
```
-The assertion function `toContain(2, 3)` is a shortcut for using a
-[Sophisticated Assertion Builder](#sophisticated-assertion-builders) -- it actually calls `toContain.inAnyOrder.atLeast(1).values(2, 3)`.
-This is reflected in the output, which tells us that we expected that the `number of such entries`, which is actually `0`, `is at least: 1`.
+The expectation function `toContain(2, 3)` is a shortcut for using a
+[Sophisticated Expectation Builder](#sophisticated-expectation-builders) -- it actually calls `toContain.inAnyOrder.atLeast(1).values(2, 3)`.
+This is reflected in the output.
👓 and what about expected value 2?
Exactly, what about the expected value `2`, why do we not see anything about it in the output?
-The output does not show anything about the expected value `2` because the default reporter reports only failing assertions.
+The output does not show anything about the expected value `2` because the default reporter reports only failing expectations.
Back to the shortcut functions.
@@ -1011,8 +1015,8 @@ Back to the shortcut functions.
Next to expecting that certain values are contained in or rather returned by an `Iterable`,
Atrium allows us to use an `assertionCreator`-lambda to identify an element
-(an `assertionCreator`-lambda can also be thought of as matcher / predicate in this context).
-An element is considered as identified, if it holds all specified assertions.
+(an `assertionCreator`-lambda can also be thought of as a matcher / predicate in this context).
+An element is considered as identified, if it holds all specified expectations the `assertionCreator` creates.
Following an example:
@@ -1038,7 +1042,7 @@ I expected subject: [1, 2, 2, 4] (java.util.Arrays.ArrayList <1234789>)
```
-In the above example, neither of the two lambdas matched any elements and thus both are reported as failing (sub) assertions.
+In the above example, neither of the two lambdas matched any elements and thus both are reported as failing (sub) expectations.
Another `toContain` shortcut function which Atrium provides for `Iterable` is kind of
the opposite of `inAnyOrder.atLeast(1)` and is named `toContainExactly`.
@@ -1054,7 +1058,7 @@ This makes of course only sense if your `Iterable` contains nullable elements.
Atrium provides also a `notToContain` shortcut function.
Furthermore, it provides aliases for `toContain` and `notToContain` named `toHaveNextAndAny` and `toHaveNextAndNone`,
which might be a better choice if you think in terms of: expect a predicate holds.
-These two are completed with an `toHaveNextAndAll` assertion function.
+These two are completed with an `toHaveNextAndAll` expectation function.
Following each in action:
@@ -1116,10 +1120,10 @@ I expected subject: [1, 2, 3, 4] (java.util.Arrays.ArrayList <1234789>)
-### Sophisticated Assertion Builders
+### Sophisticated Expectation Builders
-Sophisticated assertion builders implement a fluent builder pattern.
-To use the assertion builder for sophisticated `Iterable`-toContain-assertions, you can type `toContain`
+Sophisticated expectation builders implement a fluent builder pattern.
+To use the expectation builder for sophisticated `Iterable`-toContain-expectations, you can type `toContain`
-- as you would when using the [Shortcut Functions](#shortcut-functions) `toContain` --
but type `.` as next step (so that you are using the property `toContain` instead of one of the shortcut functions).
Currently, the builder provides two options, either `inAnyOrder` or `inOrder`.
@@ -1152,8 +1156,8 @@ I expected subject: [1, 2, 2, 4] (java.util.Arrays.ArrayList <1234789>)
Since we have chosen the `only` option, Atrium shows us a summary1 where we see three things:
- Whether a specified `assertionCreator`-lambda matched (signified by `✔` or `✘`)
- the corresponding element or not (e.g. `✘ ▶ entry 1:` was `2` and we expected, it `is less than 2`)
-- Whether the expected size was correct or not (`✘ ▶ size:` was `4`, we expected it, `to be: 2` -- see also [Property Assertions](#property-assertions))
+ the corresponding element or not (e.g. `✘ ▶ entry 1:` was `2` and we expected, it `to be less than 2`)
+- Whether the expected size was correct or not (`✘ ▶ size:` was `4`, we expected it, `to equal: 2`
- and last but not least, mismatches or additional elements as further clue (`❗❗ additional elements detected`).
😍 We are pretty sure you are going to love this feature as well.
@@ -1164,7 +1168,7 @@ Please star Atrium if you like using it.
then only failing expectations are shown.
-💬 Show only failing expectations/elements earlier than 10 elements?
+💬 Show only failing expectations/elements earlier than 10 expected elements?
You can use the `report` option to specify when Atrium shall start to show only failing expectations.
Following an example changing the limit to 3 elements by using `showOnlyFailingIfMoreExpectedElementsThan` :
@@ -1287,13 +1291,13 @@ I expected subject: [1, 2, 2, 4] (java.util.Arrays.ArrayList <1234789>)
-## Map Assertions
+## Map Expectations
-Map assertions are kind of very similar to [Collection Assertions](#collection-assertions), also regarding reporting.
+Map expectations are kind of very similar to [Collection Expectations](#collection-expectations), also regarding reporting.
That is the reason why we are not going into too much detail here because we assume you are already familiar with it.
We provide again [Shortcut Functions](#shortcut-functions-1) for the most common scenarios
-and more [Sophisticated Assertion Builder](#sophisticated-assertion-builders-1) for the other cases.
+and more [Sophisticated Expectation Builder](#sophisticated-expectation-builders-1) for the other cases.
### Shortcut Functions
@@ -1313,8 +1317,8 @@ I expected subject: {a=1, b=2} (java.util.LinkedHashMap <1234789>)
```
-Next to making assertions based on key-value `Pair`s one can also define sub assertions for the value of an entry with
-the help of the parameter object `KeyValue`:
+Next to postulate expectations based on key-value `Pair`s one can also define sub expectations for the value of
+an entry with the help of the parameter object `KeyValue`:
@@ -1361,7 +1365,7 @@ I expected subject: {a=1, b=2} (java.util.LinkedHashMap <1234789>)
```
-And the other overload which expects a `KeyValue` and allows defining sub asertions for the value:
+And the other overload which expects a `KeyValue` and allows defining sub expectations for the value:
@@ -1388,7 +1392,7 @@ I expected subject: {a=1, b=2} (java.util.LinkedHashMap <1234789>)
```
-### Sophisticated Assertion Builders
+### Sophisticated Expectation Builders
Most functionality for `Map.toContain` are provided as shortcut functions but there is a handy one
in case you deal with ordered Maps: `.toContain.inOrder.only`
@@ -1418,7 +1422,7 @@ I expected subject: {a=1, b=2} (java.util.LinkedHashMap <1234789>)
```
-And the other expecting `KeyValue`s which allow specifying sub assertions for the value
+And the other expecting `KeyValue`s which allow specifying sub expectations for the value
@@ -1447,7 +1451,7 @@ I expected subject: {a=1, b=2} (java.util.LinkedHashMap <1234789>)
### Others
-In case you want to postulate an assertion about a value of one particular key, then you can use `getExisting`.
+In case you want to postulate an expectation about a value of one particular key, then you can use `getExisting`.
For instance:
@@ -1474,7 +1478,7 @@ I expected subject: {bernstein=Person(firstName=Leonard, lastName=Bernstein, age
```
-In case you want to make an assertion only about the keys or values of the `Map` then you can use `keys` or `values`:
+In case you hvae only expectations about the keys or values of the `Map` then you can use `keys` or `values`:
@@ -1503,10 +1507,10 @@ I expected subject: {a=1, b=2} (java.util.LinkedHashMap <1234789>)
Last but not least, you can use the non-reporting `asEntries()` function which
-turns `Expect