I'm willing to automate the unit testing of my Perl modules, by plugging them into Hudson. Hudson is a continuous integration server, it "monitors executions of repeated jobs, such as building a software project or jobs run by cron". It works well, is extensible, and looks good.
So, The easiest way to do that is have Hudson to execute the module test suite, and look at the output. Actually, not really the output, but a file containing the output of the tests, in JUnit format.
Now, by default, Perl unit tests doesn't output JUnit. You know, that kind of stuff :
That's the standard output of tests run through TAP, the Test Anything Protocol, which is great, and (imho) better than JUnit.
Anyway, that output is generated because the tests are run through TAP::Harness, that outputs the result in TAP format on the console.
So first of all, let's see how to transform the tests output into JUnit. My modules use Module::Build (and also Dist::Zilla, but that's an other story) as building and releasing system. When using Module::Build, running the test suite is easy :
After some research and looking in the source code, I discovered that you can pass a lot of options to TAP::Harness, via Module::Build. Especially, you can specify a formatter to TAP::Harness when running the test suite. TAP formatters are modules that all inherit of TAP::Formatter::Base.
For instance, if instead of outputing the result on the console, you want it to be stored in a file, use TAP::Formatter::File. As you may have guessed now, there is a formatter that outputs JUnit : TAP::Formatter::Junit. That's exactly what we want. By issuing the following command line, the output of the test suite is in JUnit format.
Now we just need to tell Hudson to run it and look at the output
For some reasons, I had some trouble with TAP::Formatter::Junit on windows, mainly because there is no ActiveState PPM for this package. So I decided to give a go with TAP::Harness::JUnit
Its documentation is self-explanatory : it's a child class of TAP::Harness, that accepts an xml file name as argument, and procudes directly a JUnit output. This module being directly available in ActiveState Perl, it seemed to be aa good approach.
So the goal is to replace the call to TAP::Harness into TAP::Harness::JUnit, when doing Build test. And actually, it would be better to have an additional action to Build, so that we could do Build test, and Build hudson_test.
Luckily, Module::Build makes it easy to add an action. By looking at the ACTION_test method in Module::Build::Base, it's easy to see what needs to be changed. See this code snippet. What we want is a copy of that code that would run TAP::Harness::JUnit instead of TAP::Harness.
After some work, here is what I eneded with. This code is to be added into your Build.PL.
Now, build and run your tests in hudson mode
That's the easiest part : Setup a new project, add as execution line "perl Build.PL & Build hudson_test" (if you are on a windows hudson node). And point the project to the output file called "hudson_test_output.xml". That's it !