# Feedback wanted -- Atrium an assertion library

**URL:** <https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651>\
**Category:** Libraries\
**Created:** [December 3, 2017, 9:59am UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651 "2017-12-03T09:59:08Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![robstoll](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/robstoll/32/4488_2.png) [@robstoll](https://discuss.kotlinlang.org/u/robstoll)\
**Post date:** [December 3, 2017, 9:59am UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/1 "2017-12-03T09:59:08Z")

</div>

Hi everyone,  
I just released a new version of my assertion library called Atrium:  
[https://github.com/robstoll/atrium](https://github.com/robstoll/atrium)  
I think the project is now at a stage where I need some feedback.  
Would be awesome if you could have a quick look and tell me what you think.  
Do you miss a feature so that it stops you from using Atrium?  
Any feedback is appreciated 🙂

---

<div class="post-metadata">

**Author:** ![tieskedh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/tieskedh/32/2816_2.png) [@tieskedh](https://discuss.kotlinlang.org/u/tieskedh)\
**Post date:** [December 3, 2017, 10:14am UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/2 "2017-12-03T10:14:23Z")

</div>

Looks good.  
First thing I saw is that there are no infix-functions.  
Is this on purpose or maybe a future improvement?

---

<div class="post-metadata">

**Author:** ![robstoll](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/robstoll/32/4488_2.png) [@robstoll](https://discuss.kotlinlang.org/u/robstoll)\
**Post date:** [December 3, 2017, 10:17am UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/3 "2017-12-03T10:17:30Z")

</div>

Good point, I’ll add it to the list of future improvements. Thanks 🙂

---

<div class="post-metadata">

**Author:** ![robstoll](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/robstoll/32/4488_2.png) [@robstoll](https://discuss.kotlinlang.org/u/robstoll)\
**Post date:** [December 3, 2017, 2:24pm UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/4 "2017-12-03T14:24:55Z")

</div>

A follow-up question, how would you expect that an infix API looks like?

```auto
assert(1) toBe 2
assert(1) `to be` 2
1 toBe 2
1 `to be` 2

```

---

<div class="post-metadata">

**Author:** ![tieskedh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/tieskedh/32/2816_2.png) [@tieskedh](https://discuss.kotlinlang.org/u/tieskedh)\
**Post date:** [December 5, 2017, 3:24pm UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/5 "2017-12-05T15:24:37Z")

</div>

I would prefer the `toBe`, but if you look at other assertion frameworks, I believe `to be` is the preferred choice

---

<div class="post-metadata">

**Author:** ![robstoll](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/robstoll/32/4488_2.png) [@robstoll](https://discuss.kotlinlang.org/u/robstoll)\
**Post date:** [December 5, 2017, 3:58pm UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/6 "2017-12-05T15:58:22Z")

</div>

and which one  
`assert(1) toBe 2`  
or  
`1 toBe 2`

---

<div class="post-metadata">

**Author:** ![tieskedh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/tieskedh/32/2816_2.png) [@tieskedh](https://discuss.kotlinlang.org/u/tieskedh)\
**Post date:** [December 6, 2017, 2:58am UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/7 "2017-12-06T02:58:50Z")

</div>

I think with assert looks better.

---

<div class="post-metadata">

**Author:** ![robstoll](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/robstoll/32/4488_2.png) [@robstoll](https://discuss.kotlinlang.org/u/robstoll)\
**Post date:** [December 6, 2017, 11:53pm UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/8 "2017-12-06T23:53:11Z")

</div>

Thanks for all your feedback. You can get a sneak peek here from the infix API which will be available with v0.5.0:

> <https://github.com/robstoll/atrium/blob/main/apis/differences.md>

Your feedback is again welcome 🙂

---

<div class="post-metadata">

**Author:** ![maccamlc](https://avatars.discourse-cdn.com/v4/letter/m/50afbb/32.png) [@maccamlc](https://discuss.kotlinlang.org/u/maccamlc)\
**Post date:** [November 28, 2018, 12:18pm UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/9 "2018-11-28T12:18:17Z")

</div>

Just a note. I’ve just started to use Atrium along with Junit5 in a kotlin project.

I like it so far. I’ve added a few custom extensions for arrows Try.

Wondering if there are any plans to add some extensions for built in Arrow matchers, and perhaps something to do with JsonPath I could see being useful later.

---

<div class="post-metadata">

**Author:** ![robstoll](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/robstoll/32/4488_2.png) [@robstoll](https://discuss.kotlinlang.org/u/robstoll)\
**Post date:** [November 28, 2018, 4:32pm UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/10 "2018-11-28T16:32:42Z")

</div>

I don’t have particular plans to write assertion functions for Arrow as I don’t use the library myself. But please let me know what you need in particular and I’ll look into it. Ideally you share your existing functions 🙂

Regarding JsonPath, I planned to add assertion functions for Json in 0.9.0:  
[https://github.com/robstoll/atrium/issues/45](https://github.com/robstoll/atrium/issues/45)

Please have a look at it and provide feedback if you should miss a feature.

---

<div class="post-metadata">

**Author:** ![maccamlc](https://avatars.discourse-cdn.com/v4/letter/m/50afbb/32.png) [@maccamlc](https://discuss.kotlinlang.org/u/maccamlc)\
**Post date:** [November 30, 2018, 11:52am UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/11 "2018-11-30T11:52:32Z")

</div>

Look forward to Json functions. I’ll let know if I have any actual thoughts 🙂

In regard to Arrow, bear in mind that I am still relatively new to Kotlin, and understanding more each day.

What I’ve put together for Arrow Try matchers is:

```
import arrow.core.Try
import arrow.core.failure
import arrow.core.success
import ch.tutteli.atrium.creating.Assert
import ch.tutteli.atrium.creating.AssertionPlant
import ch.tutteli.atrium.domain.builders.AssertImpl
import ch.tutteli.atrium.reporting.RawString
import ch.tutteli.atrium.reporting.reporter
import ch.tutteli.atrium.reporting.translating.Untranslatable
import ch.tutteli.atrium.translations.DescriptionBasic
import ch.tutteli.atrium.verbs.assertThat

fun Assert<Try<Any>>.shouldBeSuccess() {
    createAndAddAssertion(
            DescriptionBasic.IS, RawString.create("a Success")) { subject.isSuccess() }
}

fun <A> Assert<Try<A>>.shouldBeSuccess(a: A) {
    val expected = a.success()
    createAndAddAssertion(
            DescriptionBasic.IS, expected) { subject == expected }
}

fun <A : Any> Assert<Try<A>>.shouldBeSuccess(assertionCreator: AssertionPlant<A>.() -> Unit) {
    AssertImpl.coreFactory.newReportingPlantAndAddAssertionsCreatedBy(
            Untranslatable("Success nested assertions"),
            { subject },
            reporter,
            {
                assertThat(subject).shouldBeSuccess()
                assertThat((subject as Try.Success).value, assertionCreator)
            }
    )
}

fun Assert<Try<Any>>.shouldBeFailure() {
    createAndAddAssertion(
            DescriptionBasic.IS, RawString.create("a Failure")) { subject.isFailure() }
}

fun Assert<Try<Any>>.shouldBeFailure(t: Throwable) {
    val expected = t.failure<Any>()
    createAndAddAssertion(
            DescriptionBasic.IS, expected) { subject == expected }
}

fun Assert<Try<Any>>.shouldBeFailure(assertionCreator: AssertionPlant<Throwable>.() -> Unit) {
    AssertImpl.coreFactory.newReportingPlantAndAddAssertionsCreatedBy(
            Untranslatable("Failure nested assertions"),
            { subject },
            reporter,
            {
                assertThat(subject).shouldBeFailure()
                assertThat((subject as Try.Failure).exception, assertionCreator)
            }
    )
}

inline fun <reified A : Throwable> Assert<Try<Any>>.shouldBeFailureOfType() {
    createAndAddAssertion(
            Untranslatable("is a Failure of type"), RawString.create(A::class.qualifiedName!!)) {
        when (subject) {
            is Try.Success -> false
            is Try.Failure -> (subject as Try.Failure).exception is A
        }
    }
}

```

Appreciate any feedback to, on how I’ve approached implementing the custom matchers 😄

---

<div class="post-metadata">

**Author:** ![medium](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/medium/32/10404_2.png) [@medium](https://discuss.kotlinlang.org/u/medium)\
**Post date:** [November 30, 2018, 12:01pm UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/12 "2018-11-30T12:01:50Z")

</div>

I wouldn’t go with `to be` because it is more annoying to type and you get syntax completion later. The slightly better look isn’t worth it. Another argument against it is that you introduce more clutter to your implementation just to meke it look a bit more like natural language.

From my point of view DSLs are often totally overrated. Business users won’t read your assertions anyway. And for a programmer the difference doesn’t really matter since the rest of the test code doesn’t look like natural language anyway. There a so many libs out there that strive for english like code and have terrible, unitiuitive API with strange constructs to implement the syntax. Spend some time in Scala land and you will be cured 😉

---

<div class="post-metadata">

**Author:** ![robstoll](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/robstoll/32/4488_2.png) [@robstoll](https://discuss.kotlinlang.org/u/robstoll)\
**Post date:** [November 30, 2018, 2:55pm UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/13 "2018-11-30T14:55:07Z")

</div>

Thanks for your thoughts, I went with `toBe`.

---

<div class="post-metadata">

**Author:** ![robstoll](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/robstoll/32/4488_2.png) [@robstoll](https://discuss.kotlinlang.org/u/robstoll)\
**Post date:** [December 2, 2018, 2:47pm UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/14 "2018-12-02T14:47:33Z")

</div>

Generally I recommend not to use `assertThat` within `assertThat`. You can, but if an inner `assertThat` fails it will throw an unexpected exception and the reporting is broken/does not behave like an assertion group. In your case you want to narrow the type from `Try` to `Try.Success`, for this you can use `AssertImpl.any.typeTransformation.transform` following an example for Either: [https://github.com/robstoll/atrium/blob/master/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/creating/any/typetransformation/creators/TypeTransformationAssertionCreatorSpec.kt#L41](https://github.com/robstoll/atrium/blob/master/domain/robstoll-lib/atrium-domain-robstoll-lib-jvm/src/test/kotlin/ch/tutteli/atrium/creating/any/typetransformation/creators/TypeTransformationAssertionCreatorSpec.kt#L41)

The error reporting will be more stable and look a bit better. In the same sense I would build up shouldBeSuccess which expects an `A` by shouldBeSuccess which expects an assertionCreator as follows:

```auto
fun <A> Assert<Try<A>>.shouldBeSuccess(a: A) = shouldBeSuccess { toBe(A) }

```

Same for shouldBeFailure.

---

<div class="post-metadata">

**Author:** ![maccamlc](https://avatars.discourse-cdn.com/v4/letter/m/50afbb/32.png) [@maccamlc](https://discuss.kotlinlang.org/u/maccamlc)\
**Post date:** [December 3, 2018, 1:24am UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/15 "2018-12-03T01:24:39Z")

</div>

Thanks. Very useful tips. I’ve refactored my shouldBeSuccess and shouldBeFailure.

I know have something like:

```auto
fun <A : Any> Assert<Try<A>>.shouldBeSuccess(assertionCreator: AssertionPlant<A>.() -> Unit) {
    val parameterObject = AnyTypeTransformation.ParameterObject(
            Untranslatable("is a"),
            RawString.create(Success::class.java.simpleName),
            this,
            assertionCreator,
            Untranslatable("Could not evaluate the defined assertion(s) -- Try.isSuccess() was false")
    )
    AssertImpl.any.typeTransformation.transform(
            parameterObject, { it.isSuccess() }, { (it as Success).value },
            AssertImpl.any.typeTransformation.failureHandlers.newExplanatory()
    )
}

inline fun <reified A : Throwable> Assert<Try<Any>>.shouldBeFailure(noinline assertionCreator: AssertionPlant<A>.() -> Unit) {
    val parameterObjectFailure: AnyTypeTransformation.ParameterObject<Try<Any>, Throwable> = AnyTypeTransformation.ParameterObject(
            Untranslatable("is a"),
            RawString.create(Failure::class.java.simpleName),
            this,
            { },
            Untranslatable("Could not evaluate the defined assertion(s) -- Try.isFailure() was false")
    )
    AssertImpl.any.typeTransformation.transform(
            parameterObjectFailure, { it.isFailure() }, { (it as Failure).exception },
            AssertImpl.any.typeTransformation.failureHandlers.newExplanatory()
    )
    val parameterObjectThrowable: AnyTypeTransformation.ParameterObject<Try<Any>, A> = AnyTypeTransformation.ParameterObject(
            Untranslatable("is a"),
            RawString.create(A::class.java.simpleName),
            this,
            assertionCreator,
            Untranslatable("Could not evaluate the defined assertion(s) -- Failure was not of type")
    )
    AssertImpl.any.typeTransformation.transform(
            parameterObjectThrowable, { (it as Failure).exception is A }, { (it as Failure).exception as A },
            AssertImpl.any.typeTransformation.failureHandlers.newExplanatory()
    )
}

```

The Failure one, I am trying to allow assertions (for-now) on the actual expected error type. Not sure if there is a neater way.

But then, I have an example where I still find myself using a nested AssertThat. Not sure if there are better available methods to avoid this type of thing, or if I am not understanding the best way to use it yet.

```
assertThat(subject).shouldBeSuccess {
           assertThat(subject.details) {
                    property(subject::code).toBe("1")
                    property(subject::message).toBe("Message")
                    property(subject::detailMessage).notToBeNull {
                        assertThat(subject).containsStrictly("Invalid request")
                    }
            }
}

```

Thanks for taking the time to respond. I’m liking the library so far in my attempts to learn Kotlin 🙂

---

<div class="post-metadata">

**Author:** ![robstoll](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/robstoll/32/4488_2.png) [@robstoll](https://discuss.kotlinlang.org/u/robstoll)\
**Post date:** [December 3, 2018, 6:25am UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/16 "2018-12-03T06:25:28Z")

</div>

You can use `isA<YourType>{}` for regular subtyping assertions (see [atrium/README.md at main · robstoll/atrium · GitHub](https://github.com/robstoll/atrium/blob/master/README.md#type-assertions)). Assign the first call of `AssertImpl.any.typeTransformation.transform` to a variable, say `plant`. You can then define assertions for the new subject (of type Throwable in this case) via `addAssertionsCreatedBy`. Yet, there is a simpler way since ParamObject does exactly that. Currently you pass `{ }` as assertionCreator. Which does nothing. Instead you could do:

```auto
{ 
  isA<A> { 
    addAssertionsCreatedBy (assertionCreator)
  }
}

```

For assertThat within assertThat. Use `property` as you already did or `returnValueOf` in case it is a method.

No need for assertThat for the following:

```auto
property(subject::detailMessage).notToBeNull {
                        assertThat(subject).containsStrictly("Invalid request")
                    }

```

You can use containsStrictly directly.

---

<div class="post-metadata">

**Author:** ![maccamlc](https://avatars.discourse-cdn.com/v4/letter/m/50afbb/32.png) [@maccamlc](https://discuss.kotlinlang.org/u/maccamlc)\
**Post date:** [December 4, 2018, 12:50am UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/17 "2018-12-04T00:50:51Z")

</div>

That’s great. Thanks for the help.

Got some much nicer assertions now, that should help with my colleagues picking this up, who are even newer to Kotlin 🙂

---

<div class="post-metadata">

**Author:** ![robstoll](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/robstoll/32/4488_2.png) [@robstoll](https://discuss.kotlinlang.org/u/robstoll)\
**Post date:** [December 4, 2018, 4:45pm UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/18 "2018-12-04T16:45:01Z")

</div>

No worries. Would be great if you could contribute back your assertion functions to Atrium - others using Arrow could certainly use it as well. I assume you are going to write more for other data types. A pull request on GitHub (or a private message with the code) would be more than welcome. I would then finalise your request so that it is available in all APIs and supports i18n. Looking forward to it 😉

---

<div class="post-metadata">

**Author:** ![maccamlc](https://avatars.discourse-cdn.com/v4/letter/m/50afbb/32.png) [@maccamlc](https://discuss.kotlinlang.org/u/maccamlc)\
**Post date:** [December 4, 2018, 10:51pm UTC](https://discuss.kotlinlang.org/t/feedback-wanted-atrium-an-assertion-library/5651/19 "2018-12-04T22:51:39Z")

</div>

No worries.

I will definitely try to get a PR created, when have a chance 🙂
