NAME
Devel::TestEmbed - extend the debugger with Test::More
SYNOPSIS
# We assume that the supplied perldb.sample has been
# copied to the appropriate place.
$ perl -demo
Loading DB routines from perl5db.pl version 1.27
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(-e:1): mo
auto(-1) DB<1> use Test::More qw(no_plan)
DB<2> use_ok("CGI");
DB<3> $obj = new CGI;
DB<4> # Keep 'new CGI' in our test
DB<5> isa_ok($obj, "CGI")
ok 2 - The object isa CGI
DB<6> tdump "our.t"
Recording tests for this session in our.t ... done (2 tests).
DB<7> q
1..2
$ cat our.t
use Test::More tests=>2;
use_ok("CGI");
# Keep 'new CGI' in our test
$obj = new CGI;
isa_ok($obj, "CGI");
DESCRIPTION
The Devel::TestEmbed
module loads Test::More
for you, allowing you to use its functions to test code; you may then save the tests you used in this debugger session via the tdump
function.
If needed, you may save "setup" code in the test as well by entering a comment at the debugger prompt after each line of such code.
The module defines an afterinit
and watchfunction
; you will need to take this into account if you wish to defined either of these yourself while using this function. See perldoc perl5db.pl
for more informaton on these routines.
THE HACK
This solution to extending the debugger is a hack using the debugger's default behaviors in conjunction with some non-standard uses of the debugger's standard interfaces.
afterinit()
The debugger allows you to define an afterinit
function in .perldb
(the debugger's equivalent to a .rc
or <init> file). afterinit
gets called, not surprisingly, after the debugger has finished its initialization and before it prompts the user for the first command.
This allows us to do a number of things on behalf of the user:
Load
Test::More
into the program's namespace.Load this module into the debugger's namespace.
Turn on the magical flag that tells the debugger to run a
watchfunction
.
watchfunction()
watchfunction()
gets called just before the command loop starts. We use it to install the tdump()
subroutine into the current namespace (whatever namespace that happens to be).
Debugger's default behavior
When the debugger gets a command line it doesn't understand, it assumes that it mus be a Perl expression, so it goes ahead and evaluates this expression in the context of the program being debugged. This is what allows you to just say print $blah
and have it actually be $blah
from your program, not the debugger.
How it all comes together
First the debugger gets up and running.
- 1. Perl starts and sees
-d
on the command line. It loades the debugger. - 2. The debugger initializes, looks for
.perldb
and executes it. - 3.
.perldb
definesafterinit
andwatchfunction
. - 4. Perl calls
afterinit
. - 5.
afterinit
loadsDevel::TestEmbed
and stacksuse Test::More plan=<no_plan
on the debugger's typeahead stack,@DB::typeahead
. - 6. The debugger calls
watchfunction
, which installstdump
into the current namespace. - 7. The debugger starts reading commands, and pulls the
use
off the typeahead stack and executes it. - 8. The debugger finally prompts the user for input.
Now everything's in place. If we enter a Test::More
sub:
- 1. The debugger decides it doesn't understand the line.
- 2. The debugger evaluates the line in the current namespace.
- 3. The proper
Test::More
sub is called, and the test runs. - 4. The debugger saves the line on
@DB::hist
(its command history).
If we enter tdump something
:
- 1. The debugger decides it doesn't understand this either.
- 2. The debugger evaluates the line in the current namespace. Since
tdump
has been imported there. it runs. - 3.
tdump
ferrets through@DB::hist
and extracts anything which matches its list of "subs found inTest::More
that are tests". - 4.
tdump
writes the file and prints a "hi, I saved your tests" message.
SUBROUTINES
tdump
This is the actual command code that searches through the debugger's history and writes the test file. It takes an optional argument of the string to be used as the file name.
BUGS
The "command" doesn't get to parse the debugger command line itself, so if you say something like tdump foo.t
without quotes around the foo.t
, you'll find that Perl has evaluated this as an expression and merrily written your test to the file foot
.
Package switching in the debugger is not captured.
Tests which have been dumped once get dumped again if you use tdump
multiple times.
Running the debugger with this enabled can vastly
slow down the execution of your program, because watchfunction
is getting called every time a line of your program executes.
The tdump
routine is forcibly imported into every package when execution goes to that package. If that package has its own tdump
routine, chaos is likely to result.
You should be using Devel::Command
instead of this module if you want a nice clean implementation of debugger command extensions.
SEE ALSO
Devel::Command
for a considerably better way to do this. perl5db.pl
for a detailed description of how afterinit
and watchfunction
work.
AUTHOR
Joe McMahon <mcmahon@cpan.org<gt>.