mirror of
https://github.com/jlengrand/atrium.git
synced 2026-03-10 08:01:19 +00:00
replace ThrowableThrown by normal expect
For this to work we have to: - introduce Fun0Assertions with the two assertion function isThrowing and isNotThrowing - rename expect which expects an act to expectOld (remove in subsequent commit) - fix old smoke tests which use wrong assertion verbs
This commit is contained in:
77
README.md
77
README.md
@@ -319,6 +319,7 @@ expect: 10 (kotlin.Int <1234789>)
|
||||
◆ is greater than: 10 (kotlin.Int <1234789>)
|
||||
```
|
||||
</ex-group>
|
||||
|
||||
An assertion group throws an `AssertionError` at the end of its block; hence reports that both assertions do not hold.
|
||||
|
||||
You can use `and` as filling element between single assertions and assertion group blocks:
|
||||
@@ -343,15 +344,16 @@ expect {
|
||||
```
|
||||
↑ <sub>[Example](https://github.com/robstoll/atrium/tree/master/samples/readme-examples/src/main/kotlin/readme/examples/ReadmeSpec.kt#L67)</sub> ↓ <sub>Output</sub>
|
||||
```text
|
||||
expect the thrown exception: java.lang.IllegalArgumentException
|
||||
◆ is instance of type: IllegalStateException (java.lang.IllegalStateException)
|
||||
» Properties of the unexpected IllegalArgumentException
|
||||
» message: "name is empty" <1234789>
|
||||
» stacktrace:
|
||||
⚬ readme.examples.ReadmeSpec$1$4$1.invoke(ReadmeSpec.kt:70)
|
||||
⚬ readme.examples.ReadmeSpec$1$4$1.invoke(ReadmeSpec.kt:45)
|
||||
⚬ readme.examples.ReadmeSpec$1$4.invoke(ReadmeSpec.kt:627)
|
||||
⚬ readme.examples.ReadmeSpec$1$4.invoke(ReadmeSpec.kt:45)
|
||||
expect: () -> kotlin.Nothing (readme.examples.ReadmeSpec$1$4$1 <1234789>)
|
||||
◆ ▶ thrown exception when called: java.lang.IllegalArgumentException
|
||||
◾ is instance of type: IllegalStateException (java.lang.IllegalStateException)
|
||||
» Properties of the unexpected IllegalArgumentException
|
||||
» message: "name is empty" <1234789>
|
||||
» stacktrace:
|
||||
⚬ readme.examples.ReadmeSpec$1$4$1.invoke(ReadmeSpec.kt:70)
|
||||
⚬ readme.examples.ReadmeSpec$1$4$1.invoke(ReadmeSpec.kt:45)
|
||||
⚬ readme.examples.ReadmeSpec$1$4.invoke(ReadmeSpec.kt:626)
|
||||
⚬ readme.examples.ReadmeSpec$1$4.invoke(ReadmeSpec.kt:45)
|
||||
```
|
||||
</ex-toThrow1>
|
||||
|
||||
@@ -377,9 +379,10 @@ expect {
|
||||
```
|
||||
↑ <sub>[Example](https://github.com/robstoll/atrium/tree/master/samples/readme-examples/src/main/kotlin/readme/examples/ReadmeSpec.kt#L74)</sub> ↓ <sub>Output</sub>
|
||||
```text
|
||||
expect the thrown exception: java.lang.IllegalArgumentException
|
||||
◆ ▶ message: null
|
||||
◾ is instance of type: String (kotlin.String) -- Class: String (java.lang.String)
|
||||
expect: () -> kotlin.Nothing (readme.examples.ReadmeSpec$1$5$1 <1234789>)
|
||||
◆ ▶ thrown exception when called: java.lang.IllegalArgumentException
|
||||
◾ ▶ message: null
|
||||
◾ is instance of type: String (kotlin.String) -- Class: String (java.lang.String)
|
||||
```
|
||||
</ex-toThrow2>
|
||||
|
||||
@@ -396,10 +399,11 @@ expect {
|
||||
```
|
||||
↑ <sub>[Example](https://github.com/robstoll/atrium/tree/master/samples/readme-examples/src/main/kotlin/readme/examples/ReadmeSpec.kt#L80)</sub> ↓ <sub>Output</sub>
|
||||
```text
|
||||
expect the thrown exception: java.lang.IllegalArgumentException
|
||||
◆ ▶ message: null
|
||||
◾ is instance of type: String (kotlin.String) -- Class: String (java.lang.String)
|
||||
» starts with: "firstName" <1234789>
|
||||
expect: () -> kotlin.Nothing (readme.examples.ReadmeSpec$1$6$1 <1234789>)
|
||||
◆ ▶ thrown exception when called: java.lang.IllegalArgumentException
|
||||
◾ ▶ message: null
|
||||
◾ is instance of type: String (kotlin.String) -- Class: String (java.lang.String)
|
||||
» starts with: "firstName" <1234789>
|
||||
```
|
||||
</ex-toThrow3>
|
||||
|
||||
@@ -418,8 +422,8 @@ expect {
|
||||
```
|
||||
↑ <sub>[Example](https://github.com/robstoll/atrium/tree/master/samples/readme-examples/src/main/kotlin/readme/examples/ReadmeSpec.kt#L88)</sub> ↓ <sub>Output</sub>
|
||||
```text
|
||||
expect the thrown exception: java.lang.IllegalArgumentException
|
||||
◆ is: not thrown at all
|
||||
expect: () -> kotlin.Nothing (readme.examples.ReadmeSpec$1$7$1 <1234789>)
|
||||
◆ does not: throw when called
|
||||
» Properties of the unexpected IllegalArgumentException
|
||||
» message: "name is empty" <1234789>
|
||||
» stacktrace:
|
||||
@@ -1604,25 +1608,26 @@ expect {
|
||||
```
|
||||
↑ <sub>[Example](https://github.com/robstoll/atrium/tree/master/samples/readme-examples/src/main/kotlin/readme/examples/ReadmeSpec.kt#L404)</sub> ↓ <sub>Output</sub>
|
||||
```text
|
||||
expect the thrown exception: java.lang.IllegalArgumentException
|
||||
◆ is instance of type: IllegalStateException (java.lang.IllegalStateException)
|
||||
» ▶ message: CANNOT evaluate representation as it is based on subject which is not defined.
|
||||
» is instance of type: String (kotlin.String) -- Class: String (java.lang.String)
|
||||
» contains:
|
||||
⚬ value: "no no no" <1234789>
|
||||
⚬ ▶ number of occurrences: -1
|
||||
◾ is at least: 1
|
||||
» Properties of the unexpected IllegalArgumentException
|
||||
» message: "no no no..." <1234789>
|
||||
» stacktrace:
|
||||
⚬ readme.examples.ReadmeSpec2$1$31$1.invoke(ReadmeSpec.kt:409)
|
||||
⚬ readme.examples.ReadmeSpec2$1$31$1.invoke(ReadmeSpec.kt:221)
|
||||
⚬ readme.examples.ReadmeSpec2$1$31.invoke(ReadmeSpec.kt:627)
|
||||
⚬ readme.examples.ReadmeSpec2$1$31.invoke(ReadmeSpec.kt:221)
|
||||
» cause: java.lang.UnsupportedOperationException
|
||||
» message: "not supported" <1234789>
|
||||
expect: () -> kotlin.Nothing (readme.examples.ReadmeSpec2$1$31$1 <1234789>)
|
||||
◆ ▶ thrown exception when called: java.lang.IllegalArgumentException
|
||||
◾ is instance of type: IllegalStateException (java.lang.IllegalStateException)
|
||||
» ▶ message: CANNOT evaluate representation as it is based on subject which is not defined.
|
||||
» is instance of type: String (kotlin.String) -- Class: String (java.lang.String)
|
||||
» contains:
|
||||
⚬ value: "no no no" <1234789>
|
||||
⚬ ▶ number of occurrences: -1
|
||||
◾ is at least: 1
|
||||
» Properties of the unexpected IllegalArgumentException
|
||||
» message: "no no no..." <1234789>
|
||||
» stacktrace:
|
||||
⚬ readme.examples.ReadmeSpec2$1$31$1.invoke(ReadmeSpec.kt:407)
|
||||
⚬ readme.examples.ReadmeSpec2$1$31$1.invoke(ReadmeSpec.kt:409)
|
||||
⚬ readme.examples.ReadmeSpec2$1$31$1.invoke(ReadmeSpec.kt:221)
|
||||
⚬ readme.examples.ReadmeSpec2$1$31.invoke(ReadmeSpec.kt:626)
|
||||
⚬ readme.examples.ReadmeSpec2$1$31.invoke(ReadmeSpec.kt:221)
|
||||
» cause: java.lang.UnsupportedOperationException
|
||||
» message: "not supported" <1234789>
|
||||
» stacktrace:
|
||||
⚬ readme.examples.ReadmeSpec2$1$31$1.invoke(ReadmeSpec.kt:407)
|
||||
```
|
||||
</ex-add-info-3>
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package ch.tutteli.atrium.api.fluent.en_GB
|
||||
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.domain.builders.ExpectImpl
|
||||
|
||||
/**
|
||||
* Expects that the thrown [Throwable] *is a* [TExpected] (the same type or a sub-type).
|
||||
*
|
||||
* Notice, that asserting a generic type is [flawed](https://youtrack.jetbrains.com/issue/KT-27826).
|
||||
* For instance `toThrow<MyException<String>>` would only check if the subject is a `MyException` without checking if
|
||||
* the element type is actually `String`.
|
||||
*
|
||||
* @return An assertion container with the new type [TExpected].
|
||||
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
|
||||
*/
|
||||
inline fun <reified TExpected : Throwable> Expect<out () -> Any?>.toThrow(): Expect<TExpected> =
|
||||
ExpectImpl.fun0.isThrowing(this, TExpected::class).getExpectOfFeature()
|
||||
|
||||
/**
|
||||
* Expects that the thrown [Throwable] *is a* [TExpected] (the same type or a sub-type) and
|
||||
* that it holds all assertions the given [assertionCreator] creates.
|
||||
*
|
||||
* Notice, in contrast to other assertion functions which expect an [assertionCreator], this function returns not
|
||||
* [Expect] of the initial type, which was `Throwable?` but an [Expect] of the specified type [TExpected].
|
||||
* This has the side effect that a subsequent call has only assertion functions available which are suited
|
||||
* for [TExpected]. Since [Expect] is invariant it especially means that an assertion function which was not
|
||||
* written in a generic way will not be available. Fixing such a function is easy (in most cases),
|
||||
* you need to transform it into a generic from. Following an example:
|
||||
*
|
||||
* ```
|
||||
* interface Person
|
||||
* class Student: Person
|
||||
* fun Expect<Person>.foo() = "dummy" // limited only to Person, not recommended
|
||||
* fun <T: Person> Expect<T>.bar() = "dummy" // available to Person and all subtypes, the way to go
|
||||
* fun Expect<Student>.baz() = "dummy" // specific only for Student, ok since closed class
|
||||
*
|
||||
* val p: Person = Student()
|
||||
* expect(p) // subject of type Person
|
||||
* .isA<Student> { ... } // subject now refined to Student
|
||||
* .baz() // available via Student
|
||||
* .foo() // not available to Student, only to Person, results in compilation error
|
||||
* .bar() // available via T : Person
|
||||
* ```
|
||||
*
|
||||
* Notice, that asserting a generic type is [flawed](https://youtrack.jetbrains.com/issue/KT-27826).
|
||||
* For instance `toThrow<MyException<String>>` would only check if the subject is a `MyException` without checking if
|
||||
* the element type is actually `String`.
|
||||
*
|
||||
* @return An assertion container with the new type [TExpected].
|
||||
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
|
||||
*/
|
||||
inline fun <reified TExpected : Throwable> Expect<out () -> Any?>.toThrow(
|
||||
noinline assertionCreator: Expect<TExpected>.() -> Unit
|
||||
): Expect<TExpected> = ExpectImpl.fun0.isThrowing(this, TExpected::class).addToFeature(assertionCreator)
|
||||
|
||||
|
||||
/**
|
||||
* Expects that no [Throwable] is thrown at all when calling the subject (a lambda with arity 0, i.e. without argument)
|
||||
* and changes the subject of the assertion to the return value of type [R].
|
||||
*
|
||||
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
|
||||
*/
|
||||
fun <R, T : () -> R> Expect<T>.notToThrow(): Expect<R> = ExpectImpl.fun0.isNotThrowing(this).getExpectOfFeature()
|
||||
@@ -4,7 +4,6 @@ import ch.tutteli.atrium.api.cc.de_CH.messageEnthaelt
|
||||
import ch.tutteli.atrium.api.cc.de_CH.wirft
|
||||
import ch.tutteli.atrium.api.cc.de_CH.wirftNichts
|
||||
import ch.tutteli.atrium.api.fluent.en_GB.toBe
|
||||
import ch.tutteli.atrium.api.verbs.assertThat
|
||||
import ch.tutteli.atrium.assertions.Assertion
|
||||
import ch.tutteli.atrium.creating.Assert
|
||||
import ch.tutteli.atrium.creating.AssertionPlant
|
||||
@@ -41,14 +40,14 @@ class SmokeTest {
|
||||
|
||||
@Test
|
||||
fun assertAnExceptionOccurred() {
|
||||
assertThat {
|
||||
expect {
|
||||
throw IllegalArgumentException()
|
||||
}.wirft<IllegalArgumentException>{}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertAnExceptionWithAMessageOccurred() {
|
||||
assertThat {
|
||||
expect {
|
||||
throw IllegalArgumentException("oho... hello btw")
|
||||
}.wirft<IllegalArgumentException> {
|
||||
messageEnthaelt("hello")
|
||||
@@ -57,7 +56,7 @@ class SmokeTest {
|
||||
|
||||
@Test
|
||||
fun assertNotToThrow() {
|
||||
assertThat {
|
||||
expect {
|
||||
|
||||
}.wirftNichts()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import ch.tutteli.atrium.api.cc.infix.en_GB.*
|
||||
import ch.tutteli.atrium.api.verbs.assertThat
|
||||
import ch.tutteli.atrium.assertions.Assertion
|
||||
import ch.tutteli.atrium.creating.Assert
|
||||
import ch.tutteli.atrium.creating.AssertionPlant
|
||||
@@ -28,14 +27,14 @@ class SmokeTest {
|
||||
|
||||
@Test
|
||||
fun assertAnExceptionOccurred() {
|
||||
assertThat {
|
||||
assert {
|
||||
throw IllegalArgumentException()
|
||||
}.toThrow<IllegalArgumentException> {}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertAnExceptionWithAMessageOccurred() {
|
||||
assertThat {
|
||||
assert {
|
||||
throw IllegalArgumentException("oho... hello btw")
|
||||
}.toThrow<IllegalArgumentException> {
|
||||
o messageContains "hello"
|
||||
@@ -44,7 +43,7 @@ class SmokeTest {
|
||||
|
||||
@Test
|
||||
fun assertNotToThrow() {
|
||||
assertThat {
|
||||
assert {
|
||||
|
||||
}.notToThrow()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package ch.tutteli.atrium.domain.creating
|
||||
|
||||
import ch.tutteli.atrium.core.polyfills.loadSingleService
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.domain.creating.changers.ChangedSubjectPostStep
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* The access point to an implementation of [Fun0Assertions].
|
||||
*
|
||||
* It loads the implementation lazily via [loadSingleService].
|
||||
*/
|
||||
val fun0Assertions by lazy { loadSingleService(Fun0Assertions::class) }
|
||||
|
||||
|
||||
/**
|
||||
* Defines the minimum set of assertion functions and builders applicable to lambdas with arity 0
|
||||
* (i.e. a lambda with 0 arguments or in other words `() -> R`),
|
||||
* which an implementation of the domain of Atrium has to provide.
|
||||
*/
|
||||
interface Fun0Assertions {
|
||||
|
||||
fun <TExpected : Throwable> isThrowing(
|
||||
assertionContainer: Expect<out () -> Any?>,
|
||||
expectedType: KClass<TExpected>
|
||||
): ChangedSubjectPostStep<*, TExpected>
|
||||
|
||||
fun <R, T : () -> R> isNotThrowing(assertionContainer: Expect<T>): ChangedSubjectPostStep<*, R>
|
||||
}
|
||||
@@ -88,6 +88,12 @@ object ExpectImpl {
|
||||
*/
|
||||
inline val floatingPoint get() = FloatingPointAssertionsBuilder
|
||||
|
||||
/**
|
||||
* Returns [Fun0AssertionsBuilder] - [Assertion]s applicable to lambdas with arity 0
|
||||
* which inter alia delegates to the implementation of [FloatingPointAssertions].
|
||||
*/
|
||||
inline val fun0 get() = Fun0AssertionsBuilder
|
||||
|
||||
/**
|
||||
* Returns [IterableAssertionsBuilder].
|
||||
* which inter alia delegates to the implementation of [IterableAssertions].
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
@file:Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||
|
||||
package ch.tutteli.atrium.domain.builders.creating
|
||||
|
||||
import ch.tutteli.atrium.core.polyfills.loadSingleService
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.domain.creating.Fun0Assertions
|
||||
import ch.tutteli.atrium.domain.creating.fun0Assertions
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Delegates inter alia to the implementation of [Fun0Assertions].
|
||||
* In detail, it implements [Fun0Assertions] by delegating to [fun0Assertions]
|
||||
* which in turn delegates to the implementation via [loadSingleService].
|
||||
*/
|
||||
object Fun0AssertionsBuilder : Fun0Assertions {
|
||||
|
||||
override inline fun <TExpected : Throwable> isThrowing(
|
||||
assertionContainer: Expect<out () -> Any?>,
|
||||
expectedType: KClass<TExpected>
|
||||
) = fun0Assertions.isThrowing(assertionContainer, expectedType)
|
||||
|
||||
override inline fun <R, T : () -> R> isNotThrowing(assertionContainer: Expect<T>) =
|
||||
fun0Assertions.isNotThrowing(assertionContainer)
|
||||
}
|
||||
@@ -42,7 +42,7 @@ object NewFeatureAssertionsBuilder : NewFeatureAssertions {
|
||||
* Also, if the extraction of the feature is always safe, then you can just use one of the fN functions
|
||||
* (e.g. [f1] for a function expecting 1 argument) or [property].
|
||||
*/
|
||||
inline fun <T> extractor(originalAssertionContainer: Expect<T>) =
|
||||
inline fun <T> extractor(originalAssertionContainer: Expect<T>): FeatureExtractorBuilder.DescriptionStep<T> =
|
||||
FeatureExtractorBuilder.create(originalAssertionContainer)
|
||||
|
||||
|
||||
@@ -71,16 +71,16 @@ object NewFeatureAssertionsBuilder : NewFeatureAssertions {
|
||||
|
||||
fun <T, R> manualFeature(
|
||||
assertionContainer: Expect<T>,
|
||||
name: String,
|
||||
description: String,
|
||||
provider: T.() -> R
|
||||
): ExtractedFeaturePostStep<T, R> = extractFeature(assertionContainer, name, provider)
|
||||
): ExtractedFeaturePostStep<T, R> = extractFeature(assertionContainer, description, provider)
|
||||
|
||||
fun <T, R> manualFeature(
|
||||
assertionContainer: Expect<T>,
|
||||
name: Translatable,
|
||||
description: Translatable,
|
||||
provider: T.() -> R
|
||||
): ExtractedFeaturePostStep<T, R> =
|
||||
genericFeature(assertionContainer, createMetaFeature(assertionContainer, name, provider))
|
||||
genericFeature(assertionContainer, createMetaFeature(assertionContainer, description, provider))
|
||||
|
||||
fun <T, R> genericSubjectBasedFeature(
|
||||
assertionContainer: Expect<T>,
|
||||
@@ -104,31 +104,31 @@ object NewFeatureAssertionsBuilder : NewFeatureAssertions {
|
||||
|
||||
private fun <T, R> extractFeature(
|
||||
assertionContainer: Expect<T>,
|
||||
name: String,
|
||||
description: String,
|
||||
provider: (T) -> R
|
||||
): ExtractedFeaturePostStep<T, R> =
|
||||
genericFeature(assertionContainer, createMetaFeature(assertionContainer, name, provider))
|
||||
genericFeature(assertionContainer, createMetaFeature(assertionContainer, description, provider))
|
||||
|
||||
private fun <T, R> createMetaFeature(
|
||||
assertionContainer: Expect<T>,
|
||||
name: String,
|
||||
description: String,
|
||||
provider: (T) -> R
|
||||
): MetaFeature<R> = createMetaFeature(assertionContainer, Untranslatable(name), provider)
|
||||
): MetaFeature<R> = createMetaFeature(assertionContainer, Untranslatable(description), provider)
|
||||
|
||||
private fun <T, R> createMetaFeature(
|
||||
assertionContainer: Expect<T>,
|
||||
name: Translatable,
|
||||
description: Translatable,
|
||||
provider: (T) -> R
|
||||
): MetaFeature<R> {
|
||||
return assertionContainer.maybeSubject.fold({
|
||||
MetaFeature(
|
||||
name,
|
||||
description,
|
||||
RawString.create(ErrorMessages.REPRESENTATION_BASED_ON_SUBJECT_NOT_DEFINED),
|
||||
None
|
||||
)
|
||||
}) {
|
||||
val prop = provider(it)
|
||||
MetaFeature(name, prop, Some(prop))
|
||||
MetaFeature(description, prop, Some(prop))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,8 @@ class MetaFeatureOption<T>(private val expect: Expect<T>) {
|
||||
|
||||
//@formatter:off
|
||||
/**
|
||||
* Creates a [MetaFeature] for the given function [f] without arguments => use [f0] in case of ambiguity issues.
|
||||
* Creates a [MetaFeature] for the given function [f] without arguments => use [f0] in case of
|
||||
* ambiguity issues.
|
||||
*
|
||||
* Notice for assertion function writers: you should use [ExpectImpl].[feature][ExpectImpl.feature] and pass a
|
||||
* class reference instead of using this convenience function (e.g. `ExpectImpl.feature(MyClass::fun)`).
|
||||
@@ -168,7 +169,8 @@ class MetaFeatureOption<T>(private val expect: Expect<T>) {
|
||||
f0(f)
|
||||
|
||||
/**
|
||||
* Creates a [MetaFeature] for the given function [f] which expects 1 argument => use [f1] in case of ambiguity issues.
|
||||
* Creates a [MetaFeature] for the given function [f] which expects 1 argument => use [f1] in case of
|
||||
* ambiguity issues.
|
||||
*
|
||||
* Notice for assertion function writers: you should use [ExpectImpl].[feature][ExpectImpl.feature] and pass a
|
||||
* class reference instead of using this convenience function (e.g. `ExpectImpl.feature(MyClass::fun, ...)`).
|
||||
@@ -179,7 +181,8 @@ class MetaFeatureOption<T>(private val expect: Expect<T>) {
|
||||
f1(f, a1)
|
||||
|
||||
/**
|
||||
* Creates a [MetaFeature] for the given function [f] which expects 2 arguments => use [f2] in case of ambiguity issues.
|
||||
* Creates a [MetaFeature] for the given function [f] which expects 2 arguments => use [f2] in case of
|
||||
* ambiguity issues.
|
||||
*
|
||||
* Notice for assertion function writers: you should use [ExpectImpl].[feature][ExpectImpl.feature] and pass a
|
||||
* class reference instead of using this convenience function (e.g. `ExpectImpl.feature(MyClass::fun, ...)`).
|
||||
@@ -190,7 +193,8 @@ class MetaFeatureOption<T>(private val expect: Expect<T>) {
|
||||
f2(f, a1, a2)
|
||||
|
||||
/**
|
||||
* Creates a [MetaFeature] for the given function [f] which expects 3 arguments => use [f3] in case of ambiguity issues.
|
||||
* Creates a [MetaFeature] for the given function [f] which expects 3 arguments => use [f3] in case of
|
||||
* ambiguity issues.
|
||||
*
|
||||
* Notice for assertion function writers: you should use [ExpectImpl].[feature][ExpectImpl.feature] and pass a
|
||||
* class reference instead of using this convenience function (e.g. `ExpectImpl.feature(MyClass::fun, ...)`).
|
||||
@@ -201,7 +205,8 @@ class MetaFeatureOption<T>(private val expect: Expect<T>) {
|
||||
f3(f, a1, a2, a3)
|
||||
|
||||
/**
|
||||
* Creates a [MetaFeature] for the given function [f] which expects 4 arguments => use [f4] in case of ambiguity issues.
|
||||
* Creates a [MetaFeature] for the given function [f] which expects 4 arguments => use [f4] in case of
|
||||
* ambiguity issues.
|
||||
*
|
||||
* Notice for assertion function writers: you should use [ExpectImpl].[feature][ExpectImpl.feature] and pass a
|
||||
* class reference instead of using this convenience function (e.g. `ExpectImpl.feature(MyClass::fun, ...)`).
|
||||
@@ -212,7 +217,8 @@ class MetaFeatureOption<T>(private val expect: Expect<T>) {
|
||||
f4(f, a1, a2, a3, a4)
|
||||
|
||||
/**
|
||||
* Creates a [MetaFeature] for the given function [f] which expects 5 arguments => use [f5] in case of ambiguity issues.
|
||||
* Creates a [MetaFeature] for the given function [f] which expects 5 arguments => use [f5] in case of
|
||||
* ambiguity issues.
|
||||
*
|
||||
* Notice for assertion function writers: you should use [ExpectImpl].[feature][ExpectImpl.feature] and pass a
|
||||
* class reference instead of using this convenience function (e.g. `ExpectImpl.feature(MyClass::fun, ...)`).
|
||||
|
||||
@@ -123,8 +123,7 @@ interface FeatureExtractorBuilder {
|
||||
|
||||
/**
|
||||
* Step to define the feature extraction as such where a one can include a check by returning [None] in case the
|
||||
* extraction should not be carried out
|
||||
* to see whether the feature extraction is feasible or not.
|
||||
* extraction should not be carried out.
|
||||
*
|
||||
* @param T the type of the current subject.
|
||||
*/
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
package ch.tutteli.atrium.domain.builders.creating.changers
|
||||
|
||||
import ch.tutteli.atrium.assertions.DescriptiveAssertion
|
||||
import ch.tutteli.atrium.core.None
|
||||
import ch.tutteli.atrium.core.Option
|
||||
import ch.tutteli.atrium.core.Some
|
||||
import ch.tutteli.atrium.core.polyfills.cast
|
||||
import ch.tutteli.atrium.creating.Assert
|
||||
import ch.tutteli.atrium.creating.AssertionPlantNullable
|
||||
@@ -17,9 +20,6 @@ import ch.tutteli.atrium.reporting.translating.Translatable
|
||||
import ch.tutteli.atrium.reporting.translating.Untranslatable
|
||||
import ch.tutteli.atrium.translations.DescriptionAnyAssertion
|
||||
import kotlin.reflect.KClass
|
||||
import ch.tutteli.atrium.core.Some
|
||||
import ch.tutteli.atrium.core.None
|
||||
import ch.tutteli.atrium.core.Option
|
||||
|
||||
/**
|
||||
* Defines the contract for sophisticated `change subject` processes.
|
||||
@@ -117,8 +117,8 @@ interface SubjectChangerBuilder {
|
||||
fun <TSub : Any> downCastTo(subType: KClass<TSub>): FailureHandlerOption<T, TSub> =
|
||||
withDescriptionAndRepresentation(DescriptionAnyAssertion.IS_A, subType)
|
||||
.withTransformation {
|
||||
Option.someIf( subType.isInstance(it) ){ subType.cast(it) }
|
||||
}
|
||||
Option.someIf(subType.isInstance(it)) { subType.cast(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the given [description] and [representation] to represent the change by delegating to the other overload
|
||||
@@ -152,7 +152,7 @@ interface SubjectChangerBuilder {
|
||||
|
||||
/**
|
||||
* Step to define the transformation which yields the new subject wrapped into a [Some] if the transformation
|
||||
* as such can be carried out or [None].
|
||||
* as such can be carried out; otherwise [None].
|
||||
*
|
||||
* @param T the type of the current subject.
|
||||
*/
|
||||
|
||||
@@ -77,13 +77,13 @@ class FinalStepImpl<T, R>(
|
||||
transformAndApply = { assertionCreator -> transformIt(this, Some(assertionCreator)) }
|
||||
)
|
||||
|
||||
private fun transformIt(expect: Expect<T>, subAssertions: Option<Expect<R>.() -> Unit>) =
|
||||
private fun transformIt(expect: Expect<T>, maybeSubAssertions: Option<Expect<R>.() -> Unit>) =
|
||||
subjectChanger.reported(
|
||||
expect,
|
||||
transformationStep.description,
|
||||
transformationStep.representation,
|
||||
transformation,
|
||||
failureHandler,
|
||||
subAssertions
|
||||
maybeSubAssertions
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import ch.tutteli.atrium.api.fluent.en_GB.startsWith
|
||||
import ch.tutteli.atrium.api.fluent.en_GB.toThrow
|
||||
import ch.tutteli.atrium.api.verbs.internal.expect
|
||||
import ch.tutteli.atrium.core.None
|
||||
import ch.tutteli.atrium.core.Option
|
||||
import ch.tutteli.atrium.core.Some
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.domain.builders.ExpectImpl
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package ch.tutteli.atrium.domain.robstoll.lib.creating
|
||||
|
||||
import ch.tutteli.atrium.assertions.Assertion
|
||||
import ch.tutteli.atrium.core.None
|
||||
import ch.tutteli.atrium.core.Option
|
||||
import ch.tutteli.atrium.core.Some
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.domain.builders.ExpectImpl
|
||||
import ch.tutteli.atrium.domain.creating.changers.ChangedSubjectPostStep
|
||||
import ch.tutteli.atrium.domain.creating.changers.SubjectChanger
|
||||
import ch.tutteli.atrium.domain.robstoll.lib.creating.throwable.thrown.creators.ThrowableThrownFailureHandler
|
||||
import ch.tutteli.atrium.reporting.RawString
|
||||
import ch.tutteli.atrium.reporting.reporter
|
||||
import ch.tutteli.atrium.translations.DescriptionFunLikeAssertion.*
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
fun <TExpected : Throwable> _isThrowing(
|
||||
assertionContainer: Expect<out () -> Any?>,
|
||||
expectedType: KClass<TExpected>
|
||||
): ChangedSubjectPostStep<*, TExpected> =
|
||||
//TODO allow to pass an ExpectOptions which allows to change the nullRepresentation.
|
||||
ExpectImpl.feature
|
||||
.manualFeature(assertionContainer, THROWN_EXCEPTION_WHEN_CALLED) {
|
||||
catchAndAdjustThrowable(this).fold(
|
||||
{ it },
|
||||
{
|
||||
// use null as subject in case no exception occurred
|
||||
null
|
||||
}
|
||||
)
|
||||
}
|
||||
.getExpectOfFeature()
|
||||
.let {
|
||||
ExpectImpl.changeSubject(it).reportBuilder()
|
||||
.downCastTo(expectedType)
|
||||
.withFailureHandler(ThrowableThrownFailureHandler(maxStackTrace = 7))
|
||||
.build()
|
||||
}
|
||||
|
||||
private inline fun <R> catchAndAdjustThrowable(act: () -> R): Either<R> =
|
||||
try {
|
||||
Right(act())
|
||||
} catch (throwable: Throwable) {
|
||||
//TODO should be taken from current assertionContainer once it is configured this way
|
||||
reporter.atriumErrorAdjuster.adjust(throwable)
|
||||
Left(throwable)
|
||||
}
|
||||
|
||||
//TODO consider to move to core of Atrium
|
||||
private sealed class Either<out R> {
|
||||
|
||||
inline fun <T> map(f: (R) -> T): Either<T> = flatMap { Right(f(it)) }
|
||||
|
||||
inline fun <T> flatMap(f: (R) -> Either<T>): Either<T> = fold({ Left(it) }, f)
|
||||
|
||||
inline fun <T> fold(default: (Throwable) -> T, f: (R) -> T): T = when (this) {
|
||||
is Right -> f(this.r)
|
||||
is Left -> default(this.l)
|
||||
}
|
||||
}
|
||||
|
||||
private data class Left(val l: Throwable) : Either<Nothing>()
|
||||
private data class Right<R>(val r: R) : Either<R>()
|
||||
|
||||
fun <R, T : () -> R> _isNotThrowing(assertionContainer: Expect<T>): ChangedSubjectPostStep<*, R> {
|
||||
return ExpectImpl.changeSubject(assertionContainer)
|
||||
.unreported {
|
||||
catchAndAdjustThrowable(it)
|
||||
}
|
||||
.let { eitherContainer ->
|
||||
ExpectImpl.changeSubject(eitherContainer).reportBuilder()
|
||||
.withDescriptionAndRepresentation(IS_NOT_THROWING_1, RawString.create(IS_NOT_THROWING_2))
|
||||
.withTransformation {
|
||||
if (it is Right) Some(it.r) else None
|
||||
}
|
||||
//TODO could be extracted into an own pattern/function FailureHandlerAdapter
|
||||
.withFailureHandler(object : SubjectChanger.FailureHandler<Either<R>, R> {
|
||||
override fun createAssertion(
|
||||
originalAssertionContainer: Expect<Either<R>>,
|
||||
descriptiveAssertion: Assertion,
|
||||
maybeAssertionCreator: Option<Expect<R>.() -> Unit>
|
||||
): Assertion {
|
||||
return ExpectImpl.changeSubject(originalAssertionContainer).unreported { (it as Left).l }
|
||||
.let {
|
||||
val handler = ThrowableThrownFailureHandler<Throwable, R>(maxStackTrace = 15)
|
||||
handler.createAssertion(it, descriptiveAssertion, maybeAssertionCreator)
|
||||
}
|
||||
}
|
||||
})
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package ch.tutteli.atrium.domain.robstoll.creating
|
||||
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.domain.creating.Fun0Assertions
|
||||
import ch.tutteli.atrium.domain.robstoll.lib.creating._isThrowing
|
||||
import ch.tutteli.atrium.domain.robstoll.lib.creating._isNotThrowing
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
||||
class Fun0AssertionsImpl : Fun0Assertions {
|
||||
|
||||
override fun <TExpected : Throwable> isThrowing(
|
||||
assertionContainer: Expect<out () -> Any?>,
|
||||
expectedType: KClass<TExpected>
|
||||
) = _isThrowing(assertionContainer, expectedType)
|
||||
|
||||
override fun <R, T : () -> R> isNotThrowing(assertionContainer: Expect<T>) = _isNotThrowing(assertionContainer)
|
||||
}
|
||||
@@ -14,6 +14,7 @@ private val register = run {
|
||||
registerService<ch.tutteli.atrium.domain.creating.ComparableAssertions> { ch.tutteli.atrium.domain.robstoll.creating.ComparableAssertionsImpl() }
|
||||
registerService<ch.tutteli.atrium.domain.creating.FeatureAssertions> { ch.tutteli.atrium.domain.robstoll.creating.FeatureAssertionsImpl() }
|
||||
registerService<ch.tutteli.atrium.domain.creating.FloatingPointAssertions> { ch.tutteli.atrium.domain.robstoll.creating.FloatingPointAssertionsImpl() }
|
||||
registerService<ch.tutteli.atrium.domain.creating.Fun0Assertions> { ch.tutteli.atrium.domain.robstoll.creating.Fun0AssertionsImpl() }
|
||||
registerService<ch.tutteli.atrium.domain.creating.IterableAssertions> { ch.tutteli.atrium.domain.robstoll.creating.IterableAssertionsImpl() }
|
||||
registerService<ch.tutteli.atrium.domain.creating.ListAssertions> { ch.tutteli.atrium.domain.robstoll.creating.ListAssertionsImpl() }
|
||||
registerService<ch.tutteli.atrium.domain.creating.MapAssertions> { ch.tutteli.atrium.domain.robstoll.creating.MapAssertionsImpl() }
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ch.tutteli.atrium.domain.robstoll.creating.Fun0AssertionsImpl
|
||||
@@ -54,6 +54,9 @@ module ch.tutteli.atrium.domain.robstoll {
|
||||
provides ch.tutteli.atrium.domain.creating.FeatureAssertions
|
||||
with ch.tutteli.atrium.domain.robstoll.creating.FeatureAssertionsImpl;
|
||||
|
||||
provides ch.tutteli.atrium.domain.creating.Fun0Assertions
|
||||
with ch.tutteli.atrium.domain.robstoll.creating.Fun0AssertionsImpl;
|
||||
|
||||
provides ch.tutteli.atrium.domain.creating.feature.extract.creators.FeatureExtractorCreatorFactory
|
||||
with ch.tutteli.atrium.domain.robstoll.creating.feature.extract.creators.FeatureExtractorCreatorFactoryImpl;
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ abstract class ReportingAssertionContainerSpec(
|
||||
|
||||
context("in case of assertion which fails") {
|
||||
context("throws an AssertionError") {
|
||||
fun expectFun(): ThrowableThrown.Builder {
|
||||
fun expectFun(): Expect<() -> Any?> {
|
||||
val testee = createTestee()
|
||||
return expect {
|
||||
testee.failingFun()
|
||||
|
||||
@@ -4,6 +4,7 @@ package ch.tutteli.atrium.specs.integration
|
||||
|
||||
import ch.tutteli.atrium.api.fluent.en_GB.*
|
||||
import ch.tutteli.atrium.api.verbs.internal.expect
|
||||
import ch.tutteli.atrium.api.verbs.internal.expectOld
|
||||
import ch.tutteli.atrium.core.polyfills.fullName
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.domain.creating.throwable.thrown.ThrowableThrown
|
||||
@@ -60,7 +61,7 @@ abstract class ThrowableAssertionsSpec(
|
||||
pattern: String, vararg otherPatterns: String
|
||||
) {
|
||||
expect {
|
||||
expect { ({ throw throwable })() }.toThrowFun()
|
||||
expectOld { ({ throw throwable })() }.toThrowFun()
|
||||
}.toThrow<AssertionError> {
|
||||
message { containsRegex(pattern, *otherPatterns) }
|
||||
}
|
||||
@@ -82,7 +83,7 @@ abstract class ThrowableAssertionsSpec(
|
||||
describeFun(toThrow) {
|
||||
checkToThrow("it throws an AssertionError when no exception occurs", { doToThrow ->
|
||||
expect {
|
||||
expect { ({ /* no exception occurs */ })() }.doToThrow()
|
||||
expectOld { ({ /* no exception occurs */ })() }.doToThrow()
|
||||
}.toThrow<AssertionError> {
|
||||
message {
|
||||
contains.exactly(1).regex(
|
||||
@@ -97,7 +98,7 @@ abstract class ThrowableAssertionsSpec(
|
||||
checkToThrow(
|
||||
"it allows to define assertions for the Throwable if the correct exception is thrown",
|
||||
{ toThrowWithCheck ->
|
||||
expect {
|
||||
expectOld {
|
||||
throw IllegalArgumentException("hello")
|
||||
}.toThrowWithCheck()
|
||||
},
|
||||
@@ -146,7 +147,7 @@ abstract class ThrowableAssertionsSpec(
|
||||
|
||||
it("throws if no assertion is made") {
|
||||
expect {
|
||||
expect {
|
||||
expectOld {
|
||||
throw IllegalArgumentException("hello")
|
||||
}.toThrowFunLazy { }
|
||||
}.toThrow<AssertionError> {
|
||||
@@ -163,7 +164,7 @@ abstract class ThrowableAssertionsSpec(
|
||||
val notToThrowFun = notToThrow.lambda
|
||||
context("no exception occurs") {
|
||||
it("does not throw") {
|
||||
expect {}.notToThrowFun()
|
||||
expectOld {}.notToThrowFun()
|
||||
}
|
||||
}
|
||||
context("exception is thrown") {
|
||||
|
||||
@@ -8,7 +8,6 @@ import ch.tutteli.atrium.domain.builders.AssertImpl
|
||||
import ch.tutteli.atrium.domain.builders.ExpectImpl
|
||||
import ch.tutteli.atrium.domain.builders.reporting.ExpectOptions
|
||||
import ch.tutteli.atrium.domain.builders.reporting.ReporterBuilder
|
||||
import ch.tutteli.atrium.domain.creating.throwable.thrown.ThrowableThrown
|
||||
import ch.tutteli.atrium.reporting.RawString
|
||||
import ch.tutteli.atrium.reporting.Reporter
|
||||
import ch.tutteli.atrium.reporting.translating.Untranslatable
|
||||
@@ -25,7 +24,7 @@ abstract class VerbSpec(
|
||||
forNonNullable: Pair<String, (subject: Int, representation: String?, ExpectOptions) -> Expect<Int>>,
|
||||
forNonNullableCreator: Pair<String, (subject: Int, representation: String?, ExpectOptions, assertionCreator: Expect<Int>.() -> Unit) -> Expect<Int>>,
|
||||
forNullable: Pair<String, (subject: Int?, representation: String?, ExpectOptions) -> Expect<Int?>>,
|
||||
forThrowable: Pair<String, (act: () -> Unit) -> ThrowableThrown.Builder>,
|
||||
forThrowable: Pair<String, (act: () -> Any?, ExpectOptions, representation: String?) -> Expect<() -> Any?>>,
|
||||
describePrefix: String = "[Atrium] "
|
||||
) : Spek({
|
||||
|
||||
@@ -178,8 +177,11 @@ abstract class VerbSpec(
|
||||
}
|
||||
|
||||
prefixedDescribe("assertion verb '${forThrowable.first}' which deals with exceptions") {
|
||||
val (_, assertionVerbFun) = forThrowable
|
||||
fun assertionVerb(options: ExpectOptions = ExpectOptions(), representation: String? = null, act: () -> Any?) =
|
||||
assertionVerbFun(act, options, representation)
|
||||
|
||||
context("an IllegalArgumentException occurs") {
|
||||
val (_, assertionVerb) = forThrowable
|
||||
it("does not throw an exception expecting an IllegalArgumentException") {
|
||||
assertionVerb {
|
||||
throw IllegalArgumentException("hello")
|
||||
@@ -201,6 +203,8 @@ abstract class VerbSpec(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// customisations are not checked as it is assumed that this verb delegates to the verb forNonNullable
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
@@ -7,6 +7,7 @@ import ch.tutteli.atrium.api.fluent.en_GB.message
|
||||
import ch.tutteli.atrium.api.fluent.en_GB.toBe
|
||||
import ch.tutteli.atrium.api.fluent.en_GB.toThrow
|
||||
import ch.tutteli.atrium.api.verbs.internal.expect
|
||||
import ch.tutteli.atrium.api.verbs.internal.expectOld
|
||||
import ch.tutteli.atrium.core.polyfills.fullName
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.domain.creating.throwable.thrown.ThrowableThrown
|
||||
@@ -50,7 +51,7 @@ abstract class ThrowableAssertionsJvmSpec(
|
||||
pattern: String, vararg otherPatterns: String
|
||||
) {
|
||||
expect {
|
||||
expect { ({ throw throwable })() }.toThrowFun()
|
||||
expectOld { ({ throw throwable })() }.toThrowFun()
|
||||
}.toThrow<AssertionError> {
|
||||
message {
|
||||
containsRegex(pattern, *otherPatterns)
|
||||
|
||||
@@ -18,25 +18,35 @@ import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable
|
||||
/**
|
||||
* Creates an [Expect] for the given [subject].
|
||||
*
|
||||
* @param subject The subject for which we are going to postulate assertions.
|
||||
* @param representation Optional, use it in case you want to use a custom representation for the subject.
|
||||
* @param options Optional, use it in case you want to tweak the resulting [Expect], for instance, use another reporter.
|
||||
*
|
||||
* @return The newly created assertion container.
|
||||
* @throws AssertionError in case an assertion does not hold.
|
||||
*/
|
||||
fun <T> expect(subject: T, representation: String? = null, options: ExpectOptions = ExpectOptions()): Expect<T> =
|
||||
fun <T> expect(subject: T, representation: String? = null, options: ExpectOptions? = null): Expect<T> =
|
||||
ExpectBuilder.forSubject(subject)
|
||||
.withVerb(EXPECT)
|
||||
.withOptions(options.merge(ExpectOptions(representation = representation?.let { RawString.create(it) })))
|
||||
.withMaybeRepresentationAndMaybeOptions(representation, options)
|
||||
.build()
|
||||
|
||||
/**
|
||||
* Creates an [Expect] for the given [subject] and [Expect.addAssertionsCreatedBy] the
|
||||
* given [assertionCreator] lambda where the created [Assertion]s are added as a group and usually (depending on
|
||||
* the configured [Reporter]) reported as a whole.
|
||||
* given [assertionCreator]-lambda where the created [Assertion]s are added as a group and reported as a whole.
|
||||
*
|
||||
* @param subject The subject for which we are going to postulate assertions.
|
||||
* @param representation Optional, use it in case you want to use a custom representation for the subject.
|
||||
* @param options Optional, use it in case you want to tweak the resulting [Expect], for instance, use another reporter.
|
||||
* @param assertionCreator Assertion group block with a non-fail fast behaviour.
|
||||
*
|
||||
* @return The newly created assertion container.
|
||||
* @throws AssertionError in case an assertion does not hold.
|
||||
*/
|
||||
fun <T> expect(
|
||||
subject: T,
|
||||
representation: String? = null,
|
||||
options: ExpectOptions = ExpectOptions(),
|
||||
options: ExpectOptions? = null,
|
||||
assertionCreator: Expect<T>.() -> Unit
|
||||
): Expect<T> = expect(subject, representation, options).addAssertionsCreatedBy(assertionCreator)
|
||||
|
||||
@@ -46,7 +56,40 @@ fun <T> expect(
|
||||
*
|
||||
* @return The newly created [ThrowableThrown.Builder].
|
||||
*/
|
||||
fun expect(act: () -> Unit): ThrowableThrown.Builder = ExpectImpl.throwable.thrownBuilder(EXPECT_THROWN, act, reporter)
|
||||
fun expectOld(act: () -> Unit): ThrowableThrown.Builder =
|
||||
ExpectImpl.throwable.thrownBuilder(EXPECT_THROWN, act, reporter)
|
||||
|
||||
/**
|
||||
* Creates an [Expect] with the given [act]-lambda as subject.
|
||||
*
|
||||
* @param act the subject for which we are going to postulate assertions.
|
||||
* @param options Optional, use it in case you want to tweak the resulting [Expect], for instance, use another reporter.
|
||||
* @param representation Optional, use it in case you want to use a custom representation for the subject.
|
||||
*
|
||||
* @return The newly created assertion container.
|
||||
* @throws AssertionError in case an assertion does not hold.
|
||||
*/
|
||||
fun <R> expect(
|
||||
options: ExpectOptions? = null,
|
||||
representation: String? = null,
|
||||
act: () -> R
|
||||
): Expect<() -> R> = expect(act, representation, options)
|
||||
|
||||
/**
|
||||
* Optimised version which only creates ExpectOptions if really required.
|
||||
*/
|
||||
fun <T> ExpectBuilder.OptionsStep<T>.withMaybeRepresentationAndMaybeOptions(
|
||||
representation: String?, options: ExpectOptions?
|
||||
): ExpectBuilder.FinalStep<T> =
|
||||
if (representation == null) {
|
||||
if (options == null) this.withoutOptions()
|
||||
else this.withOptions(options)
|
||||
} else {
|
||||
val representationOption = ExpectOptions(representation = RawString.create(representation))
|
||||
if (options == null) this.withOptions(representationOption)
|
||||
else this.withOptions(options.merge(representationOption))
|
||||
}
|
||||
|
||||
|
||||
enum class AssertionVerb(override val value: String) : StringBasedTranslatable {
|
||||
EXPECT("expect"),
|
||||
|
||||
@@ -8,5 +8,5 @@ object ExpectSpec : VerbSpec(
|
||||
expect(subject, representation, options, assertionCreator)
|
||||
},
|
||||
"expect" to { subject: Int?, representation, options -> expect(subject, representation, options) },
|
||||
"expect" to { act -> expect { act() } }
|
||||
"expect" to { act: () -> Any?, options, representation -> expect(options, representation, { act() }) }
|
||||
)
|
||||
|
||||
@@ -8,9 +8,6 @@ import ch.tutteli.atrium.reporting.translating.Translatable
|
||||
*/
|
||||
enum class AssertionVerb(override val value: String) : StringBasedTranslatable {
|
||||
ASSERT("assert"),
|
||||
ASSERT_THROWN("assert the thrown exception"),
|
||||
ASSERT_THAT("assert that"),
|
||||
ASSERT_THAT_THROWN("assert that the thrown exception"),
|
||||
EXPECT("expect"),
|
||||
EXPECT_THROWN("expect the thrown exception"),
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package ch.tutteli.atrium.api.verbs
|
||||
|
||||
import ch.tutteli.atrium.api.verbs.AssertionVerb.ASSERT
|
||||
import ch.tutteli.atrium.api.verbs.AssertionVerb.ASSERT_THROWN
|
||||
import ch.tutteli.atrium.assertions.Assertion
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.domain.builders.ExpectImpl
|
||||
import ch.tutteli.atrium.domain.builders.reporting.ExpectBuilder
|
||||
import ch.tutteli.atrium.domain.builders.reporting.ExpectOptions
|
||||
import ch.tutteli.atrium.domain.creating.throwable.thrown.ThrowableThrown
|
||||
import ch.tutteli.atrium.reporting.reporter
|
||||
|
||||
/**
|
||||
* Creates an [Expect] for the given [subject].
|
||||
@@ -16,8 +13,9 @@ import ch.tutteli.atrium.reporting.reporter
|
||||
* @param subject The subject for which we are going to postulate assertions.
|
||||
* @param representation Optional, use it in case you want to use a custom representation for the subject.
|
||||
* @param options Optional, use it in case you want to tweak the resulting [Expect], for instance, use another reporter.
|
||||
*
|
||||
* @return The newly created assertion container.
|
||||
* @throws AssertionError in case an assertion does not hold
|
||||
* @throws AssertionError in case an assertion does not hold.
|
||||
*/
|
||||
fun <T> assert(subject: T, representation: String? = null, options: ExpectOptions? = null): Expect<T> =
|
||||
ExpectBuilder.forSubject(subject)
|
||||
@@ -32,9 +30,10 @@ fun <T> assert(subject: T, representation: String? = null, options: ExpectOption
|
||||
* @param subject The subject for which we are going to postulate assertions.
|
||||
* @param representation Optional, use it in case you want to use a custom representation for the subject.
|
||||
* @param options Optional, use it in case you want to tweak the resulting [Expect], for instance, use another reporter.
|
||||
*
|
||||
* @param assertionCreator Assertion group block with a non-fail fast behaviour.
|
||||
* @return The newly created assertion container.
|
||||
* @throws AssertionError in case an assertion does not hold
|
||||
* @throws AssertionError in case an assertion does not hold.
|
||||
*/
|
||||
fun <T> assert(
|
||||
subject: T,
|
||||
@@ -44,12 +43,20 @@ fun <T> assert(
|
||||
): Expect<T> = assert(subject, representation, options).addAssertionsCreatedBy(assertionCreator)
|
||||
|
||||
/**
|
||||
* Creates a [ThrowableThrown.Builder] for the given function [act] which catches a potentially thrown [Throwable]
|
||||
* and allows to define an assertion for it.
|
||||
* Creates an [Expect] with the given [act]-lambda as subject.
|
||||
*
|
||||
* @return The newly created [ThrowableThrown.Builder].
|
||||
* @param act the subject for which we are going to postulate assertions.
|
||||
* @param options Optional, use it in case you want to tweak the resulting [Expect], for instance, use another reporter.
|
||||
*
|
||||
* @param representation Optional, use it in case you want to use a custom representation for the subject.
|
||||
* @return The newly created assertion container.
|
||||
* @throws AssertionError in case an assertion does not hold.
|
||||
*/
|
||||
fun assert(act: () -> Unit): ThrowableThrown.Builder = ExpectImpl.throwable.thrownBuilder(ASSERT_THROWN, act, reporter)
|
||||
fun <R> assert(
|
||||
options: ExpectOptions? = null,
|
||||
representation: String? = null,
|
||||
act: () -> R
|
||||
): Expect<() -> R> = assert(act, representation, options)
|
||||
|
||||
@Deprecated(
|
||||
"`assert` should not be nested, use `feature` instead.",
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package ch.tutteli.atrium.api.verbs
|
||||
|
||||
import ch.tutteli.atrium.api.verbs.AssertionVerb.ASSERT_THAT
|
||||
import ch.tutteli.atrium.api.verbs.AssertionVerb.ASSERT_THAT_THROWN
|
||||
import ch.tutteli.atrium.assertions.Assertion
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.domain.builders.ExpectImpl
|
||||
import ch.tutteli.atrium.domain.builders.reporting.ExpectBuilder
|
||||
import ch.tutteli.atrium.domain.builders.reporting.ExpectOptions
|
||||
import ch.tutteli.atrium.domain.creating.throwable.thrown.ThrowableThrown
|
||||
import ch.tutteli.atrium.reporting.reporter
|
||||
|
||||
/**
|
||||
* Creates an [Expect] for the given [subject].
|
||||
@@ -16,8 +13,9 @@ import ch.tutteli.atrium.reporting.reporter
|
||||
* @param subject The subject for which we are going to postulate assertions.
|
||||
* @param representation Optional, use it in case you want to use a custom representation for the subject.
|
||||
* @param options Optional, use it in case you want to tweak the resulting [Expect], for instance, use another reporter.
|
||||
*
|
||||
* @return The newly created assertion container.
|
||||
* @throws AssertionError in case an assertion does not hold
|
||||
* @throws AssertionError in case an assertion does not hold.
|
||||
*/
|
||||
fun <T> assertThat(subject: T, representation: String? = null, options: ExpectOptions? = null): Expect<T> =
|
||||
ExpectBuilder.forSubject(subject)
|
||||
@@ -32,9 +30,10 @@ fun <T> assertThat(subject: T, representation: String? = null, options: ExpectOp
|
||||
* @param subject The subject for which we are going to postulate assertions.
|
||||
* @param representation Optional, use it in case you want to use a custom representation for the subject.
|
||||
* @param options Optional, use it in case you want to tweak the resulting [Expect], for instance, use another reporter.
|
||||
*
|
||||
* @param assertionCreator Assertion group block with a non-fail fast behaviour.
|
||||
* @return The newly created assertion container.
|
||||
* @throws AssertionError in case an assertion does not hold
|
||||
* @throws AssertionError in case an assertion does not hold.
|
||||
*/
|
||||
fun <T> assertThat(
|
||||
subject: T,
|
||||
@@ -44,13 +43,20 @@ fun <T> assertThat(
|
||||
): Expect<T> = assertThat(subject, representation, options).addAssertionsCreatedBy(assertionCreator)
|
||||
|
||||
/**
|
||||
* Creates a [ThrowableThrown.Builder] for the given function [act] which catches a potentially thrown [Throwable]
|
||||
* and allows to define an assertion for it.
|
||||
* Creates an [Expect] with the given [act]-lambda as subject.
|
||||
*
|
||||
* @return The newly created [ThrowableThrown.Builder].
|
||||
* @param act the subject for which we are going to postulate assertions.
|
||||
* @param options Optional, use it in case you want to tweak the resulting [Expect], for instance, use another reporter.
|
||||
*
|
||||
* @param representation Optional, use it in case you want to use a custom representation for the subject.
|
||||
* @return The newly created assertion container.
|
||||
* @throws AssertionError in case an assertion does not hold.
|
||||
*/
|
||||
fun assertThat(act: () -> Unit): ThrowableThrown.Builder =
|
||||
ExpectImpl.throwable.thrownBuilder(ASSERT_THAT_THROWN, act, reporter)
|
||||
fun <R> assertThat(
|
||||
options: ExpectOptions? = null,
|
||||
representation: String? = null,
|
||||
act: () -> R
|
||||
): Expect<() -> R> = assertThat(act, representation, options)
|
||||
|
||||
@Deprecated(
|
||||
"`assertThat` should not be nested, use `feature` instead.",
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package ch.tutteli.atrium.api.verbs
|
||||
|
||||
import ch.tutteli.atrium.api.verbs.AssertionVerb.EXPECT
|
||||
import ch.tutteli.atrium.api.verbs.AssertionVerb.EXPECT_THROWN
|
||||
import ch.tutteli.atrium.assertions.Assertion
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.domain.builders.ExpectImpl
|
||||
import ch.tutteli.atrium.domain.builders.reporting.ExpectBuilder
|
||||
import ch.tutteli.atrium.domain.builders.reporting.ExpectOptions
|
||||
import ch.tutteli.atrium.domain.creating.throwable.thrown.ThrowableThrown
|
||||
import ch.tutteli.atrium.reporting.reporter
|
||||
|
||||
/**
|
||||
* Creates an [Expect] for the given [subject].
|
||||
@@ -16,8 +13,9 @@ import ch.tutteli.atrium.reporting.reporter
|
||||
* @param subject The subject for which we are going to postulate assertions.
|
||||
* @param representation Optional, use it in case you want to use a custom representation for the subject.
|
||||
* @param options Optional, use it in case you want to tweak the resulting [Expect], for instance, use another reporter.
|
||||
*
|
||||
* @return The newly created assertion container.
|
||||
* @throws AssertionError in case an assertion does not hold
|
||||
* @throws AssertionError in case an assertion does not hold.
|
||||
*/
|
||||
fun <T> expect(subject: T, representation: String? = null, options: ExpectOptions? = null): Expect<T> =
|
||||
ExpectBuilder.forSubject(subject)
|
||||
@@ -32,9 +30,10 @@ fun <T> expect(subject: T, representation: String? = null, options: ExpectOption
|
||||
* @param subject The subject for which we are going to postulate assertions.
|
||||
* @param representation Optional, use it in case you want to use a custom representation for the subject.
|
||||
* @param options Optional, use it in case you want to tweak the resulting [Expect], for instance, use another reporter.
|
||||
*
|
||||
* @param assertionCreator Assertion group block with a non-fail fast behaviour.
|
||||
* @return The newly created assertion container.
|
||||
* @throws AssertionError in case an assertion does not hold
|
||||
* @throws AssertionError in case an assertion does not hold.
|
||||
*/
|
||||
fun <T> expect(
|
||||
subject: T,
|
||||
@@ -44,22 +43,21 @@ fun <T> expect(
|
||||
): Expect<T> = expect(subject, representation, options).addAssertionsCreatedBy(assertionCreator)
|
||||
|
||||
/**
|
||||
* Creates a [ThrowableThrown.Builder] for the given function [act] which catches a potentially thrown [Throwable]
|
||||
* and allows to define an assertion for it.
|
||||
* Creates an [Expect] with the given [act]-lambda as subject.
|
||||
*
|
||||
* @return The newly created [ThrowableThrown.Builder].
|
||||
* @param act the subject for which we are going to postulate assertions.
|
||||
* @param options Optional, use it in case you want to tweak the resulting [Expect], for instance, use another reporter.
|
||||
* @param representation Optional, use it in case you want to use a custom representation for the subject.
|
||||
*
|
||||
* @return The newly created assertion container.
|
||||
* @throws AssertionError in case an assertion does not hold.
|
||||
*/
|
||||
fun expect(act: () -> Unit): ThrowableThrown.Builder = ExpectImpl.throwable.thrownBuilder(EXPECT_THROWN, act, reporter)
|
||||
|
||||
// TODO #97 now we are almost there to implement expect{}.toThrow in terms of expect
|
||||
//fun <R> expect(
|
||||
// representation: String? = null,
|
||||
// options: ExpectOptions? = null,
|
||||
// act: () -> R
|
||||
//): Expect<() -> R> = expect(act, representation, ExpectOptions {
|
||||
// withVerb(EXPECT_THROWN)
|
||||
// withNullRepresentation(RawString.create("no exception occurred"))
|
||||
//}.merge(options))
|
||||
//note the order of the parameters (options before representation) is this way to disambiguate calls
|
||||
fun <R> expect(
|
||||
options: ExpectOptions? = null,
|
||||
representation: String? = null,
|
||||
act: () -> R
|
||||
): Expect<() -> R> = expect(act, representation, options)
|
||||
|
||||
@Deprecated(
|
||||
"`expect` should not be nested, use `feature` instead.",
|
||||
|
||||
@@ -8,7 +8,8 @@ object AssertSpec : VerbSpec(
|
||||
assert(subject, representation, options, assertionCreator)
|
||||
},
|
||||
"assert" to { subject: Int?, representation, options -> assert(subject, representation, options) },
|
||||
"assert" to { act -> assert { act() } })
|
||||
"assert" to { act: () -> Any?, options, representation -> assert(options, representation, { act() }) }
|
||||
)
|
||||
|
||||
object AssertThatSpec : VerbSpec(
|
||||
"assertThat" to { subject: Int, representation, options -> assertThat(subject, representation, options) },
|
||||
@@ -16,7 +17,8 @@ object AssertThatSpec : VerbSpec(
|
||||
assertThat(subject, representation, options, assertionCreator)
|
||||
},
|
||||
"assertThat" to { subject: Int?, representation, options -> assertThat(subject, representation, options) },
|
||||
"assertThat" to { act -> assertThat { act() } })
|
||||
"assertThat" to { act: () -> Any?, options, representation -> assertThat(options, representation, { act() }) }
|
||||
)
|
||||
|
||||
object ExpectSpec : VerbSpec(
|
||||
"expect" to { subject: Int, representation, options -> expect(subject, representation, options) },
|
||||
@@ -24,5 +26,5 @@ object ExpectSpec : VerbSpec(
|
||||
expect(subject, representation, options, assertionCreator)
|
||||
},
|
||||
"expect" to { subject: Int?, representation, options -> expect(subject, representation, options) },
|
||||
"expect" to { act -> expect { act() } })
|
||||
|
||||
"expect" to { act: () -> Any?, options, representation -> expect(options, representation, { act() }) }
|
||||
)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package ch.tutteli.atrium.translations
|
||||
|
||||
import ch.tutteli.atrium.assertions.DescriptiveAssertion
|
||||
import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable
|
||||
|
||||
/**
|
||||
* Contains the [DescriptiveAssertion.description]s of the assertion functions which are applicable to [Any].
|
||||
*/
|
||||
enum class DescriptionFunLikeAssertion(override val value: String) : StringBasedTranslatable {
|
||||
IS_NOT_THROWING_1("wirft"),
|
||||
IS_NOT_THROWING_2("keine Exception bei Aufruf"),
|
||||
THROWN_EXCEPTION_WHEN_CALLED("geworfene Exception bei Aufruf"),
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package ch.tutteli.atrium.translations
|
||||
|
||||
import ch.tutteli.atrium.assertions.DescriptiveAssertion
|
||||
import ch.tutteli.atrium.reporting.translating.StringBasedTranslatable
|
||||
|
||||
/**
|
||||
* Contains the [DescriptiveAssertion.description]s of the assertion functions which are applicable to [Any].
|
||||
*/
|
||||
enum class DescriptionFunLikeAssertion(override val value: String) : StringBasedTranslatable {
|
||||
IS_NOT_THROWING_1("does not"),
|
||||
IS_NOT_THROWING_2("throw when called"),
|
||||
THROWN_EXCEPTION_WHEN_CALLED("thrown exception when called"),
|
||||
}
|
||||
Reference in New Issue
Block a user