【问题标题】:Make Julia testsuite report all error messages at end of run让 Julia 测试套件在运行结束时报告所有错误消息
【发布时间】:2019-06-23 14:10:03
【问题描述】:

我正在使用 Julia 测试套件功能,我非常喜欢它。 然而,我想不通的是如何让测试套件在完成后报告潜在的消息。

假设我有一个像下面这样的测试套件,其中每个函数在返回之前依次执行一堆测试

@testset "MyTestSuite" begin
    @testset "Subtest1" begin @test my_test_1() end
    @testset "Subtest2" begin @test my_test_2() end
    @testset "Subtest3" begin @test my_test_3() end
    @testset "Subtest4" begin @test my_test_4() end
end

如果现在说 my_test_4 失败或抛出错误,那么输出将如下所示

Test Summary:                                   |    Pass  Error    Total
MyTestSuite                                     |      65      1       66
  Subtest1                                      |       5      1        6
  Subtest2                                      |      10      0       10
  Subtest3                                      |      20      0       20
  Subtest4                                      |      30      0       30
ERROR: LoadError: Some tests did not pass: 65 passed, 0 failed, 1 errored, 0 broken.

但现在(据我所知)我可以在不向上滚动终端输出的情况下查看问题所在。如果我的测试套件足够长,并产生足够多的诊断信息,那么我什至可能会丢失错误信息,或者至少很难找到。

那么,有人知道解决这个问题的好方法吗?是否可以为宏 @testset 提供选项以确保它打印收集错误以进行进一步处理?

【问题讨论】:

    标签: unit-testing error-handling julia test-suite


    【解决方案1】:

    您可以定义您的自定义AbstractTestSet。在 Julia 手册中描述为 here

    这是改编自手册的示例。先定义:

    using Test
    
    struct CustomTestSet <: Test.AbstractTestSet
        description::AbstractString
        results::Vector
        CustomTestSet(desc) = new(desc, [])
    end
    
    Test.record(ts::CustomTestSet, child::Test.AbstractTestSet) = push!(ts.results, child)
    Test.record(ts::CustomTestSet, res::Test.Result) = push!(ts.results, res)
    
    function Test.finish(ts::CustomTestSet)
        if Test.get_testset_depth() > 0
            Test.record(Test.get_testset(), ts)
        end
        ts
    end
    

    现在你可以写了:

    julia> res = @testset CustomTestSet "custom testset" begin
               # this testset should inherit the type, but not the argument.
               @testset "custom testset inner" begin
                   @test 1==1
                   @test 1==2
                   @test 2==2
                   @test 2==3
               end
           end
    CustomTestSet("custom testset", Any[CustomTestSet("custom testset inner", Any[Test Passed, Test Failed at REPL[10]:5
      Expression: 1 == 2
       Evaluated: 1 == 2, Test Passed, Test Failed at REPL[10]:7
      Expression: 2 == 3
       Evaluated: 2 == 3])])
    
    julia> res.results[1].results
    4-element Array{Any,1}:
     Test Passed
     Test Failed at REPL[10]:5
      Expression: 1 == 2
       Evaluated: 1 == 2
     Test Passed
     Test Failed at REPL[10]:7
      Expression: 2 == 3
       Evaluated: 2 == 3
    

    并且您可以访问一个向量,该向量告诉您什么通过了,什么失败了,失败时问题出在哪里。

    您还可以过滤掉通过的测试:

    julia> filter(x -> !(x isa Test.Pass), res.results[1].results)
    2-element Array{Any,1}:
     Test Failed at REPL[6]:5
      Expression: 1 == 2
       Evaluated: 1 == 2
     Test Failed at REPL[6]:7
      Expression: 2 == 3
       Evaluated: 2 == 3
    

    如果您的测试有更复杂的嵌套结构,您应该递归地进行。

    这是你想要的吗?

    【讨论】:

    • 这当然符合我所寻找的内容,并且已经非常有用。但是,您编写的函数还记录了所有成功的测试。就我而言,这有点问题,因为我自动生成了很多测试(通过使用@test wihing foor 循环),并且这些也显示出来了。您的解决方案是否有一个很好的调整,以便只记录失败的测试?
    • 是的 - 只是过滤掉成功的测试。我将在答案中展示一个示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多