在一个旧项目中,JUnit的断言,kotlin.test和AssertJ被堆积了。这不是他唯一的问题:它通常是费奥多尔叔叔写的一封信,没有时间停下来把它变成一个单一的形式。现在这个时候到了。
本文将包含一项小型研究,根据主观标准,哪些主张更好。最初,我想做一些简单的事情:进行一组测试,以便快速复制和粘贴铆钉选项。然后他重点介绍了常规测试数据,自动进行了一些检查,以及一切进行得如何...结果是一块小的Rosetta石头,对于选择适合您实际情况的断言库,本文可能对您有用。
我将立即保留一点,即本文不会比较测试框架,测试方法和一些棘手的数据验证方法。我们将讨论简单的断言。

如果您懒得阅读无聊的推理,我的磨难历史和其他细节,那么您可以直接进入比较结果。
有点背景
Scala, — ScalaTest. , - , - .
Kotlin, - , , Kotest ( , ).
, , — . :
- Kotlin IntelliJ Idea. Scala- — . , ScalaTest , . IntelliJ
<Click to see difference>, . , , IntelliJ Idea — Kotlin- - , ?

- .
1 != 2, , "expected" "actual". " 100 , , ", , "… , , , ". , ? , — , , - . - .
assertEquals(expected, actual)— , . , — /, " , , " ,contains,includes. — , . - . -
assertThat("Friendship").contains("end"). - . - JUnit4, ,
ExpectedException@Rule. - () .
- .
- . — , . , : , , generic-, . -:
assertThat(generic<Boolean>(input)).isEqualTo(true).<Boolean>. . - , . . ? — , , . - , equals. - .
, , , , , . , — , . , -, QA-.
, 5 , , — .
:
- ScalaTest — .
- JUnit 5 — Java-.
- kotlin.test — multiplatform . — JUnit, .
- AssertJ — . FestAssert, - .
- Kotest — KotlinTest, kotlin.test. , ScalaTest. 1-22 — scala.
- Truth — . , AssertJ.
- Hamrest — . valid4j.
- Strikt — AssertJ .
- Kluent — , JUnit ( — kotlin.test), Kotest. — , .
- Atrium — , AssertJ, . — ( maven/gradle).
- Expekt — Chai.js. : — 4 .
- AssertK — AssertJ, AssertK ( ).
- 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 |
:
- 要仅连接断言,您需要更深入地研究。我认为,很难立即理解这一点。
- , reified, : .
- : . .
- :
<Click to see difference>. - : .
- : , .
-
"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>. - : .
— … ,
containsExactly, —hasSameElementsAs, —.usingRecursiveComparison().isEqualTo.
:
<Click to see difference>.
: - , . , , .
:
.usingRecursiveComparison(), . : , , . , , ,
assertThat(actual) .usingRecursiveComparison() .isNotEqualTo(unexpected)
: .
: . , DSL.
- , .
- : , ,
assertThrowsJUnit5. , 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) ...
, 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>.
: , .
: .
- : .
- : , . .
- : DSL
contains,containsinclude,theSameElementsAs. - : , .
- : , .
- , , . — , .
- , 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
— AssertJ. ( , -).
: AssertJ
assertThat(collection).containsAll(items), AssertK ,containsAllvararg. ,containsAll(1,2,3), . , , — . — . ,containsOnlycontainsExactly.
:
<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>
?
: .
- : 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. . , :containsvararg,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 - : .
: (
assertThat(actual, `is`(not(unexpected)))
assertThat(actual, not(unexpected))
containsStringvscontainsvshasItemvshasItems. , :hasItemsvararg,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>.
: .
: .
- : -
assertEquals(expected, actual), :assertArrayEquals,assertIterableEquals.. - : , JUnit - , .
- :
assertLinesMatch(listOf(".*$needle.*"), listOf(haystack)), . - :
assertLinesMatch, ,assertIterableEquals. - : ,
assertIterableEqualsMapSet, . - : .
- . JUnit, . , .
- , JUnit, :
- .
-
assertIterableEquals, . - : JUnit'
assertEquals, kotlin.test , . - : .
-
expect(x).equal(y)x.should.equal(y), . , . - :
contains(item)should.have.elements(items)should.contain.elements(items).containsAll. , :should.have.elementsvararg. ,should.have.elements(1,2,3), .any:.should.not.contain.any.elements. - : , .
- .
- .
- : .
- : .
- :
<Click to see difference>.
Kotest, Kluent AssertJ. , Kotlin , AssertJ ( ). , .
— , , AssertJ. , , .