1Test2::Plugin::Cover(3)User Contributed Perl DocumentatioTnest2::Plugin::Cover(3)
2
3
4
6 Test2::Plugin::Cover - Fast and Minimal file coverage info.
7
9 This plugin will collect minimal file coverage info, and will do so
10 with minimal performance impact.
11
12 Every time a subroutine is called this tool will do its best to find
13 the filename the subroutine was defined in, and add it to a list. Also,
14 anytime you attempt to open a file with "open()" or "sysopen()" the
15 file will be added to the list. This list will be attached to a test2
16 event just before the test exits. In most formaters the event will only
17 show up as a comment on STDOUT " # This test covered N source files. ".
18 However tools such as Test2::Harness::UI can make full use of the
19 coverage information contained in the event.
20
21 NOTE: SYSOPEN HOOK DISABLED
22 The sysopen hook is currently disabled because of an unknown segv error
23 on some platforms. I am not certain if it will be enabled again. calls
24 to subs, and calls to open are still hooked.
25
27 This tool is not intended to record comprehensive coverage information,
28 if you want that use Devel::Cover.
29
30 This tool is intended to obtain and maintain lists of files that were
31 opened, or which define subs which were executed by any given test.
32 This information is useful if you want to determine what test files to
33 run after any given code change.
34
35 The collected coverage data is contained in test2 events, if you use
36 Test2::Harness aka "yath" then this data can be logged and consumed by
37 other tools such as Test2::Harness::UI.
38
40 Unlike tools that need to record comprehensive coverage (Devel::Cover),
41 This module is only concerned about what files you open, or defined
42 subs executed directly or indirectly by a given test file. As a result
43 this module can get away with a tiny bit of XS code that only fires
44 when a subroutine is called. Most coverage tools fire off XS for every
45 statement.
46
48 This tool uses XS to inject a little bit of C code that runs every time
49 a subroutine is called, or every time "open()" or "sysopen()" is
50 called. This C code obtains the next op that will be run and tries to
51 pull the filename from it. "eval", XS, Moose, and other magic can
52 sometimes mask the filename, this module only makes a minimal attempt
53 to find the filename in these cases.
54
55 This tool DOES NOT cover anything beyond files in which subs executed
56 by the test were defined. If you want sub names, lines executed, and
57 more, use Devel::Cover.
58
59 REAL EXAMPLES
60 The following data was gathered using prove to run the full Moose test
61 suite:
62
63 # Prove on its own
64 Files=478, Tests=17326, 64 wallclock secs ( 1.62 usr 0.46 sys + 57.27 cusr 4.92 csys = 64.27 CPU)
65
66 # Prove with Test2::Plugin::Cover (no coverage event)
67 Files=478, Tests=17326, 67 wallclock secs ( 1.61 usr 0.46 sys + 60.98 cusr 5.31 csys = 68.36 CPU)
68
69 # Prove with Devel::Cover
70 Files=478, Tests=17324, 963 wallclock secs ( 2.39 usr 0.58 sys + 929.12 cusr 31.98 csys = 964.07 CPU)
71
72 no coverage event - No report was generated. This was done to only
73 measure the effect of the XS that adds the data collection overhead,
74 and not the cost of the perl code that generates the report event at
75 the end of every test.
76
77 The Moose test suite was also run using Test2::Harness aka "yath"
78
79 # Without Test2::Plugin::Cover
80 Wall Time: 62.51 seconds CPU Time: 69.13 seconds (usr: 1.84s | sys: 0.08s | cusr: 60.77s | csys: 6.44s)
81
82 # With Test2::Plugin::Cover (no coverage event)
83 Wall Time: 75.46 seconds CPU Time: 82.00 seconds (usr: 1.96s | sys: 0.05s | cusr: 72.64s | csys: 7.35s)
84
85 As you can see, there is a performance hit, but it is fairly small,
86 specially compared to Devel::Cover. This is not to say anything bad
87 about Devel::Cover which is amazing, but a bad choice for the use case
88 Test2::Plugin::Cover was written to address.
89
91 INLINE
92 use Test2::Plugin::Cover;
93
94 ...
95
96 # Arrayref of files covered so far
97 my $covered_files = Test2::Plugin::Cover->files;
98
99 COMMAND LINE
100 You can tell prove to use the module this way:
101
102 HARNESS_PERL_SWITCHES=-MTest2::Plugin::Cover prove ...
103
104 This also works for Test2::Harness aka "yath", but yath may have a flag
105 to enable this for you by the time you are reading these docs.
106
107 SUPPRESS REPORT
108 You can suppess the final report (only collect data, do not send the
109 Test2 event)
110
111 CLI:
112
113 HARNESS_PERL_SWITCHES=-MTest2::Plugin::Cover=no_event,1 prove ...
114
115 INLINE:
116
117 use Test2::Plugin::Cover no_event => 1;
118
120 $arrayref = $class->files()
121 $arrayref = $class->files(filter => \&filter, extract => \&extract)
122 This will return an arrayref of all files touched so far. If no
123 "filter" or "extract" callbacks are provided then
124 "$class->filter()" and "$class->extract()" will be used as
125 defaults.
126
127 The list of files will be sorted alphabetically, and duplicates
128 will be removed.
129
130 Custom filter callbacks should match the interface for
131 "$class->filter()".
132
133 Custom extract callbacks should match the interface for
134 "$class->extract()".
135
136 $event = $class->report(%options)
137 This will send a Test2 event containing coverage information. It
138 will also return the event.
139
140 Options:
141
142 root => Path::Tiny->new("...")
143 Normally this is set to the current directory at module load-
144 time. This is used to filter out any source files that do not
145 live under the current directory. This MUST be a Path::Tiny
146 instance, passing a string will not work.
147
148 filter => sub { ... }
149 Normally "$class->filter()" is used.
150
151 extract => sub { ... }
152 Normally "$class->extract()" is used.
153
154 verbose => $BOOL
155 If this is set to true then the comment stating how many source
156 files were touched will be printed as a diagnostics message
157 instead so that it shows up without a verbose harness.
158
159 ctx => DO NOT USE
160 This is used ONLY when the Test2::API is doing its final book-
161 keeping. Most users will never want to use this.
162
163 $class->clear()
164 This will completely clear all coverage data so far.
165
166 $file_or_undef = $class->filter($file)
167 $file_or_undef = $class->filter($file, root => Path::Tiny->new('...'))
168 This method is used as a callback when getting the final list of
169 covered source files. The default implementation removes any files
170 that are not under the current directory which lets you focus on
171 files in the distribution you are testing. You may return a
172 modified filename if you wish to normalize it here, the default
173 implementation will turn it into a relative path.
174
175 If you provide a custom "root" parameter, it MUST be a Path::Tiny
176 instance, passing a string will not work.
177
178 A custom filter callback should look something like this:
179
180 sub {
181 my $class = shift;
182 my ($file, %params) = @_;
183
184 # clean_filename() does not exist, it is just an example
185 $file = clean_filename($file, %params);
186
187 # should_show() does not exist, it is just an example
188 return $file if should_show(%params);
189
190 # Return undef or an empty list if you do NOT want to show the file.
191 return;
192 }
193
194 Please take a look at the source to see what and how "filter()" is
195 implemented if you want all the details on how it works.
196
197 $file_or_undef = $class->extract($file)
198 $file_or_undef = $class->extract($file, %params)
199 This method is responsible for extracting a sensible filename from
200 whatever the XS found. Some magic such as "eval" or Moose can set
201 the "filename" to strings like '(eval 123)' or 'foo bar (defined at
202 FILE line LINE)' or even nonsensical strings, or text with no
203 filenames.
204
205 If a sensible file name can be extracted it will be returned,
206 otherwise undef (or an empty list) is returned.
207
208 The default implementation does not use any parameters, but they
209 are passed in for custom implementations to use.
210
211 A custom extract callback should look something like this:
212
213 sub {
214 my $class = shift;
215 my ($file, %params) = @_;
216
217 # It is a valid file
218 return $file if -e $file;
219
220 # Do not use this, just an example
221 return $1 if $file =~ m/($VALID_FILE_REGEX)/;
222
223 # Cannot find a file here
224 return;
225 }
226
228 Devel::Cover is by far the best and most complete coverage tool for
229 perl. If you need comprehensive coverage use Devel::Cover.
230 Test2::Plugin::Cover is only better for a limited use case.
231
233 The source code repository for Test2-Plugin-Cover can be found at
234 https://github.com/Test-More/Test2-Plugin-Cover.
235
237 Chad Granum <exodist@cpan.org>
238
240 Chad Granum <exodist@cpan.org>
241
243 Copyright 2020 Chad Granum <exodist@cpan.org>.
244
245 This program is free software; you can redistribute it and/or modify it
246 under the same terms as Perl itself.
247
248 See http://dev.perl.org/licenses/
249
250
251
252perl v5.32.0 2020-07-28 Test2::Plugin::Cover(3)