Escolhendo uma biblioteca de asserçÔes para um projeto Kotlin

Em um dos projetos antigos, as declaraçÔes de JUnit, kotlin.test e AssertJ foram empilhadas. Esse nĂŁo era seu Ășnico problema: geralmente era escrito como uma carta do tio Fyodor, e nĂŁo havia tempo para parar e trazĂȘ-la para uma Ășnica forma. E agora chegou a hora.



O artigo conterĂĄ uma minipesquisa sobre quais afirmaçÔes sĂŁo melhores de acordo com critĂ©rios subjetivos. No começo, eu queria fazer algo simples: realizar um conjunto de testes para rebitar rapidamente as opçÔes com copiar e colar. Em seguida, ele destacou os dados gerais do teste, automatizou algumas das verificaçÔes e como tudo correu ... O resultado foi uma pequena pedra de Rosetta, e este artigo pode ser Ăștil para vocĂȘ escolher uma biblioteca de afirmaçÔes que se adapte Ă s suas realidades.



Farei uma reserva imediata de que o artigo não compararå estruturas de teste, abordagens de teste e algumas abordagens complicadas para validação de dados. Vamos falar sobre afirmaçÔes simples.





Se vocĂȘ estĂĄ com preguiça de ler o raciocĂ­nio chato, a histĂłria de minhas provaçÔes e outros detalhes, pode ir diretamente aos resultados da comparação .



Um pouco de fundo



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
  • Para conectar apenas declaraçÔes, vocĂȘ precisa ir mais fundo. Na minha opiniĂŁo, Ă© difĂ­cil entender isso imediatamente.
  • Ele nĂŁo tem a opção de capturar uma exceção com um parĂąmetro explĂ­cito, e nĂŁo reificado, mas isso na verdade nĂŁo Ă© realmente necessĂĄrio: muito poucas pessoas lidam com essas perversĂ”es.
  • Estruturas complexas: teste com matrizes aninhadas falhou. Abri um ingresso para isso .
  • : <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