Agile Zone is brought to you in partnership with:

Rob Williams is a probabilistic Lean coder of Java and Objective-C. Rob is a DZone MVB and is not an employee of DZone and has posted 171 posts at DZone. You can read more from them at their website. View Full User Profile

Testing Code Generation

11.21.2008
| 9300 views |
  • submit to reddit

Some things lend themselves to TDD better than others. Code generation, it turns out, scores a 10 on this front. (To some people, it‘s heresy to think that one should favor one approach over another based on the ease of development; I would disagree with this. When a factory tools up to make a product, it‘s all about whether they can get to a production level where they are rolling off the line for an amount where the things can be sold and a profit made. In development, we act like we can‘t really see into that dimension, so there‘s no real reason to try, and oh, yer stuff will be done when it‘s done. Estimates are NOT just about feature density. As a matter of fact, the feature line that each thing must travel will, by definition, impact all features.)

Anyway, using JUnit 4, and running plugin tests that restart the whole environment is as good as things get in terms of using TDD to really leverage agility on the dev side. You can do whacky refactors and just rerun the suite and never have to bring up an app and run through a bunch of steps, and wonder if you can trust yourself to check that each thing was done right. In code gen, all there is is the code that was generated. (Of course, one of the questions that pops out of this is how far into the mine do the savings extend. In other words, will there just be benefits to this while building up the base set of templates and the things they generate, or will we find ourselves, as we get farther into projects, returning to the gen code to augment what is coming out? I am starting to think the latter, because already I am seeing things that make a lot of sense, like generating global search, generating QBE classes, etc.

The first set of tests for checking whether code generation was done properly required the creation of a dummy project (used the Gamma/Beck code that they dropped with their book 5 years ago [fixed all the deprecations and added a few new things]), and then created an action and invoked it. The core generation outputs the properties files, the controllers (for create, update), the repository classes, the facelets, and a search page. So that test got pretty big, checking to see if all those things were generated, then looking at their contents. Then I set out to make it possible to gen QBE, and figured, since you are not going to want that for every entity, that should be a separate action. I was able to make another action to invoke pretty easily doing a cut and past in plugin.xml and then making a new handler class. Then I refactored the handler, figuring since there are going to be a number of actions that do the same thing (take a folder of templates and generate a bunch of code), might as well have a baseclass that does that. Once I was done with that I started working on the test of the new action. Then I realized that the only thing that‘s going to be different in these tests is what the action class is, so I ended up with the following construct: a base class that is abstract that does the project fixture, the action invocation, then the teardown, and the derived class just calls super, passing the class of the action. Here‘s what it looks like:

First the base class. Notice the action is just made by taking the class that was passed to the constructor and calling newInstance() on it (and note that we only have to reference it through the eclipse delegate interface):

then the action-specific tests:

The nice thing is that as people add new generation tasks, they can just completely ignore the project fixture requirements, just create a new test and start checking for their results. (Made me ponder for a moment how anyone would have an excuse for not doing a test in such circumstances….)

From http://www.jroller.com/robwilliams

Published at DZone with permission of Rob Williams, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Pieter van der Meer replied on Tue, 2008/11/25 - 6:23am

Rob,
To be honest I dislike the concept op TDD but that's some other discussion. What bothers me the most is actually the title of the post. Testing generated code? whats the purpose of generating code then.
The code generated is by default 100% correct. any additions in the application that uses this generated code is responsible for it's own code.
yes when adding code generation elements to the generator it must be tested and TDD is a way to go. Providing a base class that makes that part easier, sure why not.
The point is generated code is always correct, no discussion!
Pieter

Heng Yuan replied on Fri, 2008/11/28 - 8:22am

I don't think that strictly testing the code output within IDE environment is a great idea.  Particularly your approach went a long circle and tied to Eclipse just to get things compiled, with a lot of hardcoding.  What if other people are using a different IDE?  What about path?  Different JRE, Different configs for the code generator?  Also, what if there are a lot of tests?  What if the test failed, are there intermediate files to repeat / debug the test?

When I started to work on CookCC (a lexer/parser generator) that generates Java output, I find it better just to use shell scripts to do the tests.  Because we not only needs to test the code are generated, the generated code also has to be compiled and executed correctly with a set of test inputs.  Shell scripts are quite portable  too(there are MinGW / Cygwin for Windows and Unix / Mac have them built-in).

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.