Julia Language
단위 테스트
수색…
통사론
- @test [expr]
- @test_throws [예외] [expr]
- @testset "[이름]"시작; [테스트]; 종료
- Pkg.test ([패키지])
비고
Base.Test
대한 표준 라이브러리 설명서는이 예제에 표시된 것 이상의 추가 자료를 다룹니다.
패키지 테스트
패키지에 대한 단위 테스트를 실행하려면 Pkg.test
함수를 사용하십시오. MyPackage
라는 패키지의 경우 명령은 다음과 같습니다.
julia> Pkg.test("MyPackage")
예상되는 출력은 다음과 같습니다.
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
분명히, 다른 패키지가 다른 프레임 워크를 사용하기 때문에 위와 정확히 일치한다고 기대할 수는 없습니다.
이 명령은 클린 환경에서 패키지의 test/runtests.jl
파일을 실행합니다.
한 번에 설치된 모든 패키지를 테스트 할 수 있습니다.
julia> Pkg.test()
그러나 이것은 대개 매우 오랜 시간이 걸립니다.
간단한 테스트 작성하기
단위 테스트는 패키지의 test/runtests.jl
파일에 선언되어 있습니다. 일반적으로이 파일은
using MyModule
using Base.Test
테스트의 기본 단위는 @test
매크로입니다. 이 매크로는 일종의 주장과 같습니다. 모든 부울 표현식은 @test
매크로에서 테스트 할 수 있습니다.
@test 1 + 1 == 2
@test iseven(10)
@test 9 < 10 || 10 < 9
우리는 REPL에서 @test
매크로를 시험해 볼 수 있습니다 :
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
테스트 매크로는 루프 또는 함수와 같이 어디에서나 사용할 수 있습니다.
# 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)
테스트 세트 작성
버전 v0.5에서는 테스트 세트가 표준 라이브러리 Base.Test
모듈에 내장되어 있으므로 using Base.Test
를 사용하는 것 외에 특별한 작업을 수행 할 필요가 없습니다.
테스트 세트는 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
테스트 세트에 함께 그룹화하는 것이 좋습니다. 명확한 테스트 조직 외에도 테스트 세트는 더 나은 출력과 더 많은 사용자 정의 기능을 제공합니다.
테스트 세트를 정의하려면 @test
세트를 @testset
블록으로 임의의 수만큼 감싸기 @testset
됩니다.
@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
이것은 또한 일부 하위 테스트를 통과시킵니다. 그러나 fallback은 요소를 반복하려고 시도하기 때문에 issubset
( ⊆
) fallback은 UniversalSet
에서 작동하지 않습니다. 우리는 할 수 없습니다. 모든 세트에 대해 issubset
true
로 만드는 특수화를 간단하게 정의 할 수 있습니다.
immutable UniversalSet <: Base.AbstractSet end
Base.in(x, ::UniversalSet) = true
Base.issubset(x::Base.AbstractSet, ::UniversalSet) = true
그리고 지금, 우리의 모든 시험은 통과합니다!
예외 테스트
테스트를 실행하는 동안 예외가 발생하면 테스트가 실패하고 테스트가 테스트 세트에없는 경우 테스트 엔진을 종료하십시오. 대부분의 경우 예외가 원하는 결과가 아니기 때문에 일반적으로 이는 좋은 것입니다. 그러나 때로는 특정 예외가 발생했는지 구체적으로 테스트하려고합니다. @test_throws
매크로는 이것을 용이하게합니다.
julia> @test_throws BoundsError [1, 2, 3][4]
Test Passed
Expression: ([1,2,3])[4]
Thrown: BoundsError
잘못된 예외가 발생하면 @test_throws
는 여전히 실패합니다.
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
예외가 throw되지 않으면 @test_throws
도 실패합니다.
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
부동 소수점 근사 평등 테스트
다음과의 거래는 무엇입니까?
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
이 오류는 0.1
, 0.2
및 0.3
중 어느 것도 컴퓨터에서 정확하게 1//10
2//10
및 3//10
으로 표시되지 않기 때문에 발생합니다. 대신, 매우 가까운 값으로 근사됩니다. 그러나 위의 테스트 실패에서 볼 수 있듯이 두 근사를 함께 추가하면 결과가 가능한 것보다 약간 나쁜 근사가 될 수 있습니다. 이 주제 에는 여기에서 다룰 수없는 것들이 많이 있습니다.
그러나 우리는 운이 없다! 정확하지 않더라도, 부동 소수점 수로 반올림 및 부동 소수점 연산의 조합은 약 올바른지 테스트하기 위해 사용 가능 isapprox
(오퍼레이터에 대응하는 기능을 ≈
). 그래서 우리는 우리의 테스트를 다음과 같이 다시 작성할 수 있습니다.
julia> @test 0.1 + 0.2 ≈ 0.3
Test Passed
Expression: 0.1 + 0.2 ≈ 0.3
Evaluated: 0.30000000000000004 isapprox 0.3
물론, 우리 코드가 완전히 잘못 되었다면, 테스트는 여전히 그것을 잡을 것입니다 :
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
isapprox
함수는 허용되는 오류의 양을 결정하기 위해 숫자의 크기와 부동 소수점 유형의 정밀도에 기반한 경험적 방법을 사용합니다. 모든 상황에 적절하지는 않지만 대부분의 경우 작동하며 isapprox
의 자체 버전을 구현하는 데 많은 시간을 절약 할 수 있습니다.