Perl development in a Rational Team Concert world

This page describes a usage or software configuration that may not be supported by IBM.

Perl is used for everything from bio-informatics to GUI Development. Perl can deal with text manipulation, file wrangling, and process management that makes it uniquely suitable for these tasks. When performing Perl development with Rational Team Concert (RTC) there are several unique challenges that this article proposes solutions to address.

Development

Development of Perl from the command line is the same as developing with RTC for any other language. However, out of the box the Rational Team Concert eclipse client does not provide any Perl specific functionality. The Eclipse client can be enabled for Perl development by installing a project like EPIC. There is already a great tutorial on installing and using the client here.

Build

Building a Perl project in RTC is probably where the majority of the challenges are faced, which is odd because Perl is not compiled. However, this is where the majority of test automation, static analysis, and other code validation occurs. There is already a great wiki article for creating Perl builds in RTC. However, the basic workflow is as follows:

Workflow of the wiki article"A Jazz-based Perl build"

This paradigm has RTC calling a Perl script that calls an ant script in order to report back to RTC. The key benefits of this workflow is you can report back the build/test process at a very low-level. The downside to this workflow is RTC is required at the top and bottom level of the call hierarchy. Thus, making build more complicated since you need to write a command line interface to your Perl build and an ANT interface to your RTC instance. This article present another workflow that provides a clear separation between RTC and the Perl build. Using a Makefile may not provide current progress in RTC beyond cleaning, building, testing, installing, etc… However, the benefit is RTC only needs to know how to execute a Makefile and the Makefile doesn’t need to know anything about RTC. The workflow would be something like this:

Workflow a Makefile based RTC Perl build"

On the surface this may look more complicated, but essentially it is nothing more than an ANT wrapper to a Makefile based Perl project. The project can be built and debugged with or without RTC. Using a typical RTC Ant build definition we call an ant script which does three types of tasks. First it will call a Perl script which creates a Makefile specific to the machine it is created on. Second it will then execute the individual targets of the Makefile. Lastly the Ant script will collect build outputs (e.g. STDOUT, unit test results, or logs) . This process is optimal for Perl Module development. If you are creating simple functional Perl scripts or cgi-bin scripts than the prior method or combination of the two methods may be better for you.

Building and running a Makefile

The ExtUtils::MakeMaker module provides a simple interface for creating a Makefile. Additionally there are similar packages such as Module::Build and others on the CPAN repository or possibly included in your favorite GNU/Linux, Unix, or Perl distribution. Although modules like these are extremely customizable, I often find it does a good job of taking the guess work out of finding system specific install/build information (e.g. “Perl '-V:install.*'” or “Perl -le 'print join $/, @INC'“). A simple Makefile.pl would look something like this:

  				  use 5.006;  use strict;  use warnings;  use ExtUtils::MakeMaker;    WriteMakefile(      NAME                => 'DemoPerlProject',      AUTHOR              => q{"Aaron Cohen" <"amcohen@us.ibm.com">},      VERSION_FROM        => 'lib/DemoPerlProject.pm',      ABSTRACT_FROM       => 'lib/DemoPerlProject.pm',      ($ExtUtils::MakeMaker::VERSION >= 6.3002        ? ('LICENSE'=> 'Perl')        : ()),      PL_FILES            => {},      PREREQ_PM => {          'Test::More' => 0,      },      dist                => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },      clean               => { FILES => 'DemoPerlProject-*' },  );  				  			

In your RTC ANT build script you would call this file with something like this:

  				  <!-- - - - - - - - - - - - - - - - - -            target: Create Makefile                                - - - - - - - - - - - - - - - - - -->  <target name="Create Makefile">  	<startBuildActivity label="create Perl Module Makefile"  		activityIdProperty="createPerlModuleMakefileActivityId"  		buildResultUUID="${buildResultUUID}"  		repositoryAddress="${repositoryAddress}"  		userId="${userId}"  		password="${password}" />  	<exec executable="/usr/bin/Perl">  		<arg value="Makefile.PL"/>  	</exec>  	<completeBuildActivity repositoryAddress="${repositoryAddress}"  		userId="${userId}"  		password="${password}"  		activityId="${createPerlModuleMakefileActivityId}"  		verbose="true"  		buildResultUUID="${buildResultUUID}" />  </target>			  				  			

The result will be the creation of a standard Makefile in the current working directory. Running it requires invoking make from that working directory. The RTC ANT build code would look something like this:

  			  <!-- - - - - - - - - - - - - - - - - -   	target: Make Perl Modules                        - - - - - - - - - - - - - - - - - -->  <target name="Make Perl Modules" depends="Update ISCIP Module Version with Build ID">  	<startBuildActivity label="Make Perl Modules"  		activityIdProperty="makingPerlModuleActivityId"  		buildResultUUID="${buildResultUUID}"  		repositoryAddress="${repositoryAddress}"  		userId="${userId}"  		password="${password}" />  	<exec executable="/usr/bin/make">  	</exec>  	<completeBuildActivity repositoryAddress="${repositoryAddress}"  		userId="${userId}"  		password="${password}"  		activityId="${makingPerlModuleActivityId}"  		verbose="true"  		buildResultUUID="${buildResultUUID}" />  </target>  			  		

Running Tests

Out of the box Rational Team Concert supports publishing JUnit, CPPUnit, MSTest TRX XML, NUnit, and the JDT (or ECJ) compiler log files. There are many testing frameworks for Perl and whichever one you choose should support outputting to one of the supported formats. Of course you could output to a non supported format and use the artifactFilePublisher, but you do not get the same level of UI integration. The example used in this article utilizes the Test Anything Protocol. One of the extensions to this module is TAP::Harness::JUnit which allows for the test output to be in JUnit format. The key difference between TAP::Harness::JUnit and TAP::Harness is the “xmlfile” argument that causes the output to be formatted into XML in format similar to one that is produced by JUnit testing framework. This means the creation of your test harness is going to look like this:

  			  my $harness = TAP::Harness::JUnit->new({  	xmlfile => "output.xml",  	verbosity => 1,  	lib => ["lib"]  });  			  		

After your test are executed, the results can be sent to RTC using the normal junitLogPublisher ANT tag.

  			  <junitLogPublisher repositoryAddress="${repositoryAddress}"      			                   userId="${userId}"      			                   password="${password}"      			                   buildResultUUID="${buildResultUUID}"      			                   filePath="output.xml" />  			  		

Code Coverage

There is an outstanding code coverage Perl Module called Devel::Cover. It is enabled outside of the make file using the “cover” command. Running “cover -test” in the same directory as your Makefile is the equivalent of telling Devel::Cover to run “make test”. Unfortunately, as of writing this article, the output is not in a format that can be represented as a first-class UI report in the RTC Build Summary. Thus, it must be attached to the build using the artifactFilePublisher tag. So gathering code coverage metrics while executing your unit test will look like the following in your RTC Ant build code:

  			  <!-- - - - - - - - - - - - - - - - - -   	target: Run Perl Module Tests                        - - - - - - - - - - - - - - - - - -->  <target name="Run Perl Module Tests">  	<startBuildActivity label="Run Perl Module Tests"  		activityIdProperty="runPerlModuleTestActivityId"  		buildResultUUID="${buildResultUUID}"  		repositoryAddress="${repositoryAddress}"  		userId="${userId}"  		password="${password}" />  	<exec executable="/usr/local/bin/cover">  		<arg value="-test"/>  	</exec>  	<junitLogPublisher repositoryAddress="${repositoryAddress}"  		userId="${userId}"  		password="${password}"  		buildResultUUID="${buildResultUUID}"  		filePath="output.xml" />  	<zip destfile="coverage.zip" basedir="cover_db" />  	<artifactFilePublisher repositoryAddress="${repositoryAddress}"  		userId="${userId}"  		password="${password}"  		buildResultUUID="${buildResultUUID}"  		filePath="coverage.zip"  		label="Zipped Code Coverage Reports" />  	<completeBuildActivity repositoryAddress="${repositoryAddress}"  		userId="${userId}"  		password="${password}"  		activityId="${runPerlModuleTestActivityId}"  		verbose="true"  		buildResultUUID="${buildResultUUID}" />  </target>  			  		

Everything else

There are a plethora of Modules available that provide metrics on software quality. If any of those metrics can be summarized as pass/fail then it is best to run them as unit test which will give them a first-class presentations in the RTC Build UI. Here are a sample list of Software Metrics and modules that can be run as unit test.

Closing

Rational Team Concert provides services for source control, builds, defect tracking, reporting, and much more. The tooling out of the box is optimized for Java, .Net, CPP, and Web development. Using some of the third party open source modules presented above Perl developers can achieve feature parity with these other langauges and runtimes.