Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion lib/Test/Spec.pm
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,10 @@ sub _pick_tests {

sub _execute_tests {
my ($class,@tests) = @_;
for my $test (@tests) {
for(my $i = 0; $i<=$#tests; $i++) {
my $test = $tests[$i];
$test->run();
$class->_cleanup_complete_contexts($i, $test, @tests);
}

# Ensure we don't keep any references to user variables so they go out
Expand All @@ -162,6 +164,33 @@ sub _execute_tests {
$class->builder->done_testing;
}

sub _cleanup_complete_contexts {
my($class, $i, $test, @tests) = @_;
return unless($test->can('stack'));
my(@stack) = $test->stack;
my $next_test;
for(my $n = $i+1; $n<=$#tests; $n++){
if($tests[$n]->isa('Test::Spec::Example')){
$next_test = $tests[$n];
last;
}
}
if($next_test){
my(@next_stack) = $next_test->stack;
my $n=0;
while($n <= $#next_stack && scalar(@stack) > 0 && $next_stack[$n] == $stack[0]){
shift @stack;
$n++;
}
}
foreach my $context (reverse @stack){
if ($context->_has_run_before_all) {
$context->_run_after_all_once;
}
}
}


# it DESC => CODE
# it CODE
# it DESC
Expand Down
14 changes: 1 addition & 13 deletions lib/Test/Spec/Context.pm
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,6 @@ sub clone {
return $clone;
}

# The reference we keep to our parent causes the garbage collector to
# destroy the innermost context first, which is what we want. If that
# becomes untrue at some point, it will be easy enough to descend the
# hierarchy and run the after("all") tests that way.
sub DESTROY {
my $self = shift;
# no need to tear down what was never set up
if ($self->_has_run_before_all) {
$self->_run_after_all_once;
}
}

sub name {
my $self = shift;
$self->{_name} = shift if @_;
Expand Down Expand Up @@ -424,7 +412,7 @@ sub contextualize {

#
# Copyright (c) 2010-2011 by Informatics Corporation of America.
#
#
# This program is free software; you can redistribute it and/or modify it
# under the same terms as Perl itself.
#
Expand Down
7 changes: 2 additions & 5 deletions lib/Test/Spec/Example.pm
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,8 @@ sub _runner {
$ctx->_in_anonymous_context($self->code, $self);
}
$ctx->_run_after('each');
# "after 'all'" only happens during context destruction (DEMOLISH).
# This is the only way I can think to make this work right
# in the case that only specific test methods are run.
# Otherwise, the global teardown would only happen when you
# happen to run the last test of the context.
# After all is handled by Spec.pm itself as it requires
# knowledge that crosses contexts.
}, $self);
}

Expand Down
1 change: 0 additions & 1 deletion t/disabled.t
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,3 @@ test_passed('Test::Spec should execute enabled "it" example');
test_passed('Test::Spec should execute enabled "they" example');

done_testing();

57 changes: 57 additions & 0 deletions t/run_after_spec.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use Test::Spec;
my($first_nested_after, $second_nested_after, $inner_after, $second_inner_after, $todo_after);

describe "outer describe block" => sub {
describe "inner block" => sub {
describe "first nested block" => sub {
it "runs first" => sub {
ok(! $first_nested_after ,"first nested block");
};
after all => sub {
$first_nested_after = 1;
ok(1, "after all - first nested block");
};
};
describe "second nested block" => sub {
it "first nested after has run by now" => sub {
ok($first_nested_after, "first nested after has run");
};
it "doesn't run second nest after until all it's have run" => sub {
ok(! $second_nested_after, "second nested after hasn't run yet")
};
after all => sub {
$second_nested_after = 1;
ok(1, "after all - second nested block");
};
};

after all => sub {
$inner_after = 1;
ok($second_nested_after, "second nested after has run");
};
};
describe "second inner" => sub {
it "inner block after has run" => sub {
ok($inner_after, "inner blocks after has run");
};
after all => sub {
$second_inner_after = 1;
ok(1, "after all - second inner");
}
};
xdescribe "TODO context" => sub {
it "shouldn't run the after all here" => sub {
ok(0);
};
after all => sub {
$todo_after = 1;
ok(0, "I should never run\n");
};
};
after all => sub {
ok(! $todo_after, "todo after block didn't run");
ok($second_inner_after, "second inner after has run");
};
};

runtests;