【问题标题】:How can I test that a Perl program compiles from my test suite?如何测试从我的测试套件编译的 Perl 程序?
【发布时间】:2009-06-29 22:44:45
【问题描述】:

我正在为一些 Perl 脚本构建回归系统(不是单元测试)。

系统的核心组件是

  `perl script.pl @params 1>stdoutfile 2>stderrfile`;

但是,在实际编写脚本的过程中,它们有时无法编译(震惊!)。但是 perl 本身会正确执行。但是,我不知道如何在 stderr 上检测 Perl 是否无法编译(因此写入 stderr),或者我的脚本是否输入错误(因此写入 stderr)。

如何检测程序是否执行,而不用详尽地查找 Perl 错误消息和 grep 标准错误文件?

【问题讨论】:

    标签: perl testing


    【解决方案1】:

    这可能是最简单的两步:

    system('$^X -c script.pl');
    if ($? == 0) {
        # it compiled, now let's see if it runs
        system('$^X script.pl', @params, '1>stdoutfile', '2>stderrfile');
        # check $?
    }
    else {
        warn "script.pl didn't compile";
    }
    

    注意使用$^X 而不是perl。这更加灵活和健壮。它确保您从相同的安装运行,而不是在您的路径中首先出现的任何解释器。系统调用将继承您的环境(包括 PERL5LIB),因此生成不同版本的 perl 可能会导致难以诊断的兼容性错误。

    【讨论】:

    • 您应该始终使用 $^X。几乎每次我使用它时,我都会被硬编码的“perl”咬住。问题是子进程继承了您的 PERL5LIB,这对于 PATH 中的第一个 perl 可能是错误的。这样你最终会遇到奇怪的库不匹配错误。
    • 嘿。太丑了虽然它并不总是很重要(Windows 用户不太可能安装多个版本的 Perl),但使用 $^X 永远不会有害。我会相应地更新答案。
    • @Michael Carman Ah-em ... 我有 Cygwin、Strawberry 和 ActiveState Perl 以及我使用 VC Express 从头开始​​编译的一个。
    • @Sinan Unur:我也有几个版本,但我认为这让我们处于少数。
    【解决方案2】:

    当我想检查程序是否编译时,我会检查它是否编译:)

    这是我放入 t/compile.t 以与我的测试套件的其余部分一起运行的内容。如果脚本没有编译,它会停止所有的“bail out”测试:

    使用 Test::More 测试 => 1; 我的 $file = '...'; print "救命!脚本文件丢失!"除非 -e $file; 我的 $output = `$^X -c $file 2>&1`; print "救命!脚本文件无法编译!" 除非 like($output, qr/syntax OK$/, 'script compiles');

    【讨论】:

    • Test::More 有一个 BAIL_OUT() 函数。
    【解决方案3】:

    众所周知,脚本很难测试。你必须运行它们,然后刮掉它们的输出。你不能对他们的胆量进行单元测试......或者你可以吗?

    #!/usr/bin/perl -w
    
    # Only run if we're the file being executed by Perl
    main() if $0 eq __FILE__;
    
    sub main {
        ...your code here...
    }
    
    1;
    

    现在您可以像加载任何其他库一样加载脚本了。

    #!/usr/bin/perl -w
    
    use Test::More;
    
    require_ok("./script.pl");
    

    您甚至可以运行和测试 main()。 Test::Output 便于捕获输出。您可以说local @ARGV 来控制参数,或者您可以更改main() 以将@ARGV 作为参数(推荐)。

    然后您可以开始将 main() 拆分为更小的例程,您可以轻松地进行单元测试。

    【讨论】:

    • 问题是,我不想编辑脚本。这是一种黑盒测试方法,而不是单元测试方法(它有自己的时间和地点)。
    • 你不只是在做黑盒。通过命令行测试程序,您正在进行高级验收测试。只是高水平的验收测试。这些测试更难编写,因为您必须通过大量中间代码来测试所有内容。当出现问题时,它可能是 9381 件事中的任何一件。您在编码时失去了很多测试的好处。你已经说过你正在编写脚本,所以这不是一成不变的。最后,我想为您提供另一种方法,而不仅仅是其他人答案的变体。
    【解决方案4】:

    看看$? 变量。

    来自perldoc perlvar

    最后一个管道返回的状态 关闭,反引号(“``”)命令, 成功调用 wait() 或 waitpid(),或者来自 system() 操作员。这只是16位 返回的状态字 传统的 Unix wait() 系统调用 (或者被编成看起来像它)。 因此,子进程的退出值 真的是 ("$? >> 8"),和 "$? & 127" 给出哪个信号,如果有的话, 进程死了,“$?& 128” 报告是否存在核心转储。

    【讨论】:

    • 但是 $?从 perlscript 返回结果? Perl 的返回值是什么 - 我用谷歌搜索时找不到它。
    • 也可以。如果要检查脚本是否编译,请运行 perl -c script.pl 并测试 $? == 0。
    【解决方案5】:

    听起来你需要IPC::Open3

    【讨论】:

      猜你喜欢
      • 2020-12-13
      • 2013-02-23
      • 2013-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-09
      • 2015-09-29
      相关资源
      最近更新 更多