Zoeken…


Syntaxis

  • @test [expr]
  • @test_throws [Uitzondering] [expr]
  • @testset "[naam]" begint; [Proeven]; einde
  • Pkg.test ([package])

Opmerkingen

De standaardbibliotheekdocumentatie voor Base.Test omvat aanvullend materiaal dat verder gaat dan in deze voorbeelden wordt getoond.

Een pakket testen

Gebruik de functie Pkg.test om de eenheidstests voor een pakket uit te Pkg.test . Voor een pakket met de naam MyPackage zou het commando zijn

julia> Pkg.test("MyPackage")

Een verwachte output zou vergelijkbaar zijn met

INFO: Computing test dependencies for MyPackage...
INFO: Installing BaseTestNext v0.2.2
INFO: Testing MyPackage
Test Summary: | Pass  Total
  Data        |   66     66
Test Summary: | Pass  Total
  Monetary    |  107    107
Test Summary: | Pass  Total
  Basket      |   47     47
Test Summary: | Pass  Total
  Mixed       |   13     13
Test Summary: | Pass  Total
  Data Access |   35     35
INFO: MyPackage tests passed
INFO: Removing BaseTestNext v0.2.2

hoewel het uiteraard niet te verwachten is dat het exact overeenkomt met het bovenstaande, omdat verschillende pakketten verschillende frameworks gebruiken.

Met deze opdracht wordt het bestand test/runtests.jl het pakket in een schone omgeving uitgevoerd.

Men kan alle geïnstalleerde pakketten tegelijk testen met

julia> Pkg.test()

maar dit duurt meestal erg lang.

Een eenvoudige test schrijven

Eenheidstests worden in het pakket test/runtests.jl . Meestal begint dit bestand

using MyModule
using Base.Test

De basiseenheid van testen is de macro @test . Deze macro is als een soort bewering. Elke booleaanse uitdrukking kan worden getest in de @test macro:

@test 1 + 1 == 2
@test iseven(10)
@test 9 < 10 || 10 < 9

We kunnen de macro @test in de REPL uitproberen:

julia> using Base.Test

julia> @test 1 + 1 == 2
Test Passed
  Expression: 1 + 1 == 2
   Evaluated: 2 == 2

julia> @test 1 + 1 == 3
Test Failed
  Expression: 1 + 1 == 3
   Evaluated: 2 == 3
ERROR: There was an error during testing
 in record(::Base.Test.FallbackTestSet, ::Base.Test.Fail) at ./test.jl:397
 in do_test(::Base.Test.Returned, ::Expr) at ./test.jl:281

De testmacro kan vrijwel overal worden gebruikt, zoals in lussen of functies:

# For positive integers, a number's square is at least as large as the number
for i in 1:10
    @test i^2 ≥ i
end

# Test that no two of a, b, or c share a prime factor
function check_pairwise_coprime(a, b, c)
    @test gcd(a, b) == 1
    @test gcd(a, c) == 1
    @test gcd(b, c) == 1
end

check_pairwise_coprime(10, 23, 119)

Een testset schrijven

0.5.0

In versie v0.5 zijn Base.Test ingebouwd in de standaardbibliotheek Base.Test module en hoeft u niets speciaals te doen (behalve using Base.Test ) om ze te gebruiken.

0.4.0

Testsets maken geen deel uit van de Base.Test bibliotheek van Julia v0.4. In plaats daarvan moet je REQUIRE de BaseTestNext module en voeg using BaseTestNext om het bestand. Om zowel versie 0.4 als 0.5 te ondersteunen, zou je kunnen gebruiken

if VERSION ≥ v"0.5.0-dev+7720"
    using Base.Test
else
    using BaseTestNext
    const Test = BaseTestNext
end

Het is handig om gerelateerde @test samen te groeperen in een testset. Naast een duidelijkere testorganisatie bieden testsets een betere output en meer aanpasbaarheid.

Een testset definiëren wikkel elk aantal @test s met @testset block:

@testset "+" begin
    @test 1 + 1 == 2
    @test 2 + 2 == 4
end

@testset "*" begin
    @test 1 * 1 == 1
    @test 2 * 2 == 4
end

Als u deze testsets uitvoert, wordt de volgende uitvoer afgedrukt:

Test Summary: | Pass  Total
  +           |    2      2

Test Summary: | Pass  Total
  *           |    2      2

Zelfs als een testset een falende test bevat, wordt de volledige testset uitgevoerd en worden de fouten geregistreerd en gerapporteerd:

@testset "-" begin
    @test 1 - 1 == 0
    @test 2 - 2 == 1
    @test 3 - () == 3
    @test 4 - 4 == 0
end

Het uitvoeren van deze testset resulteert in

-: 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.
    ...

Testsets kunnen worden genest, waardoor een willekeurige diepe organisatie mogelijk is

@testset "Int" begin
    @testset "+" begin
        @test 1 + 1 == 2
        @test 2 + 2 == 4
    end
    @testset "-" begin
        @test 1 - 1 == 0
    end
end

Als de tests slagen, worden alleen de resultaten voor de buitenste testset weergegeven:

Test Summary: | Pass  Total
  Int         |    3      3

Maar als de tests mislukken, wordt een analyse van de exacte testset en de test die de fout veroorzaakt gerapporteerd.

De macro @testset kan worden gebruikt met een for lus om meerdere @testset tegelijk te maken:

@testset for i in 1:5
    @test 2i == i + i
    @test i^2 == i * i
    @test i ÷ i == 1
end

welke rapporten

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

Een veel voorkomende structuur is om testonderdelen of types van buitenste testsets te hebben. Binnen deze buitentestsets, testgedrag binnentestsets. Stel bijvoorbeeld dat we een type UniversalSet hebben gemaakt met een enkele instantie die alles bevat. Voordat we het type zelfs implementeren, kunnen we testgestuurde ontwikkelingsprincipes gebruiken en de tests implementeren:

@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

We kunnen dan beginnen met het implementeren van onze functionaliteit totdat deze onze tests doorstaat. De eerste stap is om het type te definiëren:

immutable UniversalSet <: Base.AbstractSet end

Slechts twee van onze tests slagen nu. We kunnen implementeren in :

immutable UniversalSet <: Base.AbstractSet end
Base.in(x, ::UniversalSet) = true

Dit maakt ook enkele van onze subsets testen geslaagd. De issubset ( ) fallback werkt niet voor UniversalSet , omdat de fallback probeert elementen te herhalen, wat we niet kunnen doen. We kunnen eenvoudig een specialisatie definiëren die issubset return true voor elke set:

immutable UniversalSet <: Base.AbstractSet end
Base.in(x, ::UniversalSet) = true
Base.issubset(x::Base.AbstractSet, ::UniversalSet) = true

En nu zijn al onze tests geslaagd!

Uitzonderingen testen

Uitzonderingen die worden aangetroffen tijdens het uitvoeren van een test zullen de test niet doorstaan, en als de test zich niet in een testset bevindt, beëindigt u de testmotor. Meestal is dit een goede zaak, omdat in de meeste situaties uitzonderingen niet het gewenste resultaat zijn. Maar soms wil men specifiek testen dat een bepaalde uitzondering wordt opgeworpen. De macro @test_throws maakt dit mogelijk.

julia> @test_throws BoundsError [1, 2, 3][4]
Test Passed
  Expression: ([1,2,3])[4]
      Thrown: BoundsError

Als de verkeerde uitzondering wordt gegenereerd, @test_throws nog steeds:

julia> @test_throws TypeError [1, 2, 3][4]
Test Failed
  Expression: ([1,2,3])[4]
    Expected: TypeError
      Thrown: BoundsError
ERROR: There was an error during testing
 in record(::Base.Test.FallbackTestSet, ::Base.Test.Fail) at ./test.jl:397
 in do_test_throws(::Base.Test.Threw, ::Expr, ::Type{T}) at ./test.jl:329

en als er geen uitzondering wordt gegenereerd, @test_throws ook:

julia> @test_throws BoundsError [1, 2, 3, 4][4]
Test Failed
  Expression: ([1,2,3,4])[4]
    Expected: BoundsError
  No exception thrown
ERROR: There was an error during testing
 in record(::Base.Test.FallbackTestSet, ::Base.Test.Fail) at ./test.jl:397
 in do_test_throws(::Base.Test.Returned, ::Expr, ::Type{T}) at ./test.jl:329

Drijvend punt testen Gelijkheid bij benadering

Wat is het probleem met het volgende?

julia> @test 0.1 + 0.2 == 0.3
Test Failed
  Expression: 0.1 + 0.2 == 0.3
   Evaluated: 0.30000000000000004 == 0.3
ERROR: There was an error during testing
 in record(::Base.Test.FallbackTestSet, ::Base.Test.Fail) at ./test.jl:397
 in do_test(::Base.Test.Returned, ::Expr) at ./test.jl:281

De fout wordt veroorzaakt door het feit dat geen van de waarden 0.1 , 0.2 en 0.3 in de computer worden weergegeven als exact die waarden - 1//10 , 2//10 en 3//10 . In plaats daarvan worden ze benaderd door waarden die heel dichtbij zijn. Maar zoals te zien in de bovenstaande testfout, kan het resultaat bij het optellen van twee benaderingen een iets slechtere benadering zijn dan mogelijk is. Er is veel meer aan dit onderwerp dat hier niet kan worden behandeld.

Maar we hebben geen pech! Om te testen dat de combinatie van afronden naar een drijvend puntnummer en drijvend punt rekenkundig ongeveer correct is, zelfs als ze niet exact zijn, kunnen we de isapprox functie gebruiken (die overeenkomt met operator ). Dus we kunnen onze test herschrijven als

julia> @test 0.1 + 0.2 ≈ 0.3
Test Passed
  Expression: 0.1 + 0.2 ≈ 0.3
   Evaluated: 0.30000000000000004 isapprox 0.3

Natuurlijk, als onze code helemaal fout was, zal de test dat nog steeds vangen:

julia> @test 0.1 + 0.2 ≈ 0.4
Test Failed
  Expression: 0.1 + 0.2 ≈ 0.4
   Evaluated: 0.30000000000000004 isapprox 0.4
ERROR: There was an error during testing
 in record(::Base.Test.FallbackTestSet, ::Base.Test.Fail) at ./test.jl:397
 in do_test(::Base.Test.Returned, ::Expr) at ./test.jl:281

De isapprox functie gebruikt heuristieken op basis van de grootte van de getallen en de precisie van het drijvende-komma-type om de hoeveelheid te tolereren fouten te bepalen. Het is niet geschikt voor alle situaties, maar het werkt in de meeste en bespaart veel moeite met het implementeren van een eigen versie van isapprox .



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow