Skip to content

Instantly share code, notes, and snippets.

@keyboardr
Last active March 10, 2021 23:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save keyboardr/68028799a90f8fa8b93ac564d31911c7 to your computer and use it in GitHub Desktop.
Save keyboardr/68028799a90f8fa8b93ac564d31911c7 to your computer and use it in GitHub Desktop.
package com.keyboardr.testing
import com.google.common.truth.*
import com.google.common.truth.Truth.assertWithMessage
import com.google.common.truth.Truth.assert_
import java.math.BigDecimal
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
open class AssertionBuilder<T : AssertionScope>
internal constructor(val scope: T) {
inline infix fun that(block: T.() -> Unit) {
scope.block()
}
infix fun that(actual: BigDecimal?): BigDecimalSubject = scope.startAssert().that(actual)
infix fun that(actual: Any?): Subject = scope.startAssert().that(actual)
infix fun that(actual: Class<*>?): ClassSubject = scope.startAssert().that(actual)
infix fun that(actual: Throwable?): ThrowableSubject = scope.startAssert().that(actual)
infix fun that(actual: Long?): LongSubject = scope.startAssert().that(actual)
infix fun that(actual: Double?): DoubleSubject = scope.startAssert().that(actual)
infix fun that(actual: Float?): FloatSubject = scope.startAssert().that(actual)
infix fun that(actual: Int?): IntegerSubject = scope.startAssert().that(actual)
infix fun that(actual: Boolean?): BooleanSubject = scope.startAssert().that(actual)
infix fun that(actual: String?): StringSubject = scope.startAssert().that(actual)
infix fun that(actual: Iterable<*>?): IterableSubject = scope.startAssert().that(actual)
infix fun <T> that(actual: Array<T>?): ObjectArraySubject<T> = scope.startAssert().that(actual)
infix fun that(actual: Map<*, *>?): MapSubject = scope.startAssert().that(actual)
}
object Assert : AssertionBuilder<AssertionScope>(Assertions) {
fun withMessage(message: String) = AssertionBuilder(MessageAssertionScope(message))
fun <T : AssertionScope> withExtension(extension: T) = AssertionBuilder(extension)
}
@OptIn(ExperimentalContracts::class)
inline fun assertThat(block: AssertionScope.() -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
Assert that block
}
@OptIn(ExperimentalContracts::class)
inline fun assertWithMessage(message: String, block: AssertionScope.() -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
Assert.withMessage(message) that block
}
@Suppress("unused", "NOTHING_TO_INLINE")
@AssertionDsl
abstract class AssertionScope {
open fun startAssert(): StandardSubjectBuilder = assert_()
inline infix fun Boolean?.shouldBe(expected: Boolean?) = when (expected) {
null -> startAssert().that(this).isNull()
true -> startAssert().that(this).isTrue()
false -> startAssert().that(this).isFalse()
}
inline infix fun Int?.shouldEqual(expected: Int) = startAssert().that(this).isEqualTo(expected)
inline infix fun Long?.shouldEqual(expected: Long) = startAssert().that(this).isEqualTo(expected)
inline infix fun Float?.shouldEqual(expected: Float) = startAssert().that(this).isEqualTo(expected)
inline infix fun Any?.shouldEqual(expected: Any?) = startAssert().that(this).isEqualTo(expected)
inline infix fun Int?.shouldNotEqual(expected: Int) = startAssert().that(this).isNotEqualTo(expected)
inline infix fun Long?.shouldNotEqual(expected: Long) = startAssert().that(this).isNotEqualTo(expected)
inline infix fun Float?.shouldNotEqual(expected: Float) = startAssert().that(this).isNotEqualTo(expected)
inline infix fun Any?.shouldNotEqual(expected: Any) = startAssert().that(this).isNotEqualTo(expected)
inline infix fun Int?.shouldBeSameAs(expected: Int) = startAssert().that(this).isSameInstanceAs(expected)
inline infix fun Long?.shouldBeSameAs(expected: Long) = startAssert().that(this).isSameInstanceAs(expected)
inline infix fun Float?.shouldBeSameAs(expected: Float) = startAssert().that(this).isSameInstanceAs(expected)
inline infix fun Any?.shouldBeSameAs(expected: Any?) = startAssert().that(this).isSameInstanceAs(expected)
inline infix fun Int?.shouldBeAtLeast(expected: Int) = startAssert().that(this).isAtLeast(expected)
inline infix fun Long?.shouldBeAtLeast(expected: Long) = startAssert().that(this).isAtLeast(expected)
inline infix fun Float?.shouldBeAtLeast(expected: Float) = startAssert().that(this).isAtLeast(expected)
// foo shouldBe null
inline infix fun Any?.shouldBe(@Suppress("UNUSED_PARAMETER") nothing: Nothing?) = startAssert().that(this).isNull()
// foo shouldBe !null
inline infix fun Any?.shouldBe(@Suppress("UNUSED_PARAMETER") nonNull: NonNull) = startAssert().that(this).isNotNull()
inline fun Iterable<*>?.shouldBeEmpty() = startAssert().that(this).isEmpty()
inline fun Iterable<*>?.shouldNotBeEmpty() = startAssert().that(this).isNotEmpty()
inline fun Iterable<*>?.shouldNotContainDuplicates() = startAssert().that(this).containsNoDuplicates()
inline infix fun Iterable<*>?.shouldHaveSize(expectedSize: Int) = startAssert().that(this).hasSize(expectedSize)
inline infix fun Iterable<*>?.shouldContain(element: Any?) = startAssert().that(this).contains(element)
inline infix fun Iterable<*>?.shouldNotContain(element: Any?) = startAssert().that(this).doesNotContain(element)
inline infix fun Iterable<*>?.shouldContainOnly(element: Any?): Ordered = startAssert().that(this).containsExactly(element)
inline fun Iterable<*>?.shouldContainExactlyElements(vararg varargs: Any): Ordered = startAssert().that(this).containsExactly(*varargs)
inline infix fun Iterable<*>?.shouldContainExactly(expected: Iterable<*>): Ordered = startAssert().that(this).containsExactlyElementsIn(expected)
inline infix fun Iterable<*>?.shouldContainExactly(expected: Array<*>): Ordered = startAssert().that(this).containsExactlyElementsIn(expected)
inline operator fun Nothing?.not() = NonNull
object NonNull
}
object Assertions : AssertionScope()
class MessageAssertionScope(private val message: String) :
AssertionScope() {
override fun startAssert(): StandardSubjectBuilder = assertWithMessage(message)
}
@DslMarker
annotation class AssertionDsl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment