1Test::Abortable(3) User Contributed Perl Documentation Test::Abortable(3)
2
3
4
6 Test::Abortable - subtests that you can die your way out of ... but
7 survive
8
10 version 0.002
11
13 Test::Abortable provides a simple system for catching some exceptions
14 and turning them into test events. For example, consider the code
15 below:
16
17 use Test::More;
18 use Test::Abortable;
19
20 use My::API; # code under test
21
22 my $API = My::API->client;
23
24 subtest "collection distinction" => sub {
25 my $result = $API->do_first_thing;
26
27 is($result->documents->first->title, "The Best Thing");
28 isnt($result->documents->last->title, "The Best Thing");
29 };
30
31 subtest "document transcendence" => sub { ... };
32 subtest "semiotic multiplexing" => sub { ... };
33 subtest "homoiousios type vectors" => sub { ... };
34
35 done_testing;
36
37 In this code, "$result->documents" is a collection. It has a "first"
38 method that will throw an exception if the collection is empty. If
39 that happens in our code, our test program will die and most of the
40 other subtests won't run. We'd rather that we only abort the subtest.
41 We could do that in a bunch of ways, like adding:
42
43 return fail("no documents in response") if $result->documents->is_empty;
44
45 ...but this becomes less practical as the number of places that might
46 throw these kinds of exceptions grows. To minimize code that boils
47 down to "and then stop unless it makes sense to go on," Test::Abortable
48 provides a means to communicate, via exceptions, that the running
49 subtest should be aborted, possibly with some test output, and that the
50 program should then continue.
51
52 Test::Abortable exports a "subtest" routine that behaves like the one
53 in Test::More but will handle and recover from abortable exceptions
54 (defined below). It also exports "testeval", which behaves like a
55 block eval that only catches abortable exceptions.
56
57 For an exception to be "abortable," in this sense, it must respond to a
58 "as_test_abort_events" method. This method must return an arrayref of
59 arrayrefs that describe the Test2 events to emit when the exception is
60 caught. For example, the exception thrown by our sample code above
61 might have a "as_test_abort_events" method that returns:
62
63 [
64 [ Ok => (pass => 0, name => "->first called on empty collection") ],
65 ]
66
67 It's permissible to have passing Ok events, or only Diag events, or
68 multiple events, or none — although providing none might lead to some
69 serious confusion.
70
71 Right now, any exception that provides this method will be honored. In
72 the future, a facility for only allowing abortable exceptions of a
73 given class may be added.
74
76 subtest
77 subtest "do some stuff" => sub {
78 do_things;
79 do_stuff;
80 do_actions;
81 };
82
83 This routine looks just like Test::More's "subtest" and acts just like
84 it, too, with one difference: the code item passed in is executed in a
85 block "eval" and any exception thrown is checked for
86 "as_test_abort_events". If there's no exception, it returns normally.
87 If there's an abortable exception, the events are sent to the test hub
88 and the subtest finishes normally. If there's a non-abortable
89 exception, it is rethrown.
90
91 testeval
92 my $result = testeval {
93 my $x = get_the_x;
94 my $y = acquire_y;
95 return $x * $y;
96 };
97
98 "testeval" behaves like "eval", but only catches abortable exceptions.
99 If the code passed to "testeval" throws an abortable exception
100 "testeval" will return false and put the exception into $@. Other
101 exceptions are propagated.
102
104 You don't need to use an exception class provided by Test::Abortable to
105 build abortable exceptions. This is by design. In fact,
106 Test::Abortable doesn't ship with any abortable exception classes at
107 all. You should just add a "as_test_abort_events" where it's useful
108 and appropriate.
109
110 Here are two possible simple implementations of trivial abortable
111 exception classes. First, using plain old vanilla objects:
112
113 package Abort::Test {
114 sub as_test_abort_events ($self) {
115 return [ [ Ok => (pass => 0, name => $self->{message}) ] ];
116 }
117 }
118 sub abort ($message) { die bless { message => $message }, 'Abort::Test' }
119
120 This works, but if those exceptions ever get caught somewhere else,
121 you'll be in a bunch of pain because they've got no stack trace, no
122 stringification behavior, and so on. For a more robust but still tiny
123 implementation, you might consider failures:
124
125 use failures 'testabort';
126 sub failure::testabort::as_test_abort_events ($self) {
127 return [ [ Ok => (pass => 0, name => $self->msg) ] ];
128 }
129
130 For whatever it's worth, the author's intent is to add
131 "as_test_abort_events" methods to his code through the use of
132 application-specific Moose roles,
133
135 Ricardo SIGNES <rjbs@cpan.org>
136
138 This software is copyright (c) 2016 by Ricardo SIGNES.
139
140 This is free software; you can redistribute it and/or modify it under
141 the same terms as the Perl 5 programming language system itself.
142
143
144
145perl v5.34.0 2022-01-21 Test::Abortable(3)