PPI-Based Script to Convert Test.pm-based Test Programs to Test::More

Some CPAN modules I inherited used the old Test.pm for some of their t/*.t scripts instead of the more modern Test::More. This annoys me to no end because Test.pm is very limited. When I worked on Config-IniFiles, I did the conversion manually, which was a lot of work. More recently, I started working on XML-LibXML which has over 40 of those pesky Test.pm scripts, and I did not have the nerve to do all the manual and menial work.

As a result, I ended up spending a few hours studying PPI (the Perl Parsing Interface), and writing a script to automatically convert Test.pm-based scripts to Test::More. The main issue at hand was that in Test.pm, a single argument ok() tests for the scalar's truth, while a double argument ok() tests for simple equivalence (similarly to Test::More's is()). Eventually, I got the script working, with some limitations (see the page).

So what was my impression of PPI? It naturally seems more robust than using regular expressions and hacks to process Perl code, but there were a few quirks. For example, a PPI list contains an array of its contents, and the commas are part of them, as are the various other tokens in the sub-expressions. Therefore, divining the count of the arguments is pretty hard. I would have expected to get a more abstract syntax tree of the arguments, and since I didn't I had to work around it with an ugly kludge.

Furthermore, after stringifying the document object, the contents of the here-documents were not included in the output from some reason. However, I may have done something wrong. I also wish the PPI PODs contained more meaningful examples.

Nevertheless, my script is mostly working now and I can utilise it to "test-lift" legacy test programs. You might find it useful too, so it's there in case you need it, and patches to fix its limitations would be welcome.


PPI::Token::HereDoc is a different animal, and the content() method only gets you the initial delimiter.

The PPI::Document serialize() method is supposed to be round-trip safe. Not surprisingly, most of the code in that method appears to deal with here documents.

The thing is, if you actually use the serialize() method you first need to modify the original PPI::Document to transmogrify it into a Test::More-based test. There is a public interface for replacing tokens, but none (the last time I looked) for creating them.

Leave a comment

About Shlomi Fish

user-pic An Israeli software developer, essayist, and writer, and an enthusiast of open/free software and cultural works. I've been working with Perl since 1996.