在开发过程中我应该如何将 Perl 警告升级为致命错误?

发布于 2024-08-03 12:36:20 字数 748 浏览 4 评论 0原文

当运行应用程序测试套件时,我想将所有 Perl 编译和运行时警告(例如“未初始化的变量”警告)升级为致命错误,以便我和其他开发人员调查并修复生成警告的代码。但我只想在开发和 CI 测试期间这样做。在生产中,警告应该只是警告。

我尝试了以下操作: 在“t/lib”中,我创建了一个模块 TestHelper.pm:

# TestHelper.pm
use warnings FATAL => qw( all );
1;

然后像这样调用测试套件:

$ PERL5LIB=$PERL5LIB:./t/lib PERL5OPT=-MTestHelper.pm prove -l t/*.t

但这并没有达到将所有警告提升为致命错误的预期效果。我像平常一样收到警告,但这些警告似乎没有被视为致命的。请注意,我的所有 test.t 脚本都有“use warnings;”行在它们中——也许这会覆盖 TestHelper.pm 中的内容,因为“使用警告”具有本地范围?

相反,我这样做了:

# TestHelper.pm
# Promote all warnings to fatal 
$SIG{__WARN__} = sub { die @_; };
1;

这可行,但有代码味道。我也不喜欢它在第一次警告时就爆炸了。我宁愿测试套件完整运行,记录所有警告,但测试状态最终失败,因为代码运行时带有警告。

有没有更好的方法来达到这个最终结果?

When running an applications test suite I want to promote all Perl compile and run-time warnings (eg the "Uninitialized variable" warning) to fatal errors so that I and the other developers investigate and fix the code generating the warning. But I only want to do this during development and CI testing. In production, the warnings should just stay as warnings.

I tried the following: In "t/lib" I created a module TestHelper.pm:

# TestHelper.pm
use warnings FATAL => qw( all );
1;

Then called the test suite like this:

$ PERL5LIB=$PERL5LIB:./t/lib PERL5OPT=-MTestHelper.pm prove -l t/*.t

But this did not have the desired effect of promoting all warnings to fatal errors. I got the warnings as normal but the warnings did not appear to be treated as fatal. Note that all my test.t scripts have the line "use warnings;" in them -- perhaps this over-rides the one in TestHelper.pm because "use warnings" has a local scope?

Instead I've done this:

# TestHelper.pm
# Promote all warnings to fatal 
$SIG{__WARN__} = sub { die @_; };
1;

This works but has a code smell about it. I also don't like that it bombs out on the first warning. I'd rather the test suite ran in full, logging all warnings, but that the test status ultimately failed because the code ran with warnings.

Is there a better way to achieve this end result?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

¢好甜 2024-08-10 12:36:20

我认为您正在寻找 Test::NoWarnings

I think you're looking for Test::NoWarnings.

千鲤 2024-08-10 12:36:20

使用警告 FATAL => 的原因qw( all ); 不适合您,因为 use warnings 是词法范围的。因此,TestHelper.pm 内产生的任何警告都是致命的,但其他地方产生的警告将正常工作。

如果您想在全局范围内启用致命警告,我认为 $SIG{__WARN__} 处理程序可能是唯一的方法。如果您不希望它在第一次警告时爆炸,您可以让处理程序将它们存储在数组中,然后在 END 块中检查它。

my @WARNINGS;
$SIG{__WARN__} = sub { push @WARNINGS, shift };

END { 
    if ( @WARNINGS )  {       
        print STDERR "There were warnings!\n";
        print "$_\n" for @WARNINGS;
        exit 1;
    }
}

The reason use warnings FATAL => qw( all ); isn't working for you is because use warnings is lexically scoped. So any warnings produced inside TestHelper.pm would be fatal, but warnings produced elsewhere will work as normal.

If you want to enable fatal warnings globally, I think a $SIG{__WARN__} handler is probably the only way to do it. If you don't want it to blow up on the first warning, you could let your handler store them in an array, then check it in an END block.

my @WARNINGS;
$SIG{__WARN__} = sub { push @WARNINGS, shift };

END { 
    if ( @WARNINGS )  {       
        print STDERR "There were warnings!\n";
        print "$_\n" for @WARNINGS;
        exit 1;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文