代码之家  ›  专栏  ›  技术社区  ›  DVK

模仿Perl的测试最惯用的方法是什么::more::done_testing?

  •  3
  • DVK  · 技术社区  · 14 年前

    我必须使用非常旧的版本为环境中的构建单元测试 Test::More (PurL5.8) $Test::More::VERSION being '0.80' )在添加 done_testing() .

    升级到更新的测试:出于实际原因,不存在更多问题。我尽量避免使用 no_tests -一般来说,当单元测试过早退出时不捕获是一个坏主意——比如说,由于某些逻辑没有在您期望的时候执行。

    运行可配置数量的测试最惯用的方法是什么 假设没有 诺亚试验 DONEY测试() 使用吗?


    细节 :

    我的单元测试通常采用以下形式:

    use Test::More;
    my @test_set = (
       [ "Test #1", $param1, $param2, ... ]
      ,[ "Test #1", $param1, $param2, ... ]
      # ,...
    );
    
    foreach my $test (@test_set) {
        run_test($test);
    }
    
    sub run_test {
        # $expected_tests += count_tests($test);
        ok(test1($test)) || diag("Test1 failed");
        # ...
    }
    

    标准方法 use Test::More tests => 23; BEGIN {plan tests => 23} 不起作用,因为这两个都显然是以前执行过的 @tests 是众所周知的。


    我目前的方法是 @测试 全球和定义 BEGIN {} 封锁如下:

    use Test::More;
    BEGIN {
        our @test_set = (); # Same set of tests as above
        my $expected_tests = 0;
        foreach my $test (@tests) {
            my $expected_tests += count_tests($test);
        }
        plan tests => $expected_tests;
    }
    our @test_set; # Must do!!! Since first "our" was in BEGIN's scope :(
    foreach my $test (@test_set) { run_test($test); } # Same
    sub run_test {}  # Same
    

    我觉得这可以更习惯地做,但不确定如何改进。最主要的气味是复制品 our @test_test 声明-在 BEGIN{} 之后。


    另一种方法是模拟 DONEY测试() 通过呼叫 Test::More->builder->plan(tests=>$total_tests_calculated) . 我不确定它在成语上是否更明智。

    4 回复  |  直到 14 年前
        1
  •  1
  •   FMc TLP    14 年前

    使用一个闭包返回测试集,这样可以避免包变量的尴尬,如何?这是一个例子:

    use strict;
    use warnings;
    use Test::More;
    
    BEGIN {
        my @ts = (
            [ 'Test 1', 1, 1 ],
            [ 'Test 2', 3, 3 ],
        );
    
        plan tests => scalar @ts;
    
        sub test_sets { return @ts }
    }
    
    for my $ts ( test_sets() ){
        run_test($ts);
    }
    
    sub run_test {
        my ($msg, $val, $exp) = @{shift()};
        is $val, $exp, $msg;
    }
    
        2
  •  3
  •   Schwern    14 年前

    不要对旧版本进行黑客攻击,只需附带一份test::more。它没有依赖关系。只需将其安装到 t/lib 您的发行版(您可以构建它,然后复制 blib/lib 然后 use lib "t/lib" 在你的测试中。

        3
  •  1
  •   Eric Strom    14 年前

    这里有一个相当惯用的方法:

    use warnings;
    use strict;
    use Test::More;
    use List::Util 'sum';
    
    sub count_tests {1}
    
    BEGIN {
        plan tests => sum map {
            count_tests($_)
        } @test::set = (
            [ "Test #1", '$param1, $param2, ...' ],
            [ "Test #1", '$param1, $param2, ...' ],
        )
    }
    
    run_test($_) for @test::set;
    

    使用完全限定的名称可以避免 our ,您也可以使用 @::test_set 如果你担心把东西放进 test:: 包裹。并使用 map sum List::Util 缩短中的代码 BEGIN 阻止一点。该函数形式还反转了数据流,从而允许在结束时声明所有测试,从而保持 plan 在顶部打电话,提醒为什么 开始 首先使用了块。

        4
  •  1
  •   Schwern    14 年前

    如果您所需要的只是根据一个测试表来计算计划,那么这是微不足道的。

    use Test::More;
    
    my $Asserts_Per_Set = 10;
    my %Tests = (
        "Test #1" => { foo => "bar", this => "that" },
        "Test #2" => { foo => "yar", this => 42     },
        ...
    );
    
    plan tests => keys %Tests * $Asserts_Per_Set;
    
    for my $name (keys %Tests) {
        run_tests($name, $Tests{$name});
    }
    

    如果出于某种原因 run_tests 需要根据数据运行可变数量的测试,利用 skip 而不是 if 所以它总是运行一致数量的测试。

    SKIP: {
        skip "Can't run foo test on frobnitz", 2 if $test->{foo} and $test->{frobnitz};
    
        is foo(), $test->{foo};
        is bar(), $test->{foo} + 9;
    }
    

    对于任何更复杂的事情,利用 BEGIN 阻碍。

    use Test::More;
    my $Count;
    
    BEGIN { $Count += X }
    
    ...run X tests...
    
    BEGIN { $Count += Y }
    
    ...run Y tests...
    
    BEGIN { plan tests => $Count }
    

    这至少使测试计数计算与测试的计算块保持一致,而不是将其全部放在顶部一个不可维护的大斑点中。它是高度可见的,除了 开始 .

    顺便说一下,新版本的test::more subtest 更好地处理将测试分解为多个计划的问题。