Hello community, here is the log from the commit of package perl-Test-Spec for openSUSE:Factory checked in at 2015-04-22 01:18:32 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/perl-Test-Spec (Old) and /work/SRC/openSUSE:Factory/.perl-Test-Spec.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-Test-Spec" Changes: -------- --- /work/SRC/openSUSE:Factory/perl-Test-Spec/perl-Test-Spec.changes 2015-04-15 16:25:08.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.perl-Test-Spec.new/perl-Test-Spec.changes 2015-04-22 01:18:35.000000000 +0200 @@ -1,0 +2,12 @@ +Mon Apr 20 09:12:17 UTC 2015 - [email protected] + +- updated to 0.50 + see /usr/share/doc/packages/perl-Test-Spec/Changes + + 0.50 Sun Apr 19 18:13:00 BST 2015 + - Removed several memory leaks + Reported by @JRaspass (issue #24) + - any_number() no longer fails if it is never called + Contributed by @ptolemarch and @cavemanpi (issue #25) + +------------------------------------------------------------------- Old: ---- Test-Spec-0.49.tar.gz New: ---- Test-Spec-0.50.tar.gz cpanspec.yml ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ perl-Test-Spec.spec ++++++ --- /var/tmp/diff_new_pack.z2C5GX/_old 2015-04-22 01:18:36.000000000 +0200 +++ /var/tmp/diff_new_pack.z2C5GX/_new 2015-04-22 01:18:36.000000000 +0200 @@ -17,14 +17,15 @@ Name: perl-Test-Spec -Version: 0.49 +Version: 0.50 Release: 0 %define cpan_name Test-Spec Summary: Write tests in a declarative specification style License: Artistic-1.0 or GPL-1.0+ Group: Development/Libraries/Perl Url: http://search.cpan.org/dist/Test-Spec/ -Source: http://www.cpan.org/authors/id/P/PH/PHILIP/%{cpan_name}-%{version}.tar.gz +Source0: http://www.cpan.org/authors/id/A/AN/ANDYJONES/%{cpan_name}-%{version}.tar.gz +Source1: cpanspec.yml BuildArch: noarch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: perl @@ -72,6 +73,6 @@ %files -f %{name}.files %defattr(-,root,root,755) -%doc Changes README +%doc Changes README.md %changelog ++++++ Test-Spec-0.49.tar.gz -> Test-Spec-0.50.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/Changes new/Test-Spec-0.50/Changes --- old/Test-Spec-0.49/Changes 2015-01-18 19:01:51.000000000 +0100 +++ new/Test-Spec-0.50/Changes 2015-04-19 19:15:56.000000000 +0200 @@ -1,5 +1,11 @@ Revision history for Perl extension Test::Spec. +0.50 Sun Apr 19 18:13:00 BST 2015 + - Removed several memory leaks + Reported by @JRaspass (issue #24) + - any_number() no longer fails if it is never called + Contributed by @ptolemarch and @cavemanpi (issue #25) + 0.49 Sun Jan 18 12:56:00 EST 2015 - Added with_deep Contributed by Andy Jones (issue #21) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/MANIFEST new/Test-Spec-0.50/MANIFEST --- old/Test-Spec-0.49/MANIFEST 2015-01-18 19:03:18.000000000 +0100 +++ new/Test-Spec-0.50/MANIFEST 2015-04-19 19:46:53.000000000 +0200 @@ -2,11 +2,13 @@ Changes lib/Test/Spec.pm lib/Test/Spec/Context.pm +lib/Test/Spec/Example.pm lib/Test/Spec/Mocks.pm lib/Test/Spec/SharedHash.pm +lib/Test/Spec/TodoExample.pm Makefile.PL MANIFEST -README +README.md t/another_shared_examples_spec.pl t/auto_inherit.t t/data_sharing.t @@ -21,6 +23,8 @@ t/mocks.t t/mocks_imports.t t/perl_warning_spec.pl +t/predictable_destroy.pl +t/predictable_destroy_spec.t t/runtests_subset.t t/shared_examples.t t/shared_examples_spec.pl diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/META.json new/Test-Spec-0.50/META.json --- old/Test-Spec-0.49/META.json 2015-01-18 19:03:18.000000000 +0100 +++ new/Test-Spec-0.50/META.json 2015-04-19 19:46:53.000000000 +0200 @@ -4,7 +4,7 @@ "Philip Garrett <[email protected]>" ], "dynamic_config" : 1, - "generated_by" : "ExtUtils::MakeMaker version 6.98, CPAN::Meta::Converter version 2.143240", + "generated_by" : "ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120630", "license" : [ "perl_5" ], @@ -19,33 +19,6 @@ "inc" ] }, - "prereqs" : { - "build" : { - "requires" : { - "ExtUtils::MakeMaker" : "0" - } - }, - "configure" : { - "requires" : { - "ExtUtils::MakeMaker" : "0" - } - }, - "runtime" : { - "requires" : { - "Carp" : "0", - "Exporter" : "0", - "List::Util" : "0", - "Package::Stash" : "0.23", - "Scalar::Util" : "1.11", - "TAP::Parser" : "0", - "Test::Deep" : "0.103", - "Test::More" : "0.88", - "Test::Trap" : "0", - "Tie::IxHash" : "0", - "constant" : "0" - } - } - }, "release_status" : "stable", "resources" : { "bugtracker" : { @@ -57,5 +30,5 @@ "web" : "https://github.com/kingpong/perl-Test-Spec" } }, - "version" : "0.49" + "version" : "0.50" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/META.yml new/Test-Spec-0.50/META.yml --- old/Test-Spec-0.49/META.yml 2015-01-18 19:03:18.000000000 +0100 +++ new/Test-Spec-0.50/META.yml 2015-04-19 19:46:53.000000000 +0200 @@ -2,34 +2,19 @@ abstract: 'Write tests in a declarative specification style' author: - 'Philip Garrett <[email protected]>' -build_requires: - ExtUtils::MakeMaker: '0' -configure_requires: - ExtUtils::MakeMaker: '0' +build_requires: {} dynamic_config: 1 -generated_by: 'ExtUtils::MakeMaker version 6.98, CPAN::Meta::Converter version 2.143240' +generated_by: 'ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120630' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html - version: '1.4' + version: 1.4 name: Test-Spec no_index: directory: - t - inc -requires: - Carp: '0' - Exporter: '0' - List::Util: '0' - Package::Stash: '0.23' - Scalar::Util: '1.11' - TAP::Parser: '0' - Test::Deep: '0.103' - Test::More: '0.88' - Test::Trap: '0' - Tie::IxHash: '0' - constant: '0' resources: bugtracker: https://github.com/kingpong/perl-Test-Spec/issues repository: https://github.com/kingpong/perl-Test-Spec -version: '0.49' +version: 0.50 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/README new/Test-Spec-0.50/README --- old/Test-Spec-0.49/README 2015-01-07 04:15:27.000000000 +0100 +++ new/Test-Spec-0.50/README 1970-01-01 01:00:00.000000000 +0100 @@ -1,55 +0,0 @@ -Test::Spec -========== - -This is a declarative specification‐style testing system for behavior‐ -driven development (BDD) in Perl. The tests (a.k.a. examples) are named -with strings instead of subroutine names, so your fingers will suffer -less fatigue from underscore−itis, with the side benefit that the test -reports are more legible. - -This module is inspired by and borrows heavily from RSpec -(http://rspec.info/documentation/), a BDD tool for the Ruby programming -language. - -See `perldoc Test::Spec` for syntax examples and usage information. - -INSTALLATION - -To install this module type the following: - - perl Makefile.PL - make - make test - make install - -DEPENDENCIES - -This module requires these other modules and libraries: - - * constant - * List::Util - * Package::Stash (>= 0.23) - * Scalar::Util (XS version) - * TAP::Parser - * Test::Deep (>= 0.103) - * Test::More - * Test::Trap - * Tie::IxHash - -AUTHOR - -Philip Garrett <[email protected]> - -SOURCE CODE - -The source code for Test::Spec lives at github: - https://github.com/kingpong/perl-Test-Spec - -COPYRIGHT AND LICENSE - -Copyright (C) 2011 by Informatics Corporation of America. - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself, either Perl version 5.8.8 or, -at your option, any later version of Perl 5 you may have available. - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/README.md new/Test-Spec-0.50/README.md --- old/Test-Spec-0.49/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/Test-Spec-0.50/README.md 2015-03-15 21:40:31.000000000 +0100 @@ -0,0 +1,55 @@ +Test::Spec  +========== + +Test::Spec is a declarative specification‐style testing system for behavior‐ +driven development (BDD) in Perl. The tests (a.k.a. examples) are named +with strings instead of subroutine names, so your fingers will suffer +less fatigue from underscore−itis, with the side benefit that the test +reports are more legible. + +This module is inspired by and borrows heavily from RSpec +(http://rspec.info/documentation/), a BDD tool for the Ruby programming +language. + +See `perldoc Test::Spec` for syntax examples and usage information. + +Installation +------------ +To install this module type the following: + + perl Makefile.PL + make + make test + make install + +Dependencies +------------ +This module requires these other modules and libraries: + + * constant + * List::Util + * Package::Stash (>= 0.23) + * Scalar::Util (XS version) + * TAP::Parser + * Test::Deep (>= 0.103) + * Test::More + * Test::Trap + * Tie::IxHash + +Author +------ +Philip Garrett <[email protected]> + +Source Code +----------- +The source code for Test::Spec lives at github: + https://github.com/kingpong/perl-Test-Spec + +Copyright and License +--------------------- +Copyright (c) 2011 by Informatics Corporation of America. +Copyright (c) 2015 by Philip Garrett. + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.8.8 or, +at your option, any later version of Perl 5 you may have available. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/lib/Test/Spec/Context.pm new/Test-Spec-0.50/lib/Test/Spec/Context.pm --- old/Test-Spec-0.49/lib/Test/Spec/Context.pm 2012-01-31 00:36:02.000000000 +0100 +++ new/Test-Spec-0.50/lib/Test/Spec/Context.pm 2015-04-19 19:10:20.000000000 +0200 @@ -11,12 +11,15 @@ use Scalar::Util (); use Test::More (); use Test::Spec qw(*TODO $Debug :constants); +use Test::Spec::Example; +use Test::Spec::TodoExample; our $_StackDepth = 0; sub new { my $class = shift; my $self = bless {}, $class; + if (@_) { my $args = shift; if (@_ || ref($args) ne 'HASH') { @@ -27,17 +30,19 @@ } } + my $this = $self; + Scalar::Util::weaken($this); $self->on_enter(sub { - $self->_debug(sub { - printf STDERR "%s[%s]\n", ' ' x $_StackDepth, $self->_debug_name; + $this && $this->_debug(sub { + printf STDERR "%s[%s]\n", ' ' x $_StackDepth, $this->_debug_name; $_StackDepth++; }); }); $self->on_leave(sub { - $self->_debug(sub { + $this && $this->_debug(sub { $_StackDepth--; - printf STDERR "%s[/%s]\n", ' ' x $_StackDepth, $self->_debug_name; + printf STDERR "%s[/%s]\n", ' ' x $_StackDepth, $this->_debug_name; }); }); @@ -283,109 +288,28 @@ my $description = $self->_concat((map { $_->name } @context_stack), $t->{name}); my $test_number = 1 + scalar($self->class->tests); my $sub_name = sprintf $format, $test_number, $self->_make_safe($description); - my $fq_name = $self->class . '::' . $sub_name; # create a test subroutine in the correct package - no strict 'refs'; - *{$fq_name} = sub { - if (!$t->{code} || $t->{todo}) { - my $builder = $self->_builder; - local $TODO = $t->{todo} || "(unimplemented)"; - $builder->todo_start($TODO); - $builder->ok(1, $description); - $builder->todo_end(); - } - else { - # copy these, because they'll be needed in a callback with its own @_ - my @test_args = @_; - - # clobber Test::Builder's ok() method just like Test::Class does, - # but without screwing up underscores. - no warnings 'redefine'; - my $orig_builder_ok = \&Test::Builder::ok; - local *Test::Builder::ok = sub { - my ($builder,$test,$desc) = splice(@_,0,3); - $desc ||= $description; - local $Test::Builder::Level = $Test::Builder::Level+1; - $orig_builder_ok->($builder, $test, $desc, @_); - }; - - # This recursive closure essentially does this - # $outer->contextualize { - # $outer->before_each - # $inner->contextualize { - # $inner->before_each - # $anon->contextualize { - # $anon->before_each (no-op) - # execute test - # $anon->after_each (no-op) - # } - # $inner->after_each - # } - # $outer->after_each - # } - # - my $runner; - $runner = sub { - my ($ctx,@remainder) = @_; - $ctx->contextualize(sub { - $ctx->_run_before_all_once; - $ctx->_run_before('each'); - if ($ctx == $self) { - $self->_in_anonymous_context(sub { $t->{code}->(@test_args) }); - } - else { - $runner->(@remainder); - } - $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. - }); - }; - eval { $runner->(@context_stack) }; - if (my $err = $@) { - my $builder = $self->_builder; - # eval in case stringification overload croaks - chomp($err = eval { $err . '' } || 'unknown error'); - my ($file,$line); - ($file,$line) = ($1,$2) if ($err =~ s/ at (.+?) line (\d+)\.\Z//); - - # disable ok()'s diagnostics so we can generate a custom TAP message - my $old_diag = $builder->no_diag; - $builder->no_diag(1); - # make sure we can restore no_diag - eval { $builder->ok(0, $description) }; - my $secondary_err = $@; - # no_diag needs a defined value, so double-negate it to get either '' or 1 - $builder->no_diag(!!$old_diag); - - unless ($builder->no_diag) { - # emulate Test::Builder::ok's diagnostics, but with more details - my ($msg,$diag_fh); - if ($builder->in_todo) { - $msg = "Failed (TODO)"; - $diag_fh = $builder->todo_output; - } - else { - $msg = "Failed"; - $diag_fh = $builder->failure_output; - } - print {$diag_fh} "\n" if $ENV{HARNESS_ACTIVE}; - print {$builder->failure_output} qq[# $msg test '$description' by dying:\n]; - print {$builder->failure_output} qq[# $err\n]; - print {$builder->failure_output} qq[# at $file line $line.\n] if defined($file); - } - die $secondary_err if $secondary_err; - } - } - - $self->_debug(sub { print STDERR "\n" }); - }; + my $example; + if (!$t->{code} || $t->{todo}) { + $example = Test::Spec::TodoExample->new({ + name => $sub_name, + reason => $t->{tdoo}, + description => $description, + builder => $self->_builder, + }); + } + else { + $example = Test::Spec::Example->new({ + name => $sub_name, + description => $description, + code => $t->{code}, + context => $self, + builder => $self->_builder, + }); + } - $self->class->add_test($sub_name); + $self->class->add_test($example); } # recurse to child contexts diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/lib/Test/Spec/Example.pm new/Test-Spec-0.50/lib/Test/Spec/Example.pm --- old/Test-Spec-0.49/lib/Test/Spec/Example.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/Test-Spec-0.50/lib/Test/Spec/Example.pm 2015-04-19 19:10:20.000000000 +0200 @@ -0,0 +1,145 @@ +package Test::Spec::Example; + +# Purpose: represents an `it` block + +use strict; +use warnings; + +######################################################################## +# NO USER-SERVICEABLE PARTS INSIDE. +######################################################################## + +use Carp (); +use Scalar::Util (); + +sub new { + my ($class, $args) = @_; + + if (!$args || ref($args) ne 'HASH') { + Carp::croak "usage: $class->new(\\%args)"; + } + + my $self = bless {}, $class; + foreach my $attr ( qw/name description code builder context/ ) { + $self->{$attr} = $args->{$attr} || Carp::croak "$attr missing"; + } + + Scalar::Util::weaken($self->{context}); + + return $self; +} + +sub name { shift->{name} } +sub description { shift->{description} } +sub code { shift->{code} } +sub builder { shift->{builder} } +sub context { shift->{context} } + +# Build a stack from the starting context +# down to the current context +sub stack { + my ($self) = @_; + + my $ctx = $self->context; + + my @ancestors = $ctx; + while ( $ctx = $ctx->parent ) { + push @ancestors, $ctx; + } + + return reverse(@ancestors); +} + +sub run { + my ($self) = @_; + + # clobber Test::Builder's ok() method just like Test::Class does, + # but without screwing up underscores. + no warnings 'redefine'; + my $orig_builder_ok = \&Test::Builder::ok; + local *Test::Builder::ok = sub { + my ($builder,$test,$desc) = splice(@_,0,3); + $desc ||= $self->description; + local $Test::Builder::Level = $Test::Builder::Level+1; + $orig_builder_ok->($builder, $test, $desc, @_); + }; + + # Run the test + eval { $self->_runner($self->stack) }; + + # And trap any errors + if (my $err = $@) { + my $builder = $self->builder; + my $description = $self->description; + + # eval in case stringification overload croaks + chomp($err = eval { $err . '' } || 'unknown error'); + my ($file,$line); + ($file,$line) = ($1,$2) if ($err =~ s/ at (.+?) line (\d+)\.\Z//); + + # disable ok()'s diagnostics so we can generate a custom TAP message + my $old_diag = $builder->no_diag; + $builder->no_diag(1); + # make sure we can restore no_diag + eval { $builder->ok(0, $description) }; + my $secondary_err = $@; + # no_diag needs a defined value, so double-negate it to get either '' or 1 + $builder->no_diag(!!$old_diag); + + unless ($builder->no_diag) { + # emulate Test::Builder::ok's diagnostics, but with more details + my ($msg,$diag_fh); + if ($builder->in_todo) { + $msg = "Failed (TODO)"; + $diag_fh = $builder->todo_output; + } + else { + $msg = "Failed"; + $diag_fh = $builder->failure_output; + } + print {$diag_fh} "\n" if $ENV{HARNESS_ACTIVE}; + print {$builder->failure_output} qq[# $msg test '$description' by dying:\n]; + print {$builder->failure_output} qq[# $err\n]; + print {$builder->failure_output} qq[# at $file line $line.\n] if defined($file); + } + die $secondary_err if $secondary_err; + } +} + +sub _runner { + my ($self, $ctx, @remainder) = @_; + + # This recursive closure essentially does this + # $outer->contextualize { + # $outer->before_each + # $inner->contextualize { + # $inner->before_each + # $anon->contextualize { + # $anon->before_each (no-op) + # execute test + # $anon->after_each (no-op) + # } + # $inner->after_each + # } + # $outer->after_each + # } + # + return $ctx->contextualize(sub { + $ctx->_run_before_all_once; + $ctx->_run_before('each'); + if ( @remainder ) { + $self->_runner(@remainder); + } + else { + $ctx->_in_anonymous_context($self->code); + } + $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. + }); +} + +1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/lib/Test/Spec/Mocks.pm new/Test-Spec-0.50/lib/Test/Spec/Mocks.pm --- old/Test-Spec-0.49/lib/Test/Spec/Mocks.pm 2015-01-18 19:01:51.000000000 +0100 +++ new/Test-Spec-0.50/lib/Test/Spec/Mocks.pm 2015-04-19 19:11:45.000000000 +0200 @@ -302,6 +302,7 @@ sub _check_eq_args { my $self = shift; return unless defined $self->_eq_args; + return unless $self->_call_count; if (!defined $self->_given_args || scalar(@{$self->_eq_args}) != scalar(@{$self->_given_args})) { return "Number of arguments don't match expectation"; @@ -330,6 +331,7 @@ sub _check_deep_args { my $self = shift; return unless defined $self->_deep_args; + return unless $self->_call_count; my @got = $self->_given_args; my @expected = $self->_deep_args; @@ -994,7 +996,7 @@ =item any_number -Configures the mocked method so that it can be called any number of times. +Configures the mocked method so that it can be called zero or more times. =item times diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/lib/Test/Spec/TodoExample.pm new/Test-Spec-0.50/lib/Test/Spec/TodoExample.pm --- old/Test-Spec-0.49/lib/Test/Spec/TodoExample.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/Test-Spec-0.50/lib/Test/Spec/TodoExample.pm 2015-04-19 19:10:20.000000000 +0200 @@ -0,0 +1,40 @@ +package Test::Spec::TodoExample; + +# Purpose: represents a `xit` block (ie. a pending/todo test) + +use strict; +use warnings; + +use Test::Spec qw(*TODO); + +sub new { + my ($class, $args) = @_; + + my $self = bless {}, $class; + $self->{name} = $args->{name}; + $self->{description} = $args->{description}; + $self->{reason} = $args->{reason} || '(unimplemented)'; + $self->{builder} = $args->{builder}; + + return $self; +} + +# Attributes +sub name { shift->{name} } +sub description { shift->{description} } +sub reason { shift->{reason} } +sub builder { shift->{builder} } + +# Methods +sub run { + my ($self) = @_; + + local $TODO = $self->reason; + my $builder = $self->builder; + + $builder->todo_start($TODO); + $builder->ok(1, $self->description); # XXX: could fail the TOOD (or even run it?) + $builder->todo_end(); +} + +1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/lib/Test/Spec.pm new/Test-Spec-0.50/lib/Test/Spec.pm --- old/Test-Spec-0.49/lib/Test/Spec.pm 2015-01-18 19:01:51.000000000 +0100 +++ new/Test-Spec-0.50/lib/Test/Spec.pm 2015-04-19 19:13:07.000000000 +0200 @@ -3,7 +3,7 @@ use warnings; use Test::Trap (); # load as early as possible to override CORE::exit -our $VERSION = '0.49'; +our $VERSION = '0.50'; use base qw(Exporter); @@ -26,11 +26,10 @@ constants => [qw(DEFINITION_PHASE EXECUTION_PHASE)] ); our $_Current_Context; -our $_Package_Contexts = _ixhash(); +our %_Package_Contexts; our %_Package_Phase; our %_Package_Tests; - -our $_Shared_Example_Groups = {}; +our %_Shared_Example_Groups; # Avoid polluting the Spec namespace by loading these other modules into # what's essentially a mixin class. When you write "use Test::Spec", @@ -128,10 +127,11 @@ $class->_materialize_tests; $class->phase(EXECUTION_PHASE); - my @which = @_ ? @_ : + my @which = @_ ? @_ : $ENV{SPEC} ? ($ENV{SPEC}) : (); - return $class->_execute_tests( $class->_pick_tests(@which) ); + my @tests = $class->_pick_tests(@which); + return $class->_execute_tests( @tests ); } sub builder { @@ -143,7 +143,7 @@ my ($class,@matchers) = @_; my @tests = $class->tests; for my $pattern (@matchers) { - @tests = grep { $_ =~ /$pattern/i } @tests; + @tests = grep { $_->name =~ /$pattern/i } @tests; } return @tests; } @@ -151,8 +151,14 @@ sub _execute_tests { my ($class,@tests) = @_; for my $test (@tests) { - $class->can($test)->(); + $test->run(); } + + # Ensure we don't keep any references to user variables so they go out + # of scope in a predictable fashion. + %_Package_Tests = %_Package_Contexts = (); + + # XXX: this doesn't play nicely with Test::NoWarnings and friends $class->builder->done_testing; } @@ -197,7 +203,7 @@ $container = $_Current_Context->context_lookup; } else { - $container = $_Package_Contexts->{$package} ||= _ixhash(); + $container = $_Package_Contexts{$package} ||= {}; } __PACKAGE__->_accumulate_examples({ @@ -245,7 +251,7 @@ } __PACKAGE__->_accumulate_examples({ - container => $_Shared_Example_Groups, + container => \%_Shared_Example_Groups, name => $name, class => undef, # shared examples are global code => $code, @@ -282,12 +288,9 @@ } } - # push a context onto the stack - local $_Current_Context = $context; - # evaluate the context function, which will set up lexical variables and # define tests and other contexts - $context->contextualize($code); + $context->contextualize($code); } # it_should_behave_like DESC @@ -299,7 +302,7 @@ if (!$_Current_Context) { Carp::croak "it_should_behave_like can only be used inside a describe or shared_examples_for context"; } - my $context = $_Shared_Example_Groups->{$name} || + my $context = $_Shared_Example_Groups{$name} || Carp::croak "unrecognized example group \"$name\""; # make a copy so we can assign the correct class name (via parent), @@ -380,7 +383,7 @@ sub _materialize_tests { my $class = shift; - my $contexts = $_Package_Contexts->{$class}; + my $contexts = $_Package_Contexts{$class}; if (not $contexts && %$contexts) { Carp::carp "no examples defined in spec package $class"; return; @@ -414,7 +417,7 @@ } else { my $name = ''; # unnamed context - return $_Package_Contexts->{$package}{$name} ||= + return $_Package_Contexts{$package}{$name} ||= Test::Spec::Context->new({ name => $name, class => $package, parent => undef }); } } @@ -426,7 +429,7 @@ sub contexts { my ($class) = @_; - my @ctx = values %{ $_Package_Contexts->{$class} || {} }; + my @ctx = values %{ $_Package_Contexts{$class} || {} }; return wantarray ? @ctx : \@ctx; } @@ -879,10 +882,10 @@ browser specification would be large, so putting the specs for all browsers in the same file would be a bad idea. So let's say we create C<all_browsers.pl> for the shared examples, and give Safari and Firefox -C<safari.t> and C<firefox.t>, respectively. +C<safari.t> and C<firefox.t>, respectively. The problem then becomes: how does the code in C<all_browsers.pl> access -the C<$browser> variable? In L<the example code|/shared_examples_for DESCRIPTION =E<gt> CODE>, +the C<$browser> variable? In L<the example code|/shared_examples_for DESCRIPTION =E<gt> CODE>, C<$browser> is a lexical variable that is in scope for all the examples. But once those examples are split into multiple files, you would have to use either package global variables or worse, come up with some other diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/t/mocks.t new/Test-Spec-0.50/t/mocks.t --- old/Test-Spec-0.49/t/mocks.t 2015-01-18 19:01:51.000000000 +0100 +++ new/Test-Spec-0.50/t/mocks.t 2015-04-19 19:10:20.000000000 +0200 @@ -288,6 +288,18 @@ is(scalar($expectation->problems), 0); }; + it "passes when expecting no arguments and never called" => sub { + $expectation->any_number->$with_method(); + # $stub->run(); # nope! + is(scalar($expectation->problems), 0); + }; + + it "passes when expecting one argument and never called" => sub { + $expectation->any_number->$with_method("Foo"); + # $stub->run(); # nope! + is(scalar($expectation->problems), 0); + }; + it "fails when expecting no arguments and one argument given" => sub { $expectation->$with_method(); $stub->run(1); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/t/predictable_destroy.pl new/Test-Spec-0.50/t/predictable_destroy.pl --- old/Test-Spec-0.49/t/predictable_destroy.pl 1970-01-01 01:00:00.000000000 +0100 +++ new/Test-Spec-0.50/t/predictable_destroy.pl 2015-04-19 19:10:20.000000000 +0200 @@ -0,0 +1,27 @@ +#!/usr/bin/env perl +# +# predictable_destroy.pl +# +# Objects should be destroyed in a predictable order during the RUN phase +# Expected to print out "DESTROYED IN RUN PHASE" +# +######################################################################## +# + +package Testcase::Spec::PredictableDestroy; +use Test::Spec; + +{ + package Foo; + sub new { bless {}, $_[0] } + sub DESTROY { warn("$_[0] DESTROYED IN ${^GLOBAL_PHASE}") } +}; + +describe "Test::Spec::Mocks" => sub { + my $x = Foo->new; + it "destroys objects in the run phase" => sub { + ok $x; + }; +}; + +runtests() unless caller; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Test-Spec-0.49/t/predictable_destroy_spec.t new/Test-Spec-0.50/t/predictable_destroy_spec.t --- old/Test-Spec-0.49/t/predictable_destroy_spec.t 1970-01-01 01:00:00.000000000 +0100 +++ new/Test-Spec-0.50/t/predictable_destroy_spec.t 2015-04-19 19:10:20.000000000 +0200 @@ -0,0 +1,29 @@ +#!/usr/bin/env perl +# +# predictable_destroy_spec.t +# +# Ensure we don't keep references around to objects so they +# are destroyed in a predictable order +# +######################################################################## +# + +package Testcase::Spec::PredictableDestroy; +use Test::Spec; + +use FindBin qw($Bin); +BEGIN { require "$Bin/test_helper.pl" }; + +describe "Test::Spec" => sub { + my $tap = capture_tap("predictable_destroy.pl"); + + it "destroys objects in the run phase" => sub { + unlike $tap => qr/DESTROYED IN DESTRUCT/; + }; + + it "avoids global destruction" => sub { + unlike $tap => qr/during global destruction/; + }; +}; + +runtests unless caller; ++++++ cpanspec.yml ++++++ --- #description_paragraphs: 3 #no_testing: broken upstream #sources: # - source1 # - source2 #patches: # foo.patch: -p1 # bar.patch: #preamble: |- # BuildRequires: gcc-c++ #post_prep: |- # hunspell=`pkg-config --libs hunspell | sed -e 's,-l,,; s, *,,g'` # sed -i -e "s,hunspell-X,$hunspell," t/00-prereq.t Makefile.PL #post_install: |- # sed on %{name}.files #license: SUSE-NonFree #skip_noarch: 1 #custom_build: - #./Build build flags=%{?_smp_mflags} --myflag #ignore_requires: Bizarre::Module
