自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

單元測(cè)試框架的對(duì)比

原創(chuàng) 精選
開發(fā) 測(cè)試
在開發(fā)過程中,我發(fā)現(xiàn) JUnit 并不總是那么好用。它在一些情況下需要耗費(fèi)挺多精力才能編寫出讓人滿意的測(cè)試。

作者 | 高悅翔

在我們?nèi)粘5?TDD 開發(fā)中,永遠(yuǎn)繞不過去的就是要編寫測(cè)試。而對(duì)于一個(gè) Java 程序員,JUnit 似乎是一個(gè)不二的選擇。它的確是一個(gè)十分優(yōu)秀的工具,在大多數(shù)情況下都能夠幫助我們完成測(cè)試的工作。

但是在開發(fā)過程中,我發(fā)現(xiàn) JUnit 并不總是那么好用。它在一些情況下需要耗費(fèi)挺多精力才能編寫出讓人滿意的測(cè)試。

JUnit 不擅長(zhǎng)的事情

一個(gè)讓人滿意的測(cè)試,應(yīng)該能夠清晰地體現(xiàn)被測(cè)試的目標(biāo)、測(cè)試的目的以及測(cè)試的輸入輸出,并且應(yīng)遵循 DRY 原則,盡可能的減少測(cè)試中的重復(fù)內(nèi)容。

JUnit 可以通過設(shè)計(jì)測(cè)試方法名和組織方法內(nèi)的代碼的方式清晰地表達(dá)意圖,也可以通過參數(shù)化測(cè)試來(lái)減少相同測(cè)試目的的代碼重復(fù)。但是它在這些地方都做得不夠好。

清晰表達(dá)測(cè)試的目的

在使用 JUnit 時(shí),清晰的表達(dá)測(cè)試意圖并不是總能做到的事情。這主要體現(xiàn)在兩個(gè)方面。

(1) 如何命名測(cè)試方法

第一個(gè)體現(xiàn)就是在使用 Java 編寫測(cè)試時(shí),采用什么樣的命名風(fēng)格來(lái)命名測(cè)試。是為了代碼風(fēng)格的統(tǒng)一而選擇駝峰?還是為了更高的可讀性選擇下劃線?這個(gè)問題在不同的項(xiàng)目中有不同的實(shí)踐,看起來(lái)是沒有一個(gè)統(tǒng)一的認(rèn)識(shí)。

而這個(gè)問題的根源是 JUnit 的測(cè)試名稱是 Java 的方法名,而 Java 的方法名又不能在其中插入空格。所以除了下面要介紹的兩種測(cè)試工具外,采用 Kotlin 來(lái)編寫 JUnit 也是一種方式。

(2) 如何組織方法內(nèi)的代碼

第二個(gè)體現(xiàn)就是 JUnit 對(duì)測(cè)試方法內(nèi)部如何編寫沒有強(qiáng)制的規(guī)定。這就意味著我可以在測(cè)試?yán)锩嫒我獾亟M織代碼,比如在一個(gè)測(cè)試方法里面對(duì)一個(gè)方法調(diào)用多次并驗(yàn)證每一次的結(jié)果,或者把調(diào)用測(cè)試目錄的邏輯和準(zhǔn)備數(shù)據(jù)的邏輯以及驗(yàn)證邏輯混合到一起。 總之這樣的結(jié)果就是測(cè)試方法內(nèi)的代碼組織方式千奇百怪,每當(dāng)閱讀別人編寫的測(cè)試的時(shí)候,總是要花上好幾分鐘才能知道這些代碼到底在干什么。

對(duì)于這個(gè)問題,我個(gè)人會(huì)選擇使用注釋來(lái)標(biāo)注一下 given 、 when 、 then,并且給 IDEA 設(shè)置了 live template 方便插入它們。

又不是不能用的參數(shù)化測(cè)試

如果說不能清晰地表達(dá)測(cè)試意圖這個(gè)問題還有一些 workaround 可以繞過去的話,JUnit 那僅僅是能用的參數(shù)化測(cè)試功能就沒有什么好辦法可以繞過去了。

JUnit 提供了各種 Source 注解來(lái)為參數(shù)化測(cè)試提供數(shù)據(jù),但是這個(gè)功能實(shí)在是太弱了,很難讓人滿意。

難以讓人滿意的第一個(gè)原因是,各種 Source 注解基本上只能支持 7 種基本類型再加上 String, Enum 和 Class 類型。如果想要使用其他類型的實(shí)例作為參數(shù)的話,就必須要使用 MethodSource 或者 ArgumentsSource 注解。

這就導(dǎo)致了第二個(gè)原因:這兩個(gè)注解需要單獨(dú)寫一個(gè)靜態(tài)方法或一個(gè) ArgumentProvider 的實(shí)現(xiàn),這就導(dǎo)致很難把測(cè)試參數(shù)寫到測(cè)試代碼旁邊。并且 Arguments.of() 方法并不利于閱讀測(cè)試參數(shù)。

這兩點(diǎn)導(dǎo)致測(cè)試的可讀性下降。而按照“測(cè)試即文檔”的原則,我們應(yīng)該盡力去保證測(cè)試的可讀性。

第三個(gè)原因則是來(lái)自 ParameterizedTest 注解。它的 name 字段可以使用參數(shù)的索引值來(lái)把參數(shù)填入模板中,生成更加可讀的測(cè)試名稱。

但是它的功能也僅限于此了。因?yàn)檫@個(gè)模板只能使用索引值,不能使用索引后再調(diào)用里面的方法或者字段。所以如果我們的參數(shù)是一個(gè)復(fù)雜對(duì)象,那么一定要重寫 toString 方法才能得到滿意的輸出。但是這又違背了編寫測(cè)試的原則之一——不能為了測(cè)試而添加實(shí)現(xiàn)代碼。

如果我們一定要得到一個(gè)更加表意的測(cè)試名稱,那么添加一個(gè)專用的測(cè)試參數(shù)也能做到。但是這又會(huì)導(dǎo)致 IDE 或者構(gòu)建工具的警告,因?yàn)樗鼈冋J(rèn)為這個(gè)參數(shù)沒有被使用。

總之,盡管 JUnit 可以解決絕大多數(shù)問題,但是在這么幾個(gè)小地方卻做的不是那么完美。

那么有沒有什么工具可以作為 JUnit 的替代呢?當(dāng)然是有的。下面我將按照我接觸的順序來(lái)介紹兩種種測(cè)試框架。可以在 GitHub 上找到下面例子的完整代碼。

使用 Spock 作為測(cè)試框架

Spock是一個(gè)用 Groovy 編寫的測(cè)試框架,按照 given/when/then 的結(jié)構(gòu)定義 dsl,能夠讓測(cè)試更加的語(yǔ)義化。它的一大特點(diǎn)是 Data Driven Test,可以方便的編寫參數(shù)化測(cè)試。

我曾在兩個(gè)項(xiàng)目上嘗試過使用 Spock 作為測(cè)試框架,幾乎沒有遇到過無(wú)法解決的問題。

如何使用 Spock

我們來(lái)看一個(gè)最簡(jiǎn)單的例子:

class MarsRoverSpockTest extends Specification { // 1
def "should return mars rover position and direction when mars rover report"() { //2
given: // 3.1
def marsRover = MarsRoverFixture.buildMarsRover(
position: new Position(1, 2),
direction: Direction.EAST,
)

when: // 3.2
def marsRoverInfo = marsRover.report()

then: // 3.3
marsRoverInfo.position == new Position(1, 2)
marsRoverInfo.direction == Direction.EAST
}
}

(1) 每一個(gè)測(cè)試都需要繼承抽象類 Specification;

(2) 可以使用字符串來(lái)命名測(cè)試;

(3) Spock 定義了一些 block,這里的 given 、 when 、 then 都是 block。

  • given block 負(fù)責(zé)測(cè)試的 setup 工作
  • when block 可以是任意代碼,不過最好是對(duì)測(cè)試目標(biāo)的調(diào)用。它總是和 then 一起出現(xiàn)
  • then block 用來(lái)斷言。這里不需要任何的 assertion,只需要編寫返回值是 boolean 的表達(dá)式即可

Spock 有非常友好的測(cè)試報(bào)告輸出。如果我們把上面的斷言特意改錯(cuò),就能得到這樣的測(cè)試輸出:

Condition not satisfied:

movedMarsRover.position == movedPosition
| | | |
| | | Position(x=-2, y=2)
| | false
| Position(x=-1, y=2)
MarsRover(position=Position(x=-1, y=2), direction=WEST)

在這個(gè)輸出里面,我們可以清晰的看出表達(dá)式兩端的值是什么,非常便于 debug。

特點(diǎn)

(1) 使用字符串命名測(cè)試方法

在前面的例子中,我們可以看到測(cè)試的方法名是使用字符串來(lái)命名,不需要像 JUnit 一樣遵循 Java 方法的命名規(guī)則。這樣我們就不用糾結(jié)使用什么樣的命名方法,只需要像寫一句話一樣來(lái)編寫測(cè)試方法名稱。

(2) 語(yǔ)義化的結(jié)構(gòu)

在前面的例子中,我們看到了 block 的概念。它可以幫助我們更好的組織代碼結(jié)構(gòu),寫出更加便于閱讀的代碼。其實(shí)在每一個(gè) block 聲明之后,我們還可以在添加一個(gè)字符串,達(dá)到注釋的作用。比如:

given: "a mars rover at position 1,2 and direction is north"

除了上面的例子里看到的,Spock 還提供了 cleanup 、 expect 、 where 這三個(gè) block。詳細(xì)信息可以看看它的??文檔??。

因?yàn)?Spock 強(qiáng)制要求使用 block 來(lái)組織測(cè)試代碼,這樣就可以強(qiáng)迫我們寫出結(jié)構(gòu)化的代碼,更加便于閱讀。

(3) 使用 data table 構(gòu)造參數(shù)化測(cè)試

對(duì)于參數(shù)化測(cè)試,我們?cè)賮?lái)看一個(gè)例子。

def "should move mars rover from position 1,2 forward to #movedPosition.x,#movedPosition.y when direction is #direction and move length is #length"() { 
given:
def marsRover = MarsRoverFixture.buildMarsRover(
position: new Position(1, 2),
direction: direction,
)

when:
def movedMarsRover = marsRover.forward(length)

then:
movedMarsRover.position == movedPosition
movedMarsRover.direction == direction

where:
direction | length || movedPosition
Direction.EAST | 2 || new Position(3, 2)
Direction.WEST | 3 || new Position(-2, 2)
Direction.SOUTH | -1 || new Position(1, 3)
Direction.NORTH | 1 || new Position(1, 3)
}

我們可以看到代碼的最后一段是一個(gè) where block,這是 Spock 中用來(lái)定義數(shù)據(jù)測(cè)試的數(shù)據(jù)的地方。例子中的寫法被稱作 data table。盡管 Spock 還支持一些其他的寫法,但是我個(gè)人認(rèn)為 data table 是一個(gè)更加可讀的寫法,所以這也是我最常使用的寫法。并且這個(gè)寫法不需要手動(dòng)調(diào)整格式,IDEA 支持自動(dòng) format,堪稱完美。

我們還可以留意一下方法名。方法名中有幾個(gè)以 # 開頭的字符串,它們其實(shí)是在引用 data table 中定義的變量。這種通過變量名引用的方式可讀性遠(yuǎn)遠(yuǎn)大于 JUnit 的索引值的方式。并且我們可以看到 #movedPosition.x 這樣的表達(dá)式,它們可以直接使用這些對(duì)象中的字段值來(lái)生成方法名,不需要依賴于對(duì)象的 toString 方法。

對(duì)于斷言失敗的測(cè)試,同樣會(huì)像上面的例子一樣在測(cè)試輸出中打印具體的數(shù)據(jù),方便定位到測(cè)試失敗的用例。

與 JUnit 對(duì)比起來(lái),Spock 的 data table 既讓參數(shù)列表和測(cè)試方法放到了一起,又能支持任意類型的參數(shù),還可以沒有副作用地定義參數(shù)名稱,算是把 JUnit 參數(shù)化測(cè)試的痛點(diǎn)都解決了。

(4) 簡(jiǎn)潔的斷言

在上面的例子中,我們看到 Spock 的斷言十分簡(jiǎn)潔,不需要像使用 assertj 一樣寫很長(zhǎng)的 assertThat(xxx).isEqualTo(yyy),只需要一個(gè)返回 boolean 的表達(dá)式就可以了。

甚至可以把多行斷言提取到一個(gè)方法中,返回他們與運(yùn)算的結(jié)果。

(5) 使用 Groovy 編寫測(cè)試

使用 Groovy 來(lái)編寫測(cè)試,可以說既是優(yōu)點(diǎn),也是缺點(diǎn)。

優(yōu)點(diǎn)是在于 Groovy 是動(dòng)態(tài)語(yǔ)言,我們可以利用這一特性在測(cè)試中少寫一些啰嗦的代碼。并且在前面的例子中,斷言里面獲取的 marsRover.position 字段本身是 private 字段,測(cè)試仍然可以正常執(zhí)行。這些都是由 Groovy 帶來(lái)的靈活性。

缺點(diǎn)在于這是一個(gè)相對(duì)小眾的語(yǔ)言。如果不是因?yàn)?Gradle,或許不會(huì)有多少人熟悉它的語(yǔ)法。這也會(huì)導(dǎo)致人們?cè)谶x擇它時(shí)會(huì)變得更加謹(jǐn)慎。

(6) 與 IDE 的完美集成

我一直使用的 IDEA 是能夠完美適配它的。除了前面提到的 format data table ,最主要的是 IDEA 能像執(zhí)行 JUnit 一樣執(zhí)行它,并且不需要任何的配置。

缺點(diǎn)

我在第一個(gè)項(xiàng)目里面使用 Spock 時(shí),幾乎沒有發(fā)現(xiàn)它有什么缺點(diǎn),以至于在后來(lái)的項(xiàng)目中總是在問 TL 能不能把它加到項(xiàng)目里來(lái)。

但是后來(lái)在一個(gè) Kotlin 項(xiàng)目中嘗試使用它時(shí),卻遇到一些問題。

與 Kotlin 的集成問題:

(1) 無(wú)法識(shí)別 Kotlin 的語(yǔ)法糖

Groovy 不能直接識(shí)別到 Kotlin 代碼中的各種語(yǔ)法糖,這就讓測(cè)試寫起來(lái)有那么一點(diǎn)點(diǎn)不舒服。

比如命名參數(shù)。其實(shí) Groovy 也支持命名參數(shù),但是語(yǔ)法和 Kotlin 不同。這就顯得有一點(diǎn)尷尬。不過這個(gè)問題可以通過為測(cè)試編寫一些 fixutre 之類的代碼來(lái)幫助處理這里問題。比如下面這個(gè) Kotlin 類型:

data class MarsRover(  
private val position: Position,
private val direction: Direction,
)

我們可以為它編寫一個(gè) fixture,就能在測(cè)試?yán)锩嬉彩褂妹麉?shù)了:

class MarsRoverFixture {  
@NamedVariant
static MarsRover buildMarsRover(position, direction) {
new MarsRover(position, direction)
}
}

其他的一些語(yǔ)法問題也基本都能繞過,本質(zhì)思路就是把要測(cè)試的代碼想象成編譯后的 Java,這樣就能找到繞過的辦法。

(2) 沒有對(duì) final class 的 mock 支持

這是一個(gè)基本繞不過去的問題。Kotlin 里面的類型默認(rèn)都是 final,不能再被繼承。但是 Spock 的 mock 卻需要為要 mock 的對(duì)象的類型創(chuàng)建一個(gè)子類。這就導(dǎo)致我們不能去 mock 那些類型。其實(shí)這個(gè)問題不是 Spock 特有的,Mockito 也有這個(gè)問題。只不過在使用 JUnit 時(shí)我們會(huì)選擇用 MockK 作為 Kotlin 項(xiàng)目的 mock 工具,而不是 Mockito。

解決這個(gè)問題的策略有好幾個(gè):

  • 盡可能不去 mock。這要求我們?cè)O(shè)計(jì)出更容易測(cè)試的代碼,這樣就可以避免在測(cè)試中使用 mock。
  • 因?yàn)?Spring 組件需要被繼承,所以會(huì)使用 Kotlin All-open compiler 來(lái)為 Spring 提供支持,我們就可以 mock 這些 Spring Component

在寫這篇文章的時(shí)候,發(fā)現(xiàn)一個(gè)很久沒有更新的倉(cāng)庫(kù) kotlin-test-runner,也許可以借鑒一下這里的思路來(lái)解決這個(gè)問題。

(3) 與 JUnit 的兼容問題

對(duì)于上一個(gè)問題,我們當(dāng)時(shí)還有一個(gè) workaround,那就是使用 JUnit5 + MockK 來(lái)編寫那些需要 mock 的測(cè)試。但是那個(gè)時(shí)候的 Kotlin 版本還比較低,沒有遇到和 JUnit 的兼容問題。

兼容問題是 JUnit 在編寫 Spring 集成測(cè)試的時(shí)候,如果有 mock bean 的需求,需要使用 springmock 里面的 @MockkBean 注解。但是從 kotlin 1.5.30 開始,這個(gè)庫(kù)就不能和 Spock 編寫的 Spring 集成測(cè)試兼容,會(huì)出現(xiàn) NPE 問題。這個(gè)問題在使用 Kotlin 對(duì) Specification 子類進(jìn)行反射時(shí)會(huì)出現(xiàn)。

這個(gè)問題一直到 Kotlin 1.6.20-M1 才修復(fù)。

Groovy 語(yǔ)言的學(xué)習(xí)成本:

就像前面提到過的,使用 Groovy 還是有一些學(xué)習(xí)成本的。如果團(tuán)隊(duì)里沒有熟悉它的人,可能會(huì)走一點(diǎn)彎路。

使用 Kotest 作為測(cè)試框架

Kotest 是在無(wú)意中發(fā)現(xiàn)的測(cè)試框架,還沒有在實(shí)際的項(xiàng)目中實(shí)踐過。所以這里只能分享一下如何使用,沒有什么經(jīng)驗(yàn)分享。

如何使用 Kotest

我們來(lái)看一個(gè)例子:

class MarsRoverKotestTest : BehaviorSpec({  
given("a mars rover") {
val marsRover = MarsRover(
position = Position(1, 2),
direction = Direction.EAST,
)
`when`("it report information") {
val (position, direction) = marsRover.report()
then("get it's position and direction") {
position shouldBe Position(1, 2)
direction shouldBe Direction.EAST
}
}
}
})

這是一種 BDD 風(fēng)格的測(cè)試。Kotest 使用 BehaviorSpec 類封裝起來(lái)。

在 then 中,我們沒有看到常見的 assertThat() 語(yǔ)句,取而代之的是 Kotest 的 assertion 庫(kù)提供的方法。

特點(diǎn)

(1) 豐富的測(cè)試風(fēng)格支持

除了上面的例子,我們還有很多的測(cè)試風(fēng)格可以選擇,這在它的文檔中有介紹:??Testing Styles | Kotest??。

在這些風(fēng)格中,測(cè)試名稱都是通過字符串來(lái)編寫的。如前面所說,這樣我們就不用像使用 JUnit 一樣糾結(jié)測(cè)試方法的命名風(fēng)格,只管描述測(cè)試目的就可以來(lái)。

然而除了 BDD 這種測(cè)試風(fēng)格外,其他的測(cè)試風(fēng)格都沒有對(duì)測(cè)試代碼的組織有任何強(qiáng)制要求。這就需要團(tuán)隊(duì)為測(cè)試代碼測(cè)組織達(dá)成一致并維護(hù)它。這和 JUnit 沒有什么區(qū)別。

(2) 對(duì) data driven test 的支持

Kotest 提供了擴(kuò)展來(lái)支持 data driven test。當(dāng)然,不使用這個(gè)擴(kuò)展也可以進(jìn)行,比如用 list 構(gòu)造好數(shù)據(jù)之后 foreach 創(chuàng)建測(cè)試。不過這里的例子我們還是使用這個(gè)擴(kuò)展來(lái)演示。

class MarsRoverKotestTest : FunSpec({  
context("data test") {
withData(
nameFn = { (direction, length, position) ->
"should move mars rover from 1,2 to ${position.x},${position.y} when direction is $direction and move length is $length"
},
Triple(Direction.EAST, 2, Position(3, 2)),
Triple(Direction.WEST, 3, Position(-2, 2)),
Triple(Direction.SOUTH, -1, Position(1, 3)),
Triple(Direction.NORTH, 1, Position(1, 3)),
) { (direction, length, movedPosition) ->
val marsRover = MarsRover(
position = Position(1, 2),
direction = direction,
)
val movedMarsRover = marsRover.forward(length)
movedMarsRover.report().position shouldBe movedPosition
movedMarsRover.report().direction shouldBe direction
}
}
})

雖然這個(gè) data driven test 相對(duì)于 Spock 的 data table 來(lái)講沒有那么直觀,但是對(duì)比 JUnit 的話,能夠方便的自定義測(cè)試方法名、支持任意類型的參數(shù)并且測(cè)試數(shù)據(jù)與測(cè)試代碼可以放在一起,已經(jīng)算是一個(gè)巨大的進(jìn)步了。

(3) 簡(jiǎn)潔的斷言

在上面的例子里面我們看到,Kotest 提供了自己的斷言庫(kù),不需要再寫冗長(zhǎng)的 assertThat() 之類的語(yǔ)句。

(4) 使用 Kotlin 編寫,能與 Kotlin 項(xiàng)目完美結(jié)合

使用 Kotlin 來(lái)編寫測(cè)試,可以使用到 Kotlin 里面的各種語(yǔ)法糖。這樣就不用像 Spock 一樣在語(yǔ)法切換中掙扎。

(5) 支持 MockK

同樣的,因?yàn)?Kotest 的測(cè)試使用 Kotlin 編寫,自然是支持 MockK 的。這樣就能利用 MockK 的特性,支持對(duì) final class 的 mock。

(6) 與 JUnit 兼容

因?yàn)?Kotest 是基于 JUnit 平臺(tái)的,所以是能和 JUnit 兼容的,不會(huì)出現(xiàn)上面的 Spock 那樣的問題。

缺點(diǎn)

因?yàn)闆]有在實(shí)際的項(xiàng)目中實(shí)踐過,所以目前沒有發(fā)現(xiàn)很多的缺點(diǎn)。

(1) 與 IDEA 和 Gradle 的集成不夠完美

這個(gè)問題的表現(xiàn)是在 IDEA 里面無(wú)法執(zhí)行單個(gè)測(cè)試方法。但是細(xì)究后發(fā)現(xiàn),實(shí)際上是和 gradle 的集成不夠好。

默認(rèn)情況下,IDEA 會(huì)使用 gradle 來(lái)執(zhí)行測(cè)試。執(zhí)行單個(gè)測(cè)試的命令是 gradle test --tests "xxx.Class.yyyMethod"。對(duì)于 JUnit,這里的 class 和 method 是很直觀的類名和方法名。但是 Kotest 的寫法卻不是編寫類里面的方法,而是調(diào)用方法生成測(cè)試。所以 gradle 的這個(gè)命令就沒有辦法生效,也就沒有辦法只執(zhí)行一個(gè)測(cè)試方法了。

在把 IDEA 的配置更新成使用 IDEA 來(lái)運(yùn)行測(cè)試后,在 mac 上能夠正常執(zhí)行單個(gè)測(cè)試方法。

不要使用 Spek

前面介紹了兩種值得一試的測(cè)試框架,這里再介紹一種不建議使用的框架。

當(dāng)初想要嘗試這個(gè)框架,是因?yàn)榭吹接芯W(wǎng)友說這是 Kotlin 版本的 Spock 。但是實(shí)踐下來(lái)并沒有發(fā)現(xiàn)它有和 Spock 類似的功能,并且還出現(xiàn)了這些痛點(diǎn):

  • 與其他測(cè)試框架混合使用的問題:當(dāng)與其他測(cè)試框架混合使用時(shí),Spek 測(cè)試總是會(huì)先執(zhí)行。哪怕我們?cè)?IDEA 里面只想執(zhí)行一個(gè) JUnit 的單元測(cè)試,Spek 也會(huì)先把自己的所有測(cè)試跑完,然后才會(huì)執(zhí)行到我們想要執(zhí)行的測(cè)試。這就意味著在 Speck 測(cè)試編寫了很多之后,執(zhí)行其他測(cè)試就會(huì)等待很久。
  • 不能編寫 Spring 集成測(cè)試。
  • 我在寫 demo 的時(shí)候發(fā)現(xiàn),它的 IDEA 插件在 Windows 上面無(wú)法工作。

如果這些痛點(diǎn)你都能忍,那我也不建議使用這個(gè)框架,畢竟上面已經(jīng)有更好的選擇了。

總結(jié)

現(xiàn)在我們有了兩個(gè) JUnit 以外的測(cè)試框架選擇。當(dāng)然它們也不是完美的,JUnit 仍然是那個(gè)最穩(wěn)定、風(fēng)險(xiǎn)最低的那一個(gè)。但如果你想嘗試一下這兩個(gè)框架的話,可以考慮一下這些方面:

(1) 生產(chǎn)代碼的編程語(yǔ)言:

  • 如果是 Kotlin,那么可以考慮 Kotest,不要考慮 Spock
  • 如果是 Java,那么這兩個(gè)都值得考慮

(2) 語(yǔ)言熟悉程度:Kotlin 明顯是比 Groovy 更加流行,這個(gè)角度考慮的話 Kotest 是更優(yōu)的選擇

(3) 測(cè)試框架的流行程度(這方面我不知道有什么評(píng)價(jià)標(biāo)準(zhǔn),只是作為參考):

  • 兩個(gè)框架在 GitHub 上的 star 數(shù)量半斤八兩,一個(gè) 3.1k,一個(gè) 3.2k(JUnit 也才 4.9k)
  • 在 MVNRepository 上,Spock 的 usage 明顯高于 Kotest

(4) IDEA 的集成:

  • Spock 在這方面完全沒有問題
  • Kotest 需要安裝插件,并且需要配置才能運(yùn)行單個(gè)測(cè)試

(5Gradle 集成:

  • Spock 完美集成
  • Kotest 不能執(zhí)行單個(gè)測(cè)試
責(zé)任編輯:趙寧寧 來(lái)源: Thoughtworks洞見
相關(guān)推薦

2017-01-14 23:42:49

單元測(cè)試框架軟件測(cè)試

2024-10-16 16:09:32

2023-12-24 10:00:35

Java單元測(cè)試

2009-06-01 10:47:32

jboss seam例jboss seam開jboss seam

2009-08-19 09:00:48

單元測(cè)試框架自動(dòng)化測(cè)試

2010-08-27 09:11:27

Python單元測(cè)試

2023-07-26 08:58:45

Golang單元測(cè)試

2011-05-16 16:52:09

單元測(cè)試徹底測(cè)試

2022-04-27 08:17:07

OCMock單元測(cè)試集成

2017-01-14 23:26:17

單元測(cè)試JUnit測(cè)試

2017-01-16 12:12:29

單元測(cè)試JUnit

2011-06-14 15:56:42

單元測(cè)試

2020-08-18 08:10:02

單元測(cè)試Java

2024-04-26 11:14:34

C#單元測(cè)試框架

2017-03-23 16:02:10

Mock技術(shù)單元測(cè)試

2011-07-04 18:16:42

單元測(cè)試

2020-05-07 17:30:49

開發(fā)iOS技術(shù)

2021-05-05 11:38:40

TestNGPowerMock單元測(cè)試

2012-05-21 09:41:54

XcodeiOS單元測(cè)試

2011-06-14 15:39:46

單元測(cè)試
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)