如何在不丢失程序退出代码的情况下使用 Test::More 在 perl 程序中测试 subs?

How can I test subs in a perl programs with Test::More without losing the programs exit code?

在编写中小型 perl 程序时,我想用“Test::More”测试一些函数。

我的想法是能够像“./supertool.pl --test”那样调用我的程序来进行测试。虽然能够使用“./supertool.pl”进行正常程序使用。

但是当我添加“use Test::More qw(no_plan);”在头部部分,它使程序输出及其退出代码出现乱码。

这是一个可以在控制台中调用的示例,例如:'./supertool.pl;回声$? ; echo "预期:0"'.

#!/usr/bin/perl

use strict;
use warnings;
use Test::More qw(no_plan);

if (0)
{
        note("one test");
        test__x();
        done_testing;
}

exit(0);

sub test_x
{
        ok( 1, "1 is ok" );
}

输出为:

1..0
255
Expected: 0

但我希望输出是

0
Expected: 0

是否可以将 Test::More 调整为不打印“1..0”并且在不进行测试时不乱码程序退出代码?

有多种方法可以获得您想要的行为。

一种方法是告诉它您不会 运行 测试,根据那个 command-line 选项

use warnings;
use strict;
use feature 'say';

use Test::More;

my $run_tests = shift;

if ($run_tests) { 
    Test::More->builder->no_plan;
} 
else {
    Test::More->builder->output('/dev/null'); 
    Test::More->builder->skip_all('Not testing');
}
#...

if ($run_tests) {
    note("one test");
    test_x();
}

sub test_x { ok( 1, "1 is ok" ) }

根据需要将输出重定向到 /dev/null,因此不会看到跳过的消息,但作为示例提供(并且必须有一些东西)。

我使用后端 Test::Builder 模块(Test::More->builder returns 它的对象)的方法来设置 plan/skip,即使有 plan Test::More 本身发挥作用。

这是为了保持一致性,因为 output 我们确实需要 Test::Builder,作为 Test::Builder 的进一步示例,在可能需要的情况下,人们可以在其中找到更多工具需要。 Test::More 建立在这个模块之上,我建议仔细阅读它。

另一种声明 no_plan 的方法是在程序的最后使用 done_testing,以 $run_tests 为条件(但不在 END 块中,请参阅文档).

另一种方法是将所有测试放在 SKIP 块中,用于 conditional testing

use warnings;
use strict;
use feature 'say';

use Test::More qw(no_plan);

my $run_tests = shift; 
    
SKIP: {
    skip_test() if not $run_test;

    note("one test");
    test_x();
}


sub test_x { ok( 1, "1 is ok" ) }

sub skip_test {
    Test::More->builder->output('/dev/null'); 
    skip "Not testing";
}

根据问题的需要,输出再次发送到 /dev/null

我们也可以直接使用Test::Builder方法,要么skip

use warnings;
use strict;
use feature 'say';    
use Test::More qw(no_plan);

my $run_tests = shift;

if ($run_tests) {
    note("one test");
    test_x();
}
else { skip_test() }


sub test_x { ok( 1, "1 is ok" ) } 

sub skip_test {
    Test::More->builder->output('/dev/null');
    Test::More->builder->skip;
}

或者 reset,针对不同的情况或上下文

use warnings;
use strict;
use feature 'say';

use Test::More qw(no_plan);

my $run_tests = shift;

if ($run_tests) {
    note("one test");
    test_x();
}
else { Test::More->builder->reset }
    
# At the very end of the program (not in END block though)
done_testing if $run_tests;

sub test_x { ok( 1, "1 is ok" ) } 

我们现在最好在最后使用 done_testing

当调用程序时不带任何参数时,所有这些都不打印任何内容并具有退出代码 0,或者当使用“true”参数调用时 运行 测试并打印消息。 全部使用(多于 1)个测试块进行测试,此处省略。

之所以需要处理上面的一些细节,是因为测试框架旨在用于专用程序,而不是用于测试 运行ning 程序中的部分。虽然也可以这样使用它,但有些事情会变得更加复杂。

请参阅 Test2, or perhaps its suite Test2::Suite,了解更新的替代方案。


也就是说,当传递给程序时,对于 Perl 来说是“真”,所以不是 0 或空字符串 "''"