https://kotlinlang.org logo
Join SlackCommunities
Powered by
# strikt
  • r

    Roukanken

    05/19/2022, 1:56 PM
    I wonder if there’s a way to prevent
    isA
    if the generic type of the function has its own generic type
    I don't think there is a way to prevent it compile time, but you can always just half-botch it by having the assert always fail when
    T::class.typeParameters
    is non-empty (eg, the reified class has some generic parameters on it's own)
    c
    r
    e
    • 4
    • 24
  • e

    Eric

    08/05/2022, 5:39 PM
    withCaptured
    (mockk) breaks assertion chaining if the slot has not been captured. It throws
    Mapping 'captured value %s' failed with: lateinit property captured has not been initialized
    . Not sure if this is known or intentional. Would be nice if instead of throwing it would short circuit the block and fail.
    r
    • 2
    • 7
  • e

    Eric

    09/21/2022, 5:32 PM
    comparables have `isGreaterThan`/`isGreaterThanOrEqualTo`/etc assertions but no check if equal using
    compareTo
    which is useful for things like
    BigDecimal
    maybe add this?
    Copy code
    fun <T : Comparable<T>> Assertion.Builder<T>.compareToEqual(expected: T) =
        assert("is equal using compareTo to %s", expected) {
            if (it.compareTo(expected) == 0) pass() else fail()
        }
    👍 2
  • e

    Eric

    10/28/2022, 4:13 PM
    Would be nice to have a version of
    propertiesAreEqualTo
    that doesn’t require
    other
    to be the same type as the subject. Just a couple minor tweaks.
    Copy code
    fun <T : Any> Assertion.Builder<T>.reflectionEquals(
        other: Any,
        ignoredPropertyNames: List<String> = emptyList()
    ): Assertion.Builder<T> = compose("is equal field-by-field to %s", other) { subject ->
        val otherBeanInfo = Introspector.getBeanInfo(other.javaClass)
        val beanInfo = Introspector.getBeanInfo(subject.javaClass)
        beanInfo.propertyDescriptors
            .filter { it.name != "class" && it.name !in ignoredPropertyNames }
            .forEach { property ->
                val mappedAssertion = get("value of property ${property.name}") {
                    property.readMethod(this)
                }
                val otherProperty = otherBeanInfo.propertyDescriptors.firstOrNull { it.name == property.name }
                val otherValue = otherProperty?.let { it.readMethod(other) }
    // the rest is the same as propertiesAreEqualTo
    r
    d
    • 3
    • 23
  • d

    dave08

    12/08/2022, 2:36 PM
    It says in the docs:
    Block assertions do _not_ fail fast.
    but if I use:
    Copy code
    expectThat(result) {
      get(Foo::prop1)...
      get(Foo::prop2)...
    }
    It seems to only print out the first check's result... 🤔
    r
    • 2
    • 6
  • d

    dave08

    01/02/2023, 4:34 PM
    I wonder if
    expectThat(...)
    was an
    inline fun
    with reified type param, you could technically pass that type down to the assertions and it could be a great help for things like collections... currently if I pass a
    List<Foo>
    to
    expectThat
    I can pass a
    List<Baz>
    that doesn't inherit from
    Foo
    to
    contains
    and that simply doesn't make sense... meaning refactoring to passing another type in the list could easily have the tests pass even though they shouldn't...
  • d

    dmcg

    01/06/2023, 4:35 PM
    Kotlin assertion libraries - JUnit, Hamkrest and Strikt

    https://youtu.be/lyDOPNSqYoo▾

  • r

    robfletcher

    01/06/2023, 4:36 PM
    What about https://github.com/bnorm/kotlin-power-assert
  • d

    dmcg

    01/06/2023, 6:33 PM
    I’ll have to check it out, but I have to edit out enough building time from my videos without a compiler plugin!
    c
    • 2
    • 2
  • d

    Dan Rusu

    01/08/2023, 3:12 AM
    Are all the existing tests supposed to pass? I cloned the repo and ran
    ArrayAssertions
    but am getting strange failures where it's complaining about differing strings that appear to be equal so I wonder if I'm running into some sort of character encoding issue:
    Copy code
    ▼ Expect that "▼ Expect that ['f', 'n', 'o', 'r', 'd']:
                  |  ✗ array content equals ['d', 'i', 's', 'c', 'o', 'r', 'd']":
      ✗ is equal to "▼ Expect that ['f', 'n', 'o', 'r', 'd']:
                    |  ✗ array content equals ['d', 'i', 's', 'c', 'o', 'r', 'd']"
              found "▼ Expect that ['f', 'n', 'o', 'r', 'd']:
                    |  ✗ array content equals ['d', 'i', 's', 'c', 'o', 'r', 'd']"
    The way the tests are written makes it very difficult (and frustrating) to deal with test failures because: 1. Double-clicking on a failed test in IntelliJ doesn't navigate to the failing test 2. Clicking the
    Rerun Failed Tests
    button makes it seem like they all pass because it doesn't actually rerun any tests I don't have these issues when I use Strikt for testing my own project so I wonder if this is caused by using contexts instead of a separate test method per scenario
    c
    r
    • 3
    • 32
  • d

    Dan Rusu

    01/10/2023, 10:31 PM
    Since Kotlin 1.8 no longer supports JVM target 1.6 or 1.7: https://kotlinlang.org/docs/whatsnew18.html#updated-jvm-compilation-target then I think this ticket might no longer apply: https://github.com/robfletcher/strikt/issues/41
    r
    • 2
    • 3
  • d

    Dan Rusu

    01/11/2023, 11:30 PM
    Once this PR gets merged: https://github.com/robfletcher/strikt/pull/280 Then I'd like to make another unrelated improvement to that file to speed up CI build times
    👀 1
    r
    • 2
    • 3
  • d

    Dan Rusu

    01/11/2023, 11:55 PM
    This should speed up CI builds on future submissions: https://github.com/robfletcher/strikt/pull/281
    r
    • 2
    • 11
  • d

    Dan Rusu

    01/13/2023, 11:25 PM
    I finally found the root cause of the test failures. It turns out that they are valid failures that shouldn't pass whenever the
    line.separator
    system property is anything other than
    \n
    . This is because raw / triple-quoted strings are hard-coded to always be compiled with
    \n
    line separators so they can't possibly match output that uses the
    line.separator
    system property. I didn't find any official documentation about this but found this: https://stackoverflow.com/questions/48933641/kotlin-add-carriage-return-into-multiline-string#:~:text=Kotlin%20multiline%20strings%20are%20always,separator%22))%20. and also found that the Kotlin standard library hardcoded
    \n
    in the
    reindent
    function (which is used by the
    trimIndent
    &
    trimMargin
    functions that are used throughout the tests): https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/src/kotlin/text/Indent.kt#:~:text=.joinTo(StringBuild[…]eEstimate)%2C%20%22%5Cn%22) So this brings up 2 issues: 1. The github action to run on windows doesn't seem to represent a regular windows environment. Perhaps something is overwriting the
    line.separator
    system property. 2. Either the
    EOL
    value in
    DefaultResultWriter
    should be set to
    \n
    (which makes the tests pass) or all the tests that assert against multi-line triple-quoted strings need to be fixed.
    c
    r
    • 3
    • 9
  • d

    dave08

    01/26/2023, 4:55 PM
    Is there any plans for this? I'm always doing this again and again in my test code...
  • e

    Eric

    05/31/2023, 2:11 PM
    I'm trying to create a couple strikt assertions for this `Result`: https://github.com/michaelbull/kotlin-result I'd like to replace usages like
    .isA<Ok<Foo>>().get { value }
    with
    .isSuccess<Foo>()
    but I'm having trouble w/ the generic signatures.
    Copy code
    fun <V> Assertion.Builder<Result<V, *>>.isSuccess(): Assertion.Builder<V> = isA<Ok<V>>().get { value }
    fun <E> Assertion.Builder<Result<*, E>>.isFailure(): Assertion.Builder<E> = isA<Err<E>>().get { error }
    IntelliJ is yelling at me. Any ideas on what these ext funs should look like? Thanks.
    r
    • 2
    • 36
  • e

    Eric

    06/08/2023, 1:01 PM
    propertiesAreEqualToIgnoring
    doesn't support nullable attributes as currently written this should work, though
    Copy code
    fun <T : Any> Assertion.Builder<T>.propertiesAreEqualToIgnoring(
        other: T,
        vararg ignoredProperties: KProperty1<T, Any?>,
    ): Assertion.Builder<T> = compareFieldByField(
        other,
        ignoredProperties.map(KProperty1<T, Any?>::name)
    )
    Just changed
    KProperty1<T, Any>
    ->
    KProperty1<T, Any?>
    r
    • 2
    • 3
  • d

    dave08

    06/20/2023, 12:55 PM
    Did anyone try implementing
    get()
    using Arrow Optics? It might avoid a bunch of gets to drill down a hierarchy and
    get { }
    that inspects the source code itself...
    r
    • 2
    • 4
  • p

    Pihentagy

    06/27/2023, 4:01 PM
    Hi, new to strikt, I guess there must be a more elegant way to say:
    Copy code
    expectThat(result) {
                get { statusCode }.isEqualTo(HttpStatus.OK)
                get { body }.isNotNull().and {
                    get { elements }.and {
                        hasSize(1)
                        expectThat(first().subject) {
                            get { coordinates }.isEqualTo(listOf(coord))
                            get { networkType }.isEqualTo(NetworkType.SWITCH)
                        }
                    }
                }
            }
    s
    r
    e
    • 4
    • 12
  • e

    Eric

    07/05/2023, 1:05 PM
    i find that i need
    single
    on a
    Map
    every once in a while, like there is for
    Collection
    Might be worth dropping in your std assertions
    Copy code
    fun <T : Map<K, V>, K, V> Assertion.Builder<T>.single(): Assertion.Builder<Pair<K, V>> =
        assert("has only one entry") {
            if (it.size == 1) pass(it.size) else fail(it.size)
        }.get("single entry %s") { entries.first().toPair() }
    j
    • 2
    • 6
  • k

    Klitos Kyriacou

    07/19/2023, 2:13 PM
    Does Strikt have a matcher for iterables similar to AssertK's
    containsOnly
    (or Kotest's
    shouldContainOnly
    )? Description from AssertK: "Asserts the iterable contains only the expected elements, in any order. Duplicate values in the expected and actual are ignored."
    j
    c
    • 3
    • 5
  • s

    Saharath Kleips

    07/19/2023, 5:08 PM
    Hey there - is there an option to outputting only the assertions that failed rather than the ones that have succeeded as well? Some coworkers have brought up a criticism that for some very long assertions the output is very verbose / noisey so we were thinking that this would be a good middle ground. Maybe even some sort of compacted view or if anyone else from the community has ideas on how to address this.
  • e

    Eric

    07/21/2023, 1:33 PM
    I find myself wanting
    compareToEqual
    again. https://kotlinlang.slack.com/archives/CAR7KJ96J/p1663781526609259 This time passing in a comparator:
    Copy code
    fun <T : Comparable<T>> Assertion.Builder<T>.compareToEqual(
        expected: T,
        comparator: Comparator<T> = Comparator.naturalOrder(),
    ) = assert("is equal using Comparator to %s", expected) {
        if (comparator.compare(subject, expected) == 0) pass() else fail()
    }
  • c

    christophsturm

    09/27/2023, 9:29 AM
    this looks nice: https://github.com/mcmire/super_diff maybe an inspiration for better diffing.
    r
    e
    • 3
    • 6
  • e

    Eric

    12/20/2023, 7:16 PM
    Coming back to strikt after a while... how can you do an or condition? doing some convention checks and want to check if my controller methods have the
    @PreAuthorize
    annotation or have it as a meta-annotation.
    Copy code
    that(methods).all {
                    get { annotations.toList() }.any {
                        get { annotationClass }.isEqualTo(PreAuthorize::class)
                        // or...
                        get { annotationClass.annotations }.any { get { annotationClass }.isEqualTo(PreAuthorize::class) }
                    }
                }
    • 1
    • 1
  • j

    Jakub Gwóźdź

    01/22/2024, 10:04 AM
    hi there, I’m wondering about this particular method:
    Copy code
    internal fun formatValue(value: Any?): Any =
      when (value) {
        null -> "null"
        is CharSequence -> "\"$value\""
        is Char -> "'$value'"
        is Iterable<*> -> if (value.javaClass.preferToString()) value.toString() else value.map(::formatValue)
        is Byte -> "0x${value.toString(16)}"
        is ByteArray -> "0x${value.toHex()}".truncate()
    ...
    Is there a reason why
    if (value.javaClass.preferToString()...
    is only in Iterable<*> and not on any class? Reason I’m asking is because I have things like
    expectThat(jsonObject1).isEqualTo(jsonObject2)
    (from kotlinx.serialization) and it works just fine, but whenever there is a fail, I don’t see beautiful json (like from
    jsonObject2.toString()
    ), but rather a mess with the
    =
    chars (caused by line 42).
  • e

    Eric

    02/08/2024, 3:15 PM
    Coming back to Strikt after a bit... How can I do an "or"? Writing some tests to make assertions on JPA entities and want make sure that
    val
    attributes are annotated with either
    @Column(updatable = false)
    or
    @JoinColumn(updatable = false)
    Just testing 1 right now
    Copy code
    expectThat(immutableProperties).all {
        get { getAnnotation(Column::class.java) }.isNotNull().get { updatable }.isFalse()
    }
    • 1
    • 1
  • j

    juliocbcotta

    03/05/2024, 4:53 PM
    Hey, is the lib being updated ? I found this issue in the repository https://github.com/robfletcher/strikt/issues/300
    s
    e
    +3
    • 6
    • 6
  • d

    David Hamilton

    06/23/2024, 12:51 PM
    Hi - I saw this announcement of language support for Power Assert in Kotlin 2.0, and wondered where Strikt might be able to make use of it?
    r
    • 2
    • 2
  • r

    robfletcher

    06/23/2024, 5:12 PM
    After some issues with OSSRH’s switch to token based auth, I’ve finally published v0.35.1
    🎉 3
    🙌 2
    K 4
    d
    • 2
    • 2