編寫測試集
Version >= 0.5.0
在版本 v0.5 中,測試集內建於標準庫 Base.Test
模組中,你無需執行任何特殊操作(除了 using Base.Test
)以使用它們。
Version = 0.4.0
測試集不是 Julia v0.4 的 Base.Test
庫的一部分。相反,你必須 REQUIRE
BaseTestNext
模組,並將 using BaseTestNext
新增到你的檔案。要支援版本 0.4 和 0.5,你可以使用
if VERSION ≥ v"0.5.0-dev+7720"
using Base.Test
else
using BaseTestNext
const Test = BaseTestNext
end
在測試集中將相關的 @test
組合在一起是有幫助的。除了更清晰的測試組織,測試集還提供更好的輸出和更多的可定製性。
要定義測試集,只需使用 @testset
塊包裝任意數量的 @test
:
@testset "+" begin
@test 1 + 1 == 2
@test 2 + 2 == 4
end
@testset "*" begin
@test 1 * 1 == 1
@test 2 * 2 == 4
end
執行這些測試集將列印以下輸出:
Test Summary: | Pass Total
+ | 2 2
Test Summary: | Pass Total
* | 2 2
即使測試集包含失敗的測試,整個測試集也將執行完成,並且將記錄並報告失敗:
@testset "-" begin
@test 1 - 1 == 0
@test 2 - 2 == 1
@test 3 - () == 3
@test 4 - 4 == 0
end
執行此測試集會導致
-: Test Failed
Expression: 2 - 2 == 1
Evaluated: 0 == 1
in record(::Base.Test.DefaultTestSet, ::Base.Test.Fail) at ./test.jl:428
...
-: Error During Test
Test threw an exception of type MethodError
Expression: 3 - () == 3
MethodError: no method matching -(::Int64, ::Tuple{})
...
Test Summary: | Pass Fail Error Total
- | 2 1 1 4
ERROR: Some tests did not pass: 2 passed, 1 failed, 1 errored, 0 broken.
...
測試集可以巢狀,允許任意深度組織
@testset "Int" begin
@testset "+" begin
@test 1 + 1 == 2
@test 2 + 2 == 4
end
@testset "-" begin
@test 1 - 1 == 0
end
end
如果測試通過,那麼這將只顯示最外層測試集的結果:
Test Summary: | Pass Total
Int | 3 3
但是如果測試失敗,則會報告深入到確切的測試集並導致失敗的測試。
@testset
巨集可與 for
迴圈一起使用,一次建立多個測試集:
@testset for i in 1:5
@test 2i == i + i
@test i^2 == i * i
@test i ÷ i == 1
end
報道
Test Summary: | Pass Total
i = 1 | 3 3
Test Summary: | Pass Total
i = 2 | 3 3
Test Summary: | Pass Total
i = 3 | 3 3
Test Summary: | Pass Total
i = 4 | 3 3
Test Summary: | Pass Total
i = 5 | 3 3
常見的結構是使外部測試集測試元件或型別。在這些外部測試集中,內部測試集測試行為。例如,假設我們建立了一個型別 UniversalSet
,其中包含一個包含所有內容的單例例項。在我們實現型別之前,我們可以使用測試驅動的開發原則並實現測試:
@testset "UniversalSet" begin
U = UniversalSet.instance
@testset "egal/equal" begin
@test U === U
@test U == U
end
@testset "in" begin
@test 1 in U
@test "Hello World" in U
@test Int in U
@test U in U
end
@testset "subset" begin
@test Set() ⊆ U
@test Set(["Hello World"]) ⊆ U
@test Set(1:10) ⊆ U
@test Set([:a, 2.0, "w", Set()]) ⊆ U
@test U ⊆ U
end
end
然後我們可以開始實現我們的功能,直到它通過測試。第一步是定義型別:
immutable UniversalSet <: Base.AbstractSet end
我們現在只有兩個測試通過。我們可以實現 in
:
immutable UniversalSet <: Base.AbstractSet end
Base.in(x, ::UniversalSet) = true
這也使我們的一些子集測試通過。然而,issubset
(⊆
)回退對 UniversalSet
不起作用,因為回退試圖迭代元素,這是我們做不到的。我們可以簡單地定義一個特殊化,使得 issubset
可以為任何集合返回 true
:
immutable UniversalSet <: Base.AbstractSet end
Base.in(x, ::UniversalSet) = true
Base.issubset(x::Base.AbstractSet, ::UniversalSet) = true
現在,我們所有的測試都通過了!