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::Moreinto 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
-don the command line. It loades the debugger. - 2. The debugger initializes, looks for
.perldband executes it. - 3.
.perldbdefinesafterinitandwatchfunction. - 4. Perl calls
afterinit. - 5.
afterinitloadsDevel::TestEmbedand stacksuse Test::More plan=<no_planon the debugger's typeahead stack,@DB::typeahead. - 6. The debugger calls
watchfunction, which installstdumpinto the current namespace. - 7. The debugger starts reading commands, and pulls the
useoff 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::Moresub 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
tdumphas been imported there. it runs. - 3.
tdumpferrets through@DB::histand extracts anything which matches its list of "subs found inTest::Morethat are tests". - 4.
tdumpwrites 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>.