Feeds:
Posts
Comments

I just released Delphi Code Coverage 0.4 today. It contains mostly minor usability improvements that should make it easier to use and more fault tolerant.

Oh, just one big thing affecting those of you with paths… I changed the escape character from \ to ^. (Pretty stupid of me to use backslash as an escape character for something that is purely on Windows…)

Here is the list of changes:

  • Made unit names case insensitive
  • Remove file type if existing on unit name
  • Use file name as specified in map file to look up source
  • ESCAPE CHARACTER changed to ^
  • Fixed various memory leaks as reported

Thanks to everyone who has downloaded, tried it out and found issues and suggested improvements! All contributions (yes code contributions too!) very welcome!

My ultimate goal with Delphi Code Coverage was to integrate Code Coverage reports with Hudson.

With the 0.3 release of Delphi Code Coverage, you can now generate XML reports that are compatible with the XML reports from EMMA. This means that you can get nice trend graphs directly in Hudson for your Delphi projects. Obviously, EMMAs reports are far more detailed, including class, method and block coverage. (We’ll get there some day too :) …)

In order to integrate the XML reports in to Hudson you will need to download the EMMA plugin for Hudson and configure it to pick up the XML report generated by Delphi Code Coverage.

You can also have access to the marked up Delphi source directly from within Hudson by using the HTML Publisher plugin. Just make sure you pick up the CodeCoverage_summary.html generated by Delphi Code Coverage.

Now, the 0.3 release of Delphi Code Coverage is still very much a project in its infancy. There are plenty of things on the to-do list, the next big thing is to tackle class and method coverage metrics…

Prelude…

My day job is squarely in the Java world, and trust me, in many respects it is a wonderful world. The amount of high quality, free, open source tools surrounding the Java platform is enormous. For someone interested not only in development but in “software engineering”, there is a risk that you spend all your time exploring all the great tools instead of doing some productive work…

Now, in the past professionally, and recently as a hobby, I have been using Borland/Embarcadero tools ranging from Turbo Pascal for Windows back in 1993 (who remembers TPW 1.0, hands up?) up to Delphi 2010. The Delphi community and the range of free libraries and tools has always been good, if not great. Delphi has been a very “complete” environment for the traditional Windows client and I’d say many Delphi developers probably feel uncomfortable leaving their IDE to use another tool. This has been different for other languages like C++ or Java where weaker development environments have had to be compensated by a range of IDE external tools. As far as a development IDE, Delphi is still very competitive.

As software engineering practices have advanced, a lot of the tooling focus has moved out from the developers IDE to the Continuous Integration system. With the advent of good tooling to support CI, the discipline of software engineering has taken a huge step from the closets of University CS departments out to the world of enterprise software development. Many are the development teams who embrace agile practices (code word:scrum), TDD and metrics driven development. One (in my view) welcome aspect of this is that the responsibility for quality has to a very large degree moved to the development team from the (usually understaffed) QA function. The whole point of Continuous Integration is to stay focused on the goal of having a quality product. And today, honestly, I’d think that a development shop who doesn’t use a CI tool like Hudson is seriously behind the times.

Now as people start using Hudson to build Delphi projects I know that people (at least I do) desire the same level of quality introspection and visibility in to their Delphi projects as they have with their Java, .Net and C++ projects. If that doesn’t materialize, the viability of Delphi as a development tool will diminish.

So – what’s missing you might ask?

Here’s my list:

  • An open source code coverage tool for Delphi
  • Static code analysis tools to find bugs and enforce coding guidelines (yes I love CTRL-D in Delphi 2010!)
  • Advanced mocking framework to facilitate unit testing
  • Hudson plugin to parse and visualize Delphi compiler output properly
  • Hudson plugin to parse and visualize DUnit output (or alternatively adopt DUnit to what JUnit outputs)
  • Hudson plugin to keep track of code coverage for tests

I understand that Embarcadero has embraced Hudson as a CI tool themselves – why not create and release some Delphi specific Hudson plugins, Embarcadero?

Introducing Delphi Code Coverage

So with that way too long prelude (still reading?) – to the point of this article. I have just submitted a new open source project to Google code called Delphi Code Coverage and it is to my knowledge the only free code coverage tool for Delphi. I’ve had this tool lingering on my hard drive in an unfinished state for a year and decided to spend a few hours to polish it up well enough to release it to the world. The inspiration comes again from the Java world where I have been using Emma as my code coverage tool of choice for quite some time.

Right now the tool only does line coverage, i.e. it will keep track of what lines were executed and visualize that in an html report. So you could say that it is an embryo of a Code coverage tool compared to mature code coverage tools out there. With some luck, this is a tool that more people would be willing to invest some time in and help make it as awesome as the awesome Delphi community deserves. There are plenty of features to implement to match the state of the art in Code Coverage tooling…

How it works and what does it do

Delphi Code Coverage is a command line tool that will run your executable and using the accompanying detailed MAP file keep track of what source lines were executed.

Here is a sample ( I hope self-explanatory):

CodeCoverage -e TestApp.exe -m TestApp.map -u TestUnit AnotherUnit AThirdUnit

This command line will generate 4 html files, three for the units you supplied and one with a summary for all the supplied units.

More details on the usage is available on the Google code site.

That’s all folks for now. I hope you give the tool a spin and let me know what you think!

Just a quick note to help others stuck with this particular exception deploying a war on Tomcat 6:

org.apache.jasper.JasperException: /welcome.jsp Unable to read TLD "META-INF/c.tld" from JAR file "file:/yourapp/WEB-INF/lib/com.springsource.javax.servlet.jsp.jstl-1.2.0.jar": org.apache.jasper.JasperException: Failed to load or instantiate TagLibraryValidator class: org.apache.taglibs.standard.tlv.JstlCoreTLV

The fix: remove jsp-api-2.1.jar from the WAR’s lib directory.

Exactly why this works I don’t fully know, just guessing that including it somehow blocks Tomcat’s own jsp-api.jar.

Hudson is a tremendously popular open source Continuous Integration tool mainly used for Java based projects. There is evidence that the Delphi community is picking up Hudson as a build tool as well (Hudson is built in Java) and even rumblings about Embarcadero themselves using Hudson to build Delphi.

I started using Hudson about a year ago in my day job as a step in organizing the build process for a bunch of Java projects that didn’t have an automated build and I have found it to be a tremendous help, not only in coordinating a team effort but also on a personal software process level, i.e. even if you are a single programmer on a project, I can guarantee you that you will see the benefit of using a CI tool like Hudson.

As I was getting totally smitten by Hudson in my day job, my hobby project in Delphi was suffering. Even though I was using Subversion and had automated build scripts and being a single developer I still found (my own) release process to be ad-hoc and brittle. So, enter Hudson to build my Delphi project as well. Since I am hoping that increased usage of Hudson in the Delphi community might lead to some new cool Delphi specific plugins from the Delphi community, I decided to write this little introduction.

Building a Delphi project using Hudson

Are there any prerequisites to start using Hudson? Virtually none – as you will see later on in this post, if you can write a few lines of batch script you are good to go. Well, maybe we should say that it is a pre-requisite to use one of the supported source code management systems(SCM). If your SCM is not supported, chances are you should switch (yes, it cannot be a popular SCM you are using…).

The first step is installing Hudson on a machine (if you have no other machine, your development machine will work fine). We shall not spend any words describing that since installing Hudson is so easy it should be set as an example for other systems!

The second step is to create what is called a job in Hudson parlance. A job can be described as the “build project” that describes all the aspects of building something. You will want to choose  ” Build a free-style software project”

The third step is to link the job to your Source Code Management system. Out of the box, CVS and Subversion are supported, for all others, you need to first install the appropriate SCM plugin. Hudson will place all the files from the SCM in to a “Workspace” in the filesystem from where the project is built.

The fourth step is to add a build step. Select “Execute Windows Batch Command” in the drop down box. If you haven’t already created a batch file that can build your project, now is the time. Delphi is using MSBuild, which makes it quite easy to create such a batch file. Chances are it will be this simple:

echo Building My Delphi Project
call "C:\Program Files (x86)\Embarcadero\RAD Studio\7.0\bin\rsvars.bat"
msbuild  /p:Win32LibraryPath="$(BDS)\lib;$(BDSUSERDIR)\Imports;$(BDS)\Imports;$(BDSCOMMONDIR)\Dcp;$(BDS)\include;" /t:build /p:config=Debug /verbosity:detailed "MyDelphiProject.dproj"
if errorlevel 1 exit 1

Test your batch script from the command line. If it works, you are ready to call this batch file from Hudson. Remember to check it in so that Hudson can fetch it from the SCM!

Now press SAVE on the bottom of the page.

Now you are ready to build your project. Select “Build now” and see if you get a blue dot for your project. If you get a red dot, go to the console output for that build to find out what happened.

So what have we done so far? We have made sure that Hudson can; 1. Fetch the source from the SCM. 2. Build it successfully. Now we need to make sure we live up to the “C” in continuous integration. This is done by configuring the “Build triggers” for the job to poll the SCM for changes. I usually set it up to poll every 15 minutes, but YMMV.

That’s all folks! May you all be successful in using Hudson to build your Delphi projects!

If you, like me (who is doing this as part of the Coherence Incubator), are dabbling with Java reflection, you might have run in to the case of trying to match a parameter list to available constructors or methods for a Java class in order to construct objects using reflection.

There is an easy option available in getDeclaredConstructor (and similarily for finding a particular method: getDeclaredMethod) which takes an array of Class objects and maps it to a constructor’s signature. The problem with this admittedly very convenient method is that it does an exact match between the Class for the formal parameter list and the Class of the actual parameter. So if you have a parameter that is of a subclass of the formal parameter, getDeclaredConstructor won’t find it!

The next interesting problem with getDeclaredConstructor is that if your formal parameter list includes any of the primitive types in Java, like byte, int, short, float etc. and your parameter list includes the boxed equivalents then again they won’t match! (for purposes of invoking a constructor or method using reflection, the primitive types are boxed)

But look no further, as part of the latest release of the Coherence Common Incubator project you will find getCompatibleConstructor to the rescue! Below you will find an extract from ReplicationHelper.java that will return a constructor that matches both subtyped parameters as well as primitive types.


 /**
 * Get a compatible constructor to the supplied parameter types.
 *
 * @param clazz the class which we want to construct
 * @param parameterTypes the types required of the constructor
 *
 * @return a compatible constructor or null if none exists
 */
 public static Constructor<?> getCompatibleConstructor(Class<?> clazz, Class<?>[] parameterTypes)
 {
   Constructor<?>[] constructors = clazz.getConstructors();
   for (int i = 0; i < constructors.length; i++)
   {
     if (constructors[i].getParameterTypes().length == (parameterTypes != null ? parameterTypes.length : 0))
     {
       // If we have the same number of parameters there is a shot that we have a compatible
       // constructor
       Class<?>[] constructorTypes = constructors[i].getParameterTypes();
       boolean isCompatible = true;
       for (int j = 0; j < (parameterTypes != null ? parameterTypes.length : 0); j++)
       {
         if (!constructorTypes[j].isAssignableFrom(parameterTypes[j]))
         {
           // The type is not assignment compatible, however
           // we might be able to coerce from a basic type to a boxed type
           if (constructorTypes[j].isPrimitive())
           {
             if (!isAssignablePrimitiveToBoxed(constructorTypes[j], parameterTypes[j]))
             {
               isCompatible = false;
               break;
             }
           }
         }
       }
       if (isCompatible)
       {
         return constructors[i];
       }
     }
   }
   return null;
 }

 /**
 * <p> Checks if a primitive type is assignable with a boxed type.</p>
 *
 * @param primitive a primitive class type
 * @param boxed     a boxed class type
 *
 * @return true if primitive and boxed are assignment compatible
 */
 private static boolean isAssignablePrimitiveToBoxed(Class<?> primitive, Class<?> boxed)
 {
   if (primitive.equals(java.lang.Boolean.TYPE))
   {
     if (boxed.equals(java.lang.Boolean.class))
       return true;
     else
       return false;
   }
   else
   {
     if (primitive.equals(java.lang.Byte.TYPE))
     {
       if (boxed.equals(java.lang.Byte.class))
         return true;
       else
         return false;
     }
     else
     {
       if (primitive.equals(java.lang.Character.TYPE))
       {
         if (boxed.equals(java.lang.Character.class))
           return true;
         else
           return false;
       }
       else
       {
         if (primitive.equals(java.lang.Double.TYPE))
         {
           if (boxed.equals(java.lang.Double.class))
             return true;
           else
             return false;
         }
         else
         {
           if (primitive.equals(java.lang.Float.TYPE))
           {
             if (boxed.equals(java.lang.Float.class))
               return true;
             else
               return false;
           }
           else
           {
             if (primitive.equals(java.lang.Integer.TYPE))
             {
               if (boxed.equals(java.lang.Integer.class))
                 return true;
               else
                 return false;
             }
             else
             {
               if (primitive.equals(java.lang.Long.TYPE))
               {
                 if (boxed.equals(java.lang.Long.class))
                   return true;
                 else
                   return false;
               }
               else
               {
                 if (primitive.equals(java.lang.Short.TYPE))
                 {
                   if (boxed.equals(java.lang.Short.class))
                     return true;
                   else
                     return false;
                 }
               }
             }
           }
         }
       }
     }
   }
   return false;
 }

…you should read the always (well, I find him amusing most of the time anyway) entertaining Joel Spolsky’s introduction to Mercurial. I’m currently using Subversion (at home) and Perforce (at work), both quite similar tools, but I am getting more and more enticed to go the Mercurial route instead. If you are looking for hosted Mercurial repositories, there seems to be two good choices in Bitbucket and Kiln.

Share

Follow

Get every new post delivered to your Inbox.