为Kotlin项目选择一个断言库

在一个旧项目中,JUnit的断言,kotlin.test和AssertJ被堆积了。这不是他唯一的问题:它通常是费奥多尔叔叔写的一封信,没有时间停下来把它变成一个单一的形式。现在这个时候到了。



本文将包含一项小型研究,根据主观标准,哪些主张更好。最初,我想做一些简单的事情:进行一组测试,以便快速复制和粘贴铆钉选项。然后他重点介绍了常规测试数据,自动进行了一些检查,以及一切进行得如何...结果是一块小的Rosetta石头,对于选择适合您实际情况的断言库,本文可能对您有用。



我将立即保留一点,即本文不会比较测试框架,测试方法和一些棘手的数据验证方法。我们将讨论简单的断言。





如果您懒得阅读无聊的推理,我的磨难历史和其他细节,那么您可以直接进入比较结果



有点背景



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