Skip to content

Instantly share code, notes, and snippets.

@jkeroes
Last active November 19, 2019 01:51
Show Gist options
  • Save jkeroes/797d1a6e11f2397fb6e86d51da5d9f57 to your computer and use it in GitHub Desktop.
Save jkeroes/797d1a6e11f2397fb6e86d51da5d9f57 to your computer and use it in GitHub Desktop.
Perl testing.md
# Testing
## SYNOPSIS
use Ndn::Test::Bundle -target => 'Ndn::Foo'; # Sets $CLASS to 'Ndn::Foo'
database dreamhost {
table foo {
row { col1 => 1, col2 => 2 };
row { col1 => 3, col2 => 4 };
}
table bar {
row { this => 'that' };
}
}
describe things {
tests a {
ok ...
};
tests b {
ok ...
};
};
done_testing;
## Fixtures
Running a unit test will automatically provision a sandboxed database and
create all the tables defined in Ndn::*. These tables will be empty. There
are a few different ways to insert data:
### database/table/row
any columns left unmentioned will be filled with mysql's notion of default values.
database people {
table person {
row { username => 'jdoe', first => 'John', last => 'Doe', status => 'dh2' };
row { ... };
}
}
### load_fixtures
load_fixtures people => (
person => [
{ username => 'jdoe', first => 'John', last => 'Doe', status => 'dh2' },
{ ... },
]
);
### using Ndn
my $Person = Ndn::People::Person->new(
{ username => 'jdoe', first => 'John', last => 'Doe', status => 'dh2' },
);
$Person->Save;
## Mocking time
use Test::MockTime qw(set_fixed_time);
$ENV{TZ} = 'Z';
set_fixed_time('2000-01-01T00:00:00Z');
## Coverage
Figuring out if you've tested all the things.
ndnperl current
cd ndn
cover -delete
# perl -Iperl -d:Cover perl/t/unit/path/to/file.t
# perl -Iperl -MDevel::Cover perl/t/unit/path/to/file.t
HARNESS_PERL_SWITCHES=-MDevel::Cover prove -lr **/Bronto.t **/BrontoEmail/basic.t
cover
## Profiler
HARNESS_PERL_SWITCHES=-MDevel::NYTProf prove -lr **/Bronto.t **/BrontoEmail/basic.t
## Test2
### Env vars
T2_WORKFLOW=$test_name yath ... # test single test/describe block.
T2_WORKFLOW_ASYNC=9 yath ... # run in 9 forks.
prove, perl, or yath all work the same way.
### Mock
my $mock = mock 'Some::Class' => (
add => [
new_method_name => sub { ... },
],
override => [
replacement_method_name => sub { ... },
],
);
### Output
note() - write to STDOUT; hidden under prove; shown with prove -v
diag() - write to STDERR; visible under prove and prove -v
### Exceptions
##### perldoc Test2::Tools::Exceptions
ok(lives { ... }, "did not die") or note($@);
like(
dies { die 'xxx' },
qr/xxx/,
"Got exception"
);
##### perldoc Test2::Tools::Warnings
ok ( warns { warn 'xxx' });
like(
warning { warn 'xxx' }, # works with carp, too.
qr/xxx/,
"Got warning"
);
like(
warnings { warn 'xxx' },
["Warning A", "Warning B"]
"Got warning"
);
### Comparisons
#### perldoc Test2::Tools::Compare
Test only some of the things in a hash:
is(
$hashref,
hash {
field this => 'value';
field that => hash {
field ...;
},
end;
},
"it matches!"
);
is(
$arrayref,
array {
item 'foo';
item 'bar';
end();
}
)
bag { } is like array { } but unordered.
subset { } is like array { } but ordered.
### case
describe is_corp {
my ($name, $company, $is_corp);
case both { $name = 1; $company = 1; $is_corp = 1 }
case just_name { $name = 1; $company = 0; $is_corp = 0 }
case just_company { $name = 0; $company = 1; $is_corp = 1 }
case neither { $name = 0; $company = 0; $is_corp = 0 }
tests old {
ok ($is_corp, ($name ? 0 : $company ? 1 : 0));
}
tests new {
ok ($is_corp, ($company ? 1 : 0));
}
}
### skip and todo
These can be added to any test block, ie describe, tests, subtest, etc.
Skips this block when $when is true:
describe block_name { skip => $when } {
tests unit_name { pass() };
};
A TODO will run the test block but consider any failures to be okay.
The $reason should explain why it's okay for these tests to be in a
failing state.
describe block_name { todo => $reason } {
tests unit_name { fail() };
};
### skip unless...
Requires that a certain environment variable be set:
use Test2::Require::EnvVar 'LIVE_API_TESTING';
Requires that a certain module be present:
use Test2::Require::Module 'Some::Module';
Requires that v5.555 or better of Other::Module be installed.
use Test2::Require::Module 'Other::Module' => '5.555';
## Old perl testing
For testing code on controllers. The Jenkins machines, serf5353 and snafu, have
the controllers' set of modules as well as some extra test modules. They're just
special that way.
serf5353 runs the Jenkins ndn-syntax-check-env job for envperl.
snafu runs the Jenkins ndn-syntax-check job for oldperl.
These modules are known to exist of serf5353 and snafu.
use Test::More; # subtest "..." => sub { ... }; is(); ok();
use Test::Fatal; # like(exception { dies() }, qr/.../, "..."); # available on serf5353 only.
use Test::Warn; # warning_like(), warning_ok()
use Test::Deep; # cmp_deeply(), bag(), subset(), superhashof(),
use Test::Exception; # works on snafu but crappier than Test::Fatal.
use Mock::Quick;
qtakeover $class => (
$subname => sub { ... },
);
use Capture::Tiny;
my ($stdout, $stderr, $exit) = capture { ... };
my Capture::Tiny qw/capture_stdout capture_stderr/;
my $stdout = capture_stdout { ... };
my $stderr = capture_stderr { ... };
cmp_deeply(
$hash,
superhashof(
this => ignore(),
that => ignore(),
other => 'foo',
),
"explained"
);
cmp_deeply(
$ary,
superbagof( # order does not matter.
'foo',
'bar',
)
);
SKIP: {
skip $why, $how_many unless $boolean;
ok ...
...
};
TODO: { ... }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment