簡體   English   中英

模仿Perl的Test :: More :: done_testing最慣用的方法是什么?

[英]What is the most idiomatic way to emulating Perl's Test::More::done_testing?

我必須在環境中構建單元測試,其中包含一個非常舊版本的Test::More (perl5.8,其中$Test::More::VERSION being '0.80' ),它早於添加done_testing()

由於實際原因,升級到更新的Test :: More是不可能的。 我試圖避免使用no_tests - 當你的單元測試過早退出時通常是一個壞主意 - 比如由於某些邏輯沒有按預期執行。

假設沒有使用no_testsdone_testing() ,那么運行可配置數量的測試的最慣用方法是什么?


細節

我的單元測試通常采用以下形式:

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;方法use Test::More tests => 23; 或者BEGIN {plan tests => 23}不起作用,因為兩者顯然都是在@tests之前執行的。


我目前的方法是將@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{}和之后。


另一種方法是通過調用Test::More->builder->plan(tests=>$total_tests_calculated)來模擬done_testing() Test::More->builder->plan(tests=>$total_tests_calculated) 我不確定它是否更具有慣用性。

不要破解舊版本,只需附帶Test :: More的副本。 它沒有依賴關系。 只需將其安裝到您的發行版的t/lib中(您可以構建它然后復制blib/lib ),然后在測試中use lib "t/lib"

這是一個相當慣用的方法:

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:: package中添加某些東西,也可以使用@::test_set 使用List::Util mapsum可以縮短BEGIN塊中的代碼。 函數形式還反轉了數據流,允許在最后聲明所有測試,將plan調用保持在頂部,以提醒為什么首先使用BEGIN塊。

如何使用閉包來返回測試集,這可以避免包變量的尷尬? 這是一個例子:

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;
}

如果您只需要根據測試表計算計划,那就太微不足道了。

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 }

這至少使測試計數計算與其計算的測試塊保持一致,而不是將其全部放在頂部的一個大的不可維護的blob中。 這一切都非常明顯,除了BEGIN之外不需要任何魔力。

順便提一下,Test :: More的新版本有subtest來更好地處理將測試分解為多個計划的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM