編寫測試集

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

現在,我們所有的測試都通過了!