File Coverage

blib/lib/Test/Class/Sugar/CodeGenerator.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1 2     2   3192 use MooseX::Declare;
  0            
  0            
2              
3             class Test::Class::Sugar::CodeGenerator {
4             use Sub::Name;
5             use Carp qw/croak/;
6             use B::Hooks::EndOfScope;
7             our $VERSION = '0.0200';
8              
9             has name => (is => 'rw', isa => 'Str');
10             has plan => (is => 'rw');
11             has context => (is => 'rw');
12              
13             has options => (
14             is => 'ro',
15             isa => 'HashRef',
16             default => sub {{}},
17             );
18              
19             has classname => (
20             is => 'rw',
21             isa => 'Str',
22             lazy_build => 1,
23             );
24              
25             method _classname_prefix {
26             my $prefix = $self->options->{prefix} || "Test";
27             $prefix =~ s/(?:::)?$/::/;
28             $prefix;
29             }
30              
31             method _build_classname {
32             if ($self->options->{class_under_test}) {
33             $self->_classname_prefix . $self->options->{class_under_test};
34             }
35             else {
36             $self->context->get_curstash_name
37             || croak "Must specify a testclass name or a class to exercise";
38             }
39             }
40              
41             method test_preamble {
42             $self->context->scope_injector_call() . q{my $test = shift;};
43             }
44              
45             method inject_test {
46             my $ctx = $self->context;
47             $ctx->skipspace;
48             $ctx->inject_if_block($self->test_preamble);
49             }
50              
51             method shadow_test {
52             my $ctx = $self->context;
53             my $name = $self->name;
54             my $plan = $self->plan;
55              
56             my $classname = $self->classname;
57              
58             my $longname = ($name !~ /::/)
59             ? join('::', $classname, $name)
60             : $name;
61              
62             $ctx->shadow(
63             sub (&) {
64             my $code = shift;
65             no strict 'refs';
66             *{$longname} = subname $longname => $code;
67             $classname->add_testinfo(
68             $name,
69             $ctx->declarator,
70             $plan
71             );
72             }
73             );
74             }
75              
76             method helpers {
77             $self->options->{helpers} = [qw{Test::Most}] unless defined $self->options->{helpers};
78             @{$self->options->{helpers}};
79             }
80              
81             method use_helpers_string {
82             join '', map {"use $_;"} $self->helpers;
83             }
84              
85             method subject_method_string {
86             my $subject = $self->options->{class_under_test};
87             return '' unless $subject;
88              
89             "require ${subject} unless \%${subject}::; sub subject { \"${subject}\" };"
90             }
91              
92             method baseclasses {
93             $self->options->{base} || 'Test::Class';
94             }
95              
96             method use_base_string {
97             "use base qw/" . $self->baseclasses . '/;';
98             }
99              
100             method testclass_preamble {
101             my $classname = $self->classname;
102              
103             $self->context->scope_injector_call
104             . "package " . $self->classname . "; use strict; use warnings;"
105             . "use Test::Class::Sugar qw/-inner/;"
106             . $self->use_base_string
107             . $self->use_helpers_string
108             . $self->subject_method_string
109             }
110              
111             method inject_testclass {
112             $self->context->skipspace;
113             my $inject = $self->context->inject_if_block($self->testclass_preamble);
114             croak "Expecting an opening brace" unless defined $inject;
115             $inject;
116             }
117              
118             method shadow_testclass {
119             $self->context->shadow(sub (&) { shift->() });
120             }
121              
122             method install_testclass {
123             croak "You provide either a class name or an exercises clause"
124             unless defined $self->has_classname;
125              
126             $self->inject_testclass;
127             $self->shadow_testclass;
128             }
129              
130             method install_test {
131             $self->inject_test;
132             $self->shadow_test;
133             }
134             }
135              
136             __END__
137              
138             =head1 NAME
139              
140             Test::Class::Sugar::CodeGenerator - CodeGenerator for building B<Test::Class>es
141              
142             =head1 DESCRIPTION
143              
144             This class is intentionally mostly undocumented. However, if you were to take
145             it on yourself to write a version of L<Test::Class::Sugar> which builds, say,
146             L<Test::Able> classes, you should be able to do the job using this class as
147             your starting point.
148              
149             If you get stuck, drop me some email and I'll try and help you out.
150              
151             =head1 AUTHOR
152              
153             Piers Cawley C<< <pdcawley@bofh.org.uk> >>
154              
155             =head1 LICENCE AND COPYRIGHT
156              
157             Copyright (c) 2009, Piers Cawley C<< <pdcawley@bofh.org.uk> >>. All rights reserved.
158              
159             This module is free software; you can redistribute it and/or
160             modify it under the same terms as Perl itself. See L<perlartistic>.
161              
162              
163             =head1 DISCLAIMER OF WARRANTY
164              
165             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
166             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
167             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
168             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
169             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
170             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
171             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
172             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
173             NECESSARY SERVICING, REPAIR, OR CORRECTION.
174              
175             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
176             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
177             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
178             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
179             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
180             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
181             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
182             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
183             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
184             SUCH DAMAGES.