如何调试Module :: Starter制作的模块?

5 testing perl

我正在练习使用Module :: Starter创建一个新模块.我为包编写了一些测试用例,有时它们运行正常.

但是我注意到有两个问题:

  • 当测试用例失败时,我想在正在测试的函数中放入一些print语句.我跑了make test,它只告诉我我的测试用例失败了,它没有显示我的打印输出,尽管我确实已经达到了打印语句.

  • 假设我有三个测试用例来测试一个函数,我在函数内部放了一个print语句,当测试用例运行时,它会报告三个测试用例中只有一个被运行.如果我删除print语句,则将运行所有三个测试用例.这是为什么?

这是我的代码:

# package declaration and stuff...
sub get_in {
  my ( $hash, @path ) = @_;
  my $ref = $hash;
  print 'lol'; # This is the troublesome print statement. Remove this statement and all three test cases will run and pass
  foreach (@path) {
    if ( ref($ref) eq 'HASH' && exists $ref->{$_} ) {
      $ref = $ref->{$_};
    } else {
      return undef;
    }
  }
  return $ref;
}
Run Code Online (Sandbox Code Playgroud)

这是测试用例:

use Test::More tests => 3;
use strict;
use warnings;
use diagnostics;
require_ok('Foo::Doc');
ok( Foo::Doc::get_in( { 'a' => { 'b' => { 'c' => 101 } } }, 'a', 'b', 'c' ) == 101 );
ok( @{ Foo::Doc::get_in( { 'a' => { 'b' => { 'c' => [ 1, 2, 3 ] } } }, 'a', 'b', 'c' ) } == @{ [ 1, 2, 3 ] } );
Run Code Online (Sandbox Code Playgroud)

zos*_*tay 7

您需要解决的测试以及您自己的问题本身存在一些问题.首先你的问题:

如果要在测试中显示输出,则需要显式打印到标准错误.作为最佳实践,您还需要输出前缀#.该测试::更多模块,提供了可用于轻松地做到这一点的工具.

my $got = Foo::Doc::get_in( { 'a' => { 'b' => { 'c' => 101 } } }, 'a', 'b', 'c' );
ok($got == 101); # you probably want is() instead, see below
diag("GOT $got"); # outputs "# GOT 101" or whatever to STDERR
Run Code Online (Sandbox Code Playgroud)

如果您不想每次都打印该输出,但仅在请求详细日志记录时,您可以使用note:

note("GOT $got");
Run Code Online (Sandbox Code Playgroud)

当您用于prove -v运行测试时,这非常有用:

prove -l -v t/test.t
Run Code Online (Sandbox Code Playgroud)

还有一个explain函数可以转储复杂的输出以供查看:

diag explain $got;
# OR
note explain $got;
Run Code Online (Sandbox Code Playgroud)

至于你的其他问题.通常最好is()用于ok():

is($got, 101); # gives slightly more readable output on error
Run Code Online (Sandbox Code Playgroud)

此外,在测试复杂的数据结构时,您需要使用它is_deeply()来进行完整的比较:

is_deeply($got, [1, 2, 3]);
Run Code Online (Sandbox Code Playgroud)

你一定要看一下Test :: More的文档,因为那里有很多有用的信息.