1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
#!/usr/bin/env perl
#
# define.t
#
# Test cases for Test::Spec definitions
#
########################################################################
#
package Testcase::Spec::Define;
use strict;
use warnings;
use Test::Deep;
use Test::More tests => 18;
# builds a hash of "parent name" => { "child name" => ... }
sub build_context_tree {
my $node = shift;
my $tree = shift || {};
for my $ctx ($node->contexts) {
build_context_tree($ctx, $tree->{$ctx->name} = {});
}
return $tree;
}
{
package Stub;
sub new { bless do { \my $stub }, shift() }
sub AUTOLOAD { shift }
}
my ($outer,$inner) = (0,0);
my ($before_all,$before_each) = (0,0);
my ($after_all,$after_each) = (0,0);
my ($ctx_in_desc, $ctx_in_before, $ctx_in_after);
my $enter_leave_state = undef;
my ($on_enter,$on_leave) = (0,0);
{
package A;
use Test::Spec; # imports
use base qw(Test::Spec);
describe "Outer 1" => sub {
$outer++;
$ctx_in_desc = A->current_context;
before all => sub {
$before_all++;
$ctx_in_before = A->current_context;
};
before each => sub {
$before_each++;
};
it "runs outer test 1" => sub { ok(1, "ran outer test 1") };
describe "Inner 1" => sub {
$inner++;
A->current_context->on_enter(sub {
$enter_leave_state = 'ENTER';
$on_enter++;
});
A->current_context->on_leave(sub {
$enter_leave_state = 'LEAVE' if $enter_leave_state eq 'ENTER';
$on_leave++;
});
it "runs inner test 1" => sub { ok(1) };
};
after each => sub {
$after_each++;
$ctx_in_after = A->current_context;
};
after all => sub {
$after_all++;
};
};
context "Outer 1" => sub {
$outer++;
context "Inner 1" => sub {
$inner++;
};
context "Inner 2" => sub {
};
};
# tests
describe "Outer 2" => sub {
};
}
is( $outer, 2, "both outer blocks ran");
is( $inner, 2, "both inner blocks ran");
my $tree = build_context_tree('A');
is_deeply( $tree, {
"Outer 1" => { "Inner 1" => {}, "Inner 2" => {} },
"Outer 2" => {},
}, "contexts shallow-merged");
is( $before_all, 0, "before-all not run during definition" );
is( $before_each, 0, "before-all not run during definition" );
is( $after_each, 0, "after-each not run during definition" );
is( $after_all, 0, "after-all not run during definition" );
ok( $on_enter > 0, "enter block called");
is( $on_enter, $on_leave, "entered and left symmetrically" );
is( A->phase, Test::Spec::DEFINITION_PHASE, "definition phase" );
{
no warnings 'once';
my $stub = Stub->new;
local *A::builder = sub { $stub };
local *Test::More::builder = sub { $stub };
A->runtests;
}
is( A->phase, Test::Spec::EXECUTION_PHASE, "execution phase" );
is( $ctx_in_desc, $ctx_in_before,
"describe() and before() contexts are the same (for hooks, esp. mocks)");
is( $ctx_in_desc, $ctx_in_after,
"describe() and after() contexts are the same (for hooks, esp. mocks)");
is( $outer, 2, "describe blocks did not re-run");
is( $before_all, 1, "before-all ran once before all tests" );
is( $before_each, 2, "before-each ran before each test");
is( $after_each, 2, "after-each ran after each test");
TODO: {
local $TODO = "after-all untestable without changes to Spec.pm";
is($after_all, 1, "after-all ran once after all tests" );
}
|