Choisir une bibliothĂšque d'assertions pour un projet Kotlin

Dans l'un des anciens projets, les affirmations de JUnit, kotlin.test et AssertJ ont Ă©tĂ© empilĂ©es. Ce n'Ă©tait pas son seul problĂšme: il Ă©tait gĂ©nĂ©ralement Ă©crit comme une lettre de l'oncle Fyodor, et il n'y avait pas de temps pour s'arrĂȘter et l'amener Ă  une forme unique. Et maintenant, ce moment est venu.



L'article contiendra une mini-recherche sur les affirmations qui sont les meilleures selon des critĂšres subjectifs. Au dĂ©but, je voulais faire quelque chose de simple: lancer une sĂ©rie de tests afin de riveter rapidement les options avec le copier-coller. Puis il a mis en Ă©vidence les donnĂ©es gĂ©nĂ©rales des tests, automatisĂ© certaines vĂ©rifications, et comment tout s'est passĂ© ... Le rĂ©sultat Ă©tait une petite pierre de Rosetta, et cet article peut vous ĂȘtre utile afin de choisir une bibliothĂšque d'assertions qui correspond Ă  vos rĂ©alitĂ©s.



Je ferai une réserve tout de suite que l'article ne comparera pas les cadres de test, les approches de test et certaines approches délicates de la validation des données. Nous parlerons d'assertions simples.





Si vous ĂȘtes trop paresseux pour lire des raisonnements ennuyeux, l'historique de mes Ă©preuves et d'autres dĂ©tails, vous pouvez accĂ©der directement aux rĂ©sultats de la comparaison .



Un peu de contexte



Scala, — ScalaTest. , - , - .



Kotlin, - , , Kotest ( , ).





, , — . :



  1. Kotlin IntelliJ Idea. Scala- — . , ScalaTest , . IntelliJ <Click to see difference>, . , , IntelliJ Idea — Kotlin- - , ?

  2. . 1 != 2 , , "expected" "actual". " 100 , , ", , "
 , , , ". , ? , — , , - .
  3. . assertEquals(expected, actual) — , . , — /, " , , " , contains, includes. — , .
  4. . - assertThat("Friendship").contains("end").
  5. . - JUnit4, , ExpectedException @Rule.
  6. () .
  7. .
  8. . — , . , : , , generic-, . -: assertThat(generic<Boolean>(input)).isEqualTo(true). <Boolean> . .
  9. , . . ? — , , . - , equals. - .


, , , , , . , — , . , -, QA-.





, 5 , , — .



:



  1. ScalaTest — .
  2. JUnit 5 — Java-.
  3. kotlin.test — multiplatform . — JUnit, .
  4. AssertJ — . FestAssert, - .
  5. Kotest — KotlinTest, kotlin.test. , ScalaTest. 1-22 — scala.
  6. Truth — . , AssertJ.
  7. Hamrest ­— . valid4j.
  8. Strikt — AssertJ .
  9. Kluent — , JUnit ( — kotlin.test), Kotest. — , .
  10. Atrium — , AssertJ, . — ( maven/gradle).
  11. Expekt — Chai.js. : — 4 .
  12. AssertK — AssertJ, AssertK ( ).
  13. HamKrest — Hamrest, HamKrest ( Hamcrest ).


— , -.





80 , , , . - , .



, , 1 — 1 . , , - , " , " "".



, - , JUnit , , , , , . ScalaTest, : , , — . : ? , :). / , , .



: listOf(1,2,3)? — -, — . , , : , . , .



type erasure. Reified inline-, .



assertThrows<T>{...}


, reified :



assertThrows(expectedClass){...}


. , kotlin.test Asserter: , . , ?:)



GitHub. ScalaTest , .





: 0 — , 0.5 — , 1 — . — 9 .



-, , . . , . , - , " " , " " . .



Kotest ± ± + + + + + - 6.0
Kluent ± ± + + + + + - 6.0
AssertJ ± + ± + ± + + ± 6.0
Truth ± + + + - + + - 5.5
Strikt ± ± ± + + + + - 5.5
ScalaTest ± ± ± + + + + - 5.5
HamKrest ± - ± + + ± + - 5.5
AssertK ± ± ± + ± + + - 5.0
Atrium ± ± ± + + ± + - 5.0
Hamrest ± ± ± + - ± + - 5.0
JUnit + + - ± + - ± - 4.5
kotlin.test + ± - - + - - - 3.5
Expekt ± ± - + - ± + - 3.5


:



Kotest
  • , . .
  • , reified, : .
  • : . .
  • : <Click to see difference> .
  • : .
  • : , .


Kluent
  • "hello".shouldBeEqualTo("hello"), "hello" `should be equal to` "hello". DSL .
  • :

    invoking { block() } shouldThrow expectedClass.kotlin withMessage expectedMessage
  • , , . Expected Iterable to contain none of "[1, 3]" — , Iterable .
  • : <Click to see difference> .
  • : .


AssertJ
  • — 
 , containsExactly, — hasSameElementsAs, — .usingRecursiveComparison().isEqualTo.



  • : <Click to see difference> .



  • : - , . , , .



  • : .usingRecursiveComparison(), . : , , . , , ,



    assertThat(actual)
        .usingRecursiveComparison()
        .isNotEqualTo(unexpected)


    : .



  • : . , DSL.





Truth
  • , .
  • : , , assertThrows JUnit5. , JUnit , ?
  • : , , : containsAtLeastElementsIn. , assertThat(actual).isEqualTo(expected).
  • : <Click to see difference> .
  • : .
  • : , .
  • " ":

    expected: 1
    but was : 2
    at asserts.truth.TruthAsserts.simpleAssert(TruthAsserts.kt:10)
    at common.FailedAssertsTestBase.simple assert should have descriptive message(FailedAssertsTestBase.kt:20)
    at [[Reflective call: 4 frames collapsed (https://goo.gl/aH3UyP)]].(:0)
    at [[Testing framework: 27 frames collapsed (https://goo.gl/aH3UyP)]].(:0)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at [[Testing framework: 9 frames collapsed (https://goo.gl/aH3UyP)]].(:0)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at [[Testing framework: 9 frames collapsed (https://goo.gl/aH3UyP)]].(:0)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at [[Testing framework: 17 frames collapsed (https://goo.gl/aH3UyP)]].(:0)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
    ...


Strikt
  • , reified, : .



  • : expectThat(haystack).not().contains(needle), expectThat(collection).doesNotContain(items).



  • : contentEquals. : expectThat(actual).not().contentEquals(unexpected). , , Array<T> Strikt - . — containsExactly, — containsExactlyInAnyOrder.



  • : . , . :



    val actual: Array<String> = arrayOf("1")
    val expected: Array<String> = arrayOf("2")
    expectThat(actual).contentEquals(expected)


    , contentEquals. , contentEquals :



    infix fun <T> Assertion.Builder<Array<out T>>.contentEquals(other: Array<out T>)


    -



    val actual: Array<out String> = arrayOf("1")
    val expected: Array<String> = arrayOf("2")
    expectThat(actual).contentEquals(expected)


  • : <Click to see difference>.



  • : , .



  • : .





ScalaTest
  • : .
  • : , . .
  • : DSL contains, contains include, theSameElementsAs.
  • : , .
  • : , .


HamKrest
  • , , . — , .
  • , Hamcrest, - : -.
  • — :

    assertThat( {
        block()
    }, throws(has(RuntimeException::message, equalTo(expectedMessage))))
  • : . - 3,5 . : assertThat(collection, allOf(items.map { hasElement(it) })).
  • .
  • : .
  • : <Click to see difference>.
  • — - :

    expected: a value that not contains 1 or contains 3
    but contains 1 or contains 3


AssertK
  • — AssertJ. ( , -).



  • : AssertJ assertThat(collection).containsAll(items), AssertK , containsAll vararg. , containsAll(1,2,3), . , , — . — . , containsOnly containsExactly.



  • : <Click to see difference>.



  • : - , , .



  • : .usingRecursiveComparison() .



  • — ( ), :



    expected to contain exactly:<[3, 4, 5]> but was:<[1, 2, 3]>
    at index:0 unexpected:<1>
    at index:1 unexpected:<2>
    at index:1 expected:<4>
    at index:2 expected:<5>


    ?



  • : .





Atrium
  • : fluent infix. assertThat(x).isEqualTo(y) x shouldBe y, , expect(x).toBe(y) expect(x) toBe y. , , "". - o: expect(x) contains o atLeast 1 butAtMost 2 value "hello". , , . infix- ( - ), Atrium fluent-.
  • : : notToBe, containsNot. . , : contains vararg, containsElementsOf , . , contains(1,2,3), . expect(collection).containsNot.elementsOf(items).
  • , toList.
  • , reified, : .
  • : .
  • : <Click to see difference>.
  • : ( , ), :

    expected that subject: [4, 2, 1]        (java.util.Arrays.ArrayList <938196491>)
    ◆ does not contain:
    ⚬ an entry which is: 1        (kotlin.Int <211381230>)
      ✘  number of such entries: 1
           is: 0        (kotlin.Int <1934798916>)
        has at least one element: true
           is: true
  • : .


Hamcrest
  • : (



    assertThat(actual, `is`(not(unexpected)))




    assertThat(actual, not(unexpected))


    containsString vs contains vs hasItem vs hasItems. , : hasItems vararg, Set<T> T . , hasItems(1,2,3), .



    assertThat(collection, allOf(items.map { hasItem(it) }))


    :



    assertThat(collection, not(anyOf(items.map { hasItem(it) })))


  • hasItems, ± "", , .



  • : .



  • : <Click to see difference>.



  • : .



  • : .





JUnit
  • : - assertEquals(expected, actual), : assertArrayEquals, assertIterableEquals ..
  • : , JUnit - , .
  • : assertLinesMatch(listOf(".*$needle.*"), listOf(haystack)) , .
  • : assertLinesMatch, , assertIterableEquals.
  • : , assertIterableEquals Map Set , .
  • : .


kotlin.test
  • . JUnit, . , .
  • , JUnit, :
  • .
  • assertIterableEquals, .
  • : JUnit' assertEquals, kotlin.test , .
  • : .


Expekt
  • expect(x).equal(y) x.should.equal(y), . , .
  • : contains(item) should.have.elements(items) should.contain.elements(items). containsAll. , : should.have.elements vararg. , should.have.elements(1,2,3), . any: .should.not.contain.any.elements.
  • : , .
  • .
  • .
  • : .
  • : .
  • : <Click to see difference>.




Kotest, Kluent AssertJ. , Kotlin , AssertJ ( ). , .



— , , AssertJ. , , .




All Articles