You might have noticed I have a habit of latching onto a good idea, and then persisting at it over several years until it finally works.
Test::Inline is another one of these projects I've been working on for a looooong time.
Schwern had the initial vision, of putting tests right next to the code it's testing, inline in Pod segments.
It clicked with me immediately, but to my dismay I encountered his downside, to do a very quick initial version that stagnates because he has too many other things to do :)
pod2test was just STDIN -> STDOUT, and did one file. So you would have to built an entire automation framework around it. It didn't handle per-class or or per-method dependencies... it didn't really scale to where I needed it to.
I decided I could do better, built Test::Inline2 for private use at my company, and then a year ago told him about it, and was given the namespace to turn Test::Inline2 into Test::Inline 2.00.
After releasing it, I found although it worked well at the API level, the main inline2test script sucked for day to day use.
Test::Inline 2.100 is a 2 day overhaul of the entire front-end user interface. Primarily, the CLI inline2test script.
So now my dream of simple inline testing is fulfilled at last. This is how easy it is.
1) Install Test::Inline 2.100
2) In the root of your CPAN module (as an example), create a config file called inline2test.conf containing:
input=lib
output=t
The inline2test script by default will look for a config file in the current directory, and so will locate yout lib and testing directories. Relative paths are relative to the config file.
You'll also need to define a little template for your test scripts, to make sure common module loading stuff happens. So, create a inline2test.tpl in the same directory containing something like this.
#!/usr/bin/perl -w
use strict;
use My::Module;
use Test::More [% plan %];
[% tests %]
With those two files created, lets add a simple test. You can put one of these test ANYWHERE inside your lib path, in any .pm file.
=pod
=begin testing
is( My::Module->squared(4), 16, "->squared returns as expected" );
=end testing
=cut
Now back in the root dir of your dist, just run
adam@red:~/DDS/trunk$ inline2test
adam@red:~/DDS/trunk$
And that's it. There should no be a nice shiney testing file in your t directory, which will run like any other test script. The naming scheme is based on the class the test was found in. So the best idea is to stick to numeric 01_compile.t, 02_main.t, etc etc testing for your normal tests, and let Test::Inline do the class-named ones.
The beauty of the whole thing is that each test takes so little time to write, and anyone can add tests anywhere. When you care about the tests (i.e. are doing testing), just run inline2test again, and it will rebuild the test scripts again.
So over time, with lots of tests in lots of places, you get something like this (run with the -e flag to tell inline2tests to immediately execute all the generated tests.
adam@red:~/DDS/trunk$ inline2test -e
Warning: Missing dependency 'getStatus' in DDS::Entity::NewCar
Warning: Missing dependency 'new' in DDS::Entity::NewCar
Warning: Missing dependency 'new' in DDS::Template
t/inline/dds__entity..............................ok
t/inline/dds_component_vehicle....................ok 250/196# Looks like you planned 196 tests but ran 54 extra.
t/inline/dds_component_vehicle....................dubious
Test returned status 54 (wstat 13824, 0x3600)
DIED. FAILED tests 197-250
Failed 54/196 tests, 72.45% okay (less 75 skipped tests: 67 okay, 34.18%)
t/inline/dds_db_foot_many.........................ok
t/inline/dds_db_relation..........................ok
t/inline/dds_db_schema............................ok
t/inline/dds_entity_account.......................ok
2/6 skipped: Skipping database testing
t/inline/dds_entity_franchise.....................ok
t/inline/dds_entity_location......................ok
t/inline/dds_entity_newcar........................ok
t/inline/dds_entity_newcar_table..................ok
t/inline/dds_entity_newcar_workflow...............ok
t/inline/dds_entity_newsale.......................ok
t/inline/dds_entity_newsale_table.................ok
t/inline/dds_entity_newsale_workflow..............ok
t/inline/dds_entity_staff.........................ok
t/inline/dds_entity_usedcar_table.................ok
t/inline/dds_html.................................ok
t/inline/dds_info_newcar..........................ok
t/inline/dds_interface_custom_make................ok
t/inline/dds_interface_custom_newsale_salesman....ok
t/inline/dds_make.................................ok
t/inline/dds_make_ford............................ok
t/inline/dds_make_toyota..........................ok
t/inline/dds_object...............................ok
t/inline/dds_template.............................ok
t/inline/dds_template_label.......................ok
t/inline/dds_web_application......................ok
t/inline/dds_web_application_new..................ok
t/inline/dds_web_screen_newcar....................ok
t/inline/dds_web_screen_newsale...................ok
t/inline/dds_web_screen_tradein...................ok
Failed Test Stat Wstat Total Fail Failed List of Failed
-------------------------------------------------------------------------------
t/inline/dds_component_vehicle.t 54 13824 196 54 27.55% 197-250
77 subtests skipped.
Failed 1/31 test scripts, 96.77% okay. -54/685 subtests failed, 107.88% okay.
adam@red:~/DDS/trunk$
As I use it more and more it's now becoming a habit to just drop inline2test.conf and inline2test.tpl files into the root of big projects even if I haven't written any tests yet, because I know that I will be. Then I have the convenience to drop in anything I want, anywhere I want, any time I want.
Two big projects done in 2 weeks... man... it sure feels like a burden off my back.
Update:> If you have trouble installing File::Remove on OS X Tiger, there's a new version just uploaded that should work.