Skip to content

Commit

Permalink
Add spec_defaults()
Browse files Browse the repository at this point in the history
This adds spec_defaults which allows you to specify default attributes
for blocks of a given type for any given build scope.

Fixes #6
Fixes #7
  • Loading branch information
exodist committed Jul 27, 2016
1 parent f8c61bb commit c6d1442
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 7 deletions.
2 changes: 2 additions & 0 deletions Changes
@@ -1,5 +1,7 @@
{{$NEXT}} {{$NEXT}}


- Add spec_defaults()

0.000014 2016-07-02 22:11:29-07:00 America/Los_Angeles 0.000014 2016-07-02 22:11:29-07:00 America/Los_Angeles


- No Changes from last trial - No Changes from last trial
Expand Down
95 changes: 91 additions & 4 deletions lib/Test2/Tools/Spec.pm
Expand Up @@ -3,7 +3,7 @@ use strict;
use warnings; use warnings;


use Carp qw/croak/; use Carp qw/croak/;
use Test2::Workflow qw/parse_args build current_build root_build init_root/; use Test2::Workflow qw/parse_args build current_build root_build init_root build_stack/;


use Test2::Workflow::Runner(); use Test2::Workflow::Runner();
use Test2::Workflow::Task::Action(); use Test2::Workflow::Task::Action();
Expand All @@ -13,7 +13,7 @@ use Importer();


use vars qw/@EXPORT @EXPORT_OK/; use vars qw/@EXPORT @EXPORT_OK/;
push @EXPORT => qw{describe cases}; push @EXPORT => qw{describe cases};
push @EXPORT_OK => qw{include_workflow include_workflows}; push @EXPORT_OK => qw{include_workflow include_workflows spec_defaults};


my %HANDLED; my %HANDLED;
sub import { sub import {
Expand Down Expand Up @@ -116,9 +116,12 @@ sub import {


sub describe { sub describe {
my @caller = caller(0); my @caller = caller(0);
my $build = build(args => \@_, caller => \@caller);


return $build if defined wantarray; my $want = wantarray;

my $build = build(args => \@_, caller => \@caller, stack_stop => defined $want ? 1 : 0);

return $build if defined $want;


my $current = current_build() || root_build($caller[0]) my $current = current_build() || root_build($caller[0])
or croak "No current workflow build!"; or croak "No current workflow build!";
Expand All @@ -140,6 +143,25 @@ sub include_workflow {
} }
} }


sub defaults {
my %params = @_;

my ($package, $tool) = @params{qw/package tool/};

my @stack = (root_build($package), build_stack());
return unless @stack;

my %out;
for my $build (@stack) {
%out = () if $build->stack_stop;
my $new = $build->defaults->{$tool} or next;
%out = (%out, %$new);
}

return \%out;
}


# Generate a bunch of subs that only have minor differences between them. # Generate a bunch of subs that only have minor differences between them.
BEGIN { BEGIN {
@EXPORT = qw{ @EXPORT = qw{
Expand Down Expand Up @@ -208,6 +230,20 @@ BEGIN {
around_each => [scaffold => 1, around => 1], around_each => [scaffold => 1, around => 1],
); );


sub spec_defaults {
my ($tool, %params) = @_;
my @caller = caller(0);

croak "'$tool' is not a spec tool"
unless exists $props{$tool} || exists $stages{$tool};

my $build = current_build() || root_build($caller[0])
or croak "No current workflow build!";

my $old = $build->defaults->{$tool} ||= {};
$build->defaults->{$tool} = { %$old, %params };
}

my $run = ""; my $run = "";
for my $func (@EXPORT, @EXPORT_OK) { for my $func (@EXPORT, @EXPORT_OK) {
$run .= <<" EOT"; $run .= <<" EOT";
Expand All @@ -222,6 +258,14 @@ sub $func {
my \$build = current_build() || root_build(\$caller[0]) my \$build = current_build() || root_build(\$caller[0])
or croak "No current workflow build!"; or croak "No current workflow build!";
if (my \$defaults = defaults(package => \$caller[0], tool => '$func')) {
for my \$attr (keys \%\$defaults) {
next if defined \$action->\$attr;
my \$sub = "set_\$attr";
\$action->\$sub(\$defaults->{\$attr});
}
}
\$build->\$_(\$action) for \@{\$stages{$func}}; \$build->\$_(\$action) for \@{\$stages{$func}};
} }
EOT EOT
Expand Down Expand Up @@ -524,6 +568,49 @@ Same as:
=back =back
=head2 CUSTOM ATTRIBUTE DEFAULTS
Sometimes you want to apply default attributes to all C<tests()> or C<case()>
blocks. This can be done, and is lexical to your describe or package root!
use Test2::Bundle::Extended;
use Test2::Tools::Spec ':ALL';
# All 'tests' blocks after this declaration will have C<<iso => 1>> by default
spec_defaults tests => (iso => 1);
tests foo => sub { ... }; # isolated
tests foo, {iso => 0}, sub { ... }; # Not isolated
spec_defaults tests => (iso => 0); # Turn it off again
Defaults are inherited by nested describe blocks. You can also override the
defaults for the scope of the describe:
spec_defaults tests => (iso => 1);
describe foo => sub {
spec_defaults tests => (async => 1); # Scoped to this describe and any child describes
tests bar => sub { ... }; # both iso and async
};
tests baz => sub { ... }; # Just iso, no async.
You can apply defaults to any type of blocks:
spec_defaults case => (iso => 1); # All cases are 'iso';
Defaults are not inherited when a builder's return is captured.
spec_defaults tests => (iso => 1);
# Note we are not calling this in void context, that is the key here.
my $d = describe foo => {
tests bar => sub { ... }; # Not iso
};
=head1 EXECUTION ORDER =head1 EXECUTION ORDER
As each function is encountered it executes, just like any other function. The As each function is encountered it executes, just like any other function. The
Expand Down
6 changes: 4 additions & 2 deletions lib/Test2/Workflow.pm
Expand Up @@ -4,7 +4,7 @@ use warnings;


our $VERSION = "0.000014"; our $VERSION = "0.000014";


our @EXPORT_OK = qw/parse_args current_build build root_build init_root/; our @EXPORT_OK = qw/parse_args current_build build root_build init_root build_stack/;
use base 'Exporter'; use base 'Exporter';


use Test2::Workflow::Build; use Test2::Workflow::Build;
Expand All @@ -19,6 +19,7 @@ sub parse_args {
my %props; my %props;


my $caller = $out{frame} = $input{caller} || caller(defined $input{level} ? $input{level} : 1); my $caller = $out{frame} = $input{caller} || caller(defined $input{level} ? $input{level} : 1);
delete @input{qw/caller level/};


for my $arg (@$args) { for my $arg (@$args) {
if (my $r = ref($arg)) { if (my $r = ref($arg)) {
Expand Down Expand Up @@ -54,7 +55,7 @@ sub parse_args {
die "a codeblock must be provided at $caller->[1] line $caller->[2].\n" die "a codeblock must be provided at $caller->[1] line $caller->[2].\n"
unless $out{code}; unless $out{code};


return { %props, %out }; return { %props, %out, %input };
} }


{ {
Expand All @@ -63,6 +64,7 @@ sub parse_args {


sub root_build { $ROOT_BUILDS{$_[0]} } sub root_build { $ROOT_BUILDS{$_[0]} }
sub current_build { @BUILD_STACK ? $BUILD_STACK[-1] : undef } sub current_build { @BUILD_STACK ? $BUILD_STACK[-1] : undef }
sub build_stack { @BUILD_STACK }


sub init_root { sub init_root {
my ($pkg, %args) = @_; my ($pkg, %args) = @_;
Expand Down
3 changes: 2 additions & 1 deletion lib/Test2/Workflow/Build.pm
Expand Up @@ -17,7 +17,7 @@ BEGIN {
} }


use base 'Test2::Workflow::Task'; use base 'Test2::Workflow::Task';
use Test2::Util::HashBase @BUILD_FIELDS, qw/events/; use Test2::Util::HashBase @BUILD_FIELDS, qw/events defaults stack_stop/;


sub init { sub init {
my $self = shift; my $self = shift;
Expand All @@ -28,6 +28,7 @@ sub init {
} }


$self->{$_} ||= [] for @BUILD_FIELDS; $self->{$_} ||= [] for @BUILD_FIELDS;
$self->{+DEFAULTS} ||= {};
} }


for my $field (@BUILD_FIELDS) { for my $field (@BUILD_FIELDS) {
Expand Down

0 comments on commit c6d1442

Please sign in to comment.