Thursday, May 31, 2007

JUnit results in free form projects

At work, I'm working with a couple of colleagues on a project. Now, as is probably usual in many other environments, we all use different tools to work on the project: I use NetBeans, and the other two guys use Eclipse and Emacs. Thus, we have agreed that the Ant build scripts will be "the truth" : they have to be maintained and kept as the main tool for building, testing, and running the application.

So, all of that is great; however, I really like my NetBeans IDE, and I just couldn't continue living life without being able to use all of it's goodness. The best thing about NetBeans is that it is Ant based and it has the smarts/hooks to understand what you're trying to do (even in a freeform project), so that it can help you best. Here are the steps that I took to get my testing configuration going for a freeform project:

1. The first thing I did is to review the NetBeans Advanced Free Form Project Configuration

2. I added a compile selected item and debug project tasks (the debug task was quite useful since the code I was trying to understand was kinda convoluted and the debugger was invaluable in understanding how it works):

Here is what I added to my nbproject/project.xml (the ide-actions section):

<action name='debug'>
<script>nbproject/ide-file-targets.xml</script>
<target>debug-nb</target>
</action>
<action name='compile.single'>
<script>nbproject/ide-file-targets.xml</script>
<target>compile-selected-files-in-test</target>
<context>
<property>files</property>
<folder>test</folder>
<pattern>\.java$</pattern>
<format>relative-path</format>
<arity>
<separated-files>,</separated-files>
</arity>
</context>
</action>
<action name='test.single'>
<script>nbproject/ide-file-targets.xml</script>
<target>run-selected-files-in-test</target>
<context>
<property>classname</property>
<folder>test</folder>
<pattern>\.java$</pattern>
<format>java-name</format>
<arity>
<one-file-only></one-file-only>
</arity>
</context>
</action>



My ide-file-targets.xml additions look like this:

<target name='compile-selected-files-in-test'>
<fail unless='files'>Must set property 'files'</fail>
<mkdir dir='${test.classes.dir}'></mkdir>
<javac srcdir='test' source='1.6' includes='${files}' destdir='${test.classes.dir}'>
<classpath refid='run.test.class.path'></classpath>
</javac>
</target>
<target name='run-selected-files-in-test'>
<fail unless='classname'>Must set property 'files'</fail>
<mkdir dir='${test.classes.dir}'></mkdir>
<junit dir='${test.classes.dir}' printsummary='true' showoutput='true' fork='true'>

<classpath refid='run.test.class.path'></classpath>
<formatter type='brief' usefile='false'></formatter>
<formatter type='xml'></formatter>
<test name='${classname}'></test>
</junit>
</target>
<target name='debug-nb' depends='compile, compile-test'>
<path id='sourcepath'>
<pathelement path='src/'></pathelement>
<pathelement path='test/'></pathelement>
<pathelement path='..\\DeclTypeSys\\src'></pathelement>
<pathelement path='..\\DeclTypeSys\\test'></pathelement>
</path>
<nbjpdastart transport='dt_socket' name='perspective' addressproperty='jpda.address'>
<classpath refid='run.test.class.path'></classpath>
<sourcepath refid='sourcepath'></sourcepath>
</nbjpdastart>
<junit dir='${test.classes.dir}' showoutput='true' printsummary='yes' fork='true'>
<jvmarg value='-Xdebug'></jvmarg>
<jvmarg value='-Xnoagent'></jvmarg>
<jvmarg value='-Djava.compiler=none'></jvmarg>
<jvmarg value='-Xrunjdwp:transport=dt_socket,address=${jpda.address},suspend=y'></jvmarg>

<formatter type='xml'></formatter>
<formatter usefile='false' type='brief'></formatter>
<classpath refid='run.test.class.path'></classpath>
<batchtest>
<fileset dir='${basedir}/test'>

<include name='**/**/*Test.java'></include>
</fileset>
</batchtest>
</junit>
</target>

After I did that, my JUnit results look like this:











So, that was OK, but far from great. I thought that there should be a way to invoke the NetBeans JUnit test runner; however, googling around for it didn't help much. Then, just when I was about to lose hope, I ran upon these couple of posts:

Binding Freeform to Output and
UPortal Develop by Greg Sporar .

3.A slight complication on my end : I really didn't want to mess around with the target name of the original build.xml since the other team members were using that already. Thus, I added the following task to my ide-file-targets.xml:

<target name='test-project'>

<antcall target='junit'></antcall>
</target>

and changed the test single target name to "test-run-selected-files-in-test", so that the target name starts with "test" and changed the corresponding entry in my project.xml to run the right target.

And now, my test results look like this:








BEAUTY !!!

Tuesday, May 22, 2007

NetBeans testing with Groovy

I'm making some progress on my thesis, and as one can expect, when I'm writing code, I need to be writing some unit tests for it. Now, I know that Groovy is an excellent candidate for writing unit tests (better than the traditional JUnit stuff that NetBeans supports out of the box). However, it isn't quite obvious exactly how is one supposed to use and run these Groovy unit tests inside of NetBeans (apart form hacking together a crude solution where you have to add a line to a file, every time you need something to the suite() method). I just want to be able to hit the Alt-F6 button and have all of my tests run like magic : no manual additions to the suite, no tweaking.

So, in the end it worked, with a couple of gotchas:
1. NetBeans only seems to like running JUnit Test cases (when you hit Alt-F6) if and only if the test case name ends with "Test". That's kinda clunky, and as far as I know is not a requirement of JUnit itself. THere is nothing preventing you from executing the unit test individually (e.g. right-click -> run) - it runs like magic, but unless the class name ends with "Test", NetBeans doesn't add it to the bucket of tests to run.

2. The coyote module provides some support for testing in Groovy; however, it is not entirely intuitive exactly how that is done. In effect, if you want things to work nicely, you have to do 2 things:
- first, select a class that you want to test, go to Tools - Groovy Tests - Create Tests. That will basically greate a suite and a test in the $PROJECT/groovy-tests directory, as well as a groovy class in there.

A note a couple of months later, after the completion of the thesis project: Groovy worked great for the unit and integration testing of my project. It was fairly easy to script any of the scenarios that I had in mind, and after I had the general template for working with the groovy tests, it became quite easy to have pretty decent test coverage. Actually, the Groovy tests ended up being one of the important reasons for managing to complete the project after losing all of the work that I had done for the last 1.5 years ( yeah, I know i'm dumb not to have a backup, so, if YOU are working on something that important, DO A BACKUP NOW!!!).

Here is what my setup looks like:



1. I have one Java class for each type of tests that I wrote in Groovy. That is useful to be able to say "Test Project" from the project menu, and have all Groovy Tests executed in a meaningful manner.

2. Each Java JUnit subclass, has something like this in it. In effect, that takes the all Groovy files starting with "Service" and makes test suite out of them. One thing to note is that (slightly inconventiently), when the unit tests are run, all test methods from all groovy files show up under the name of the Java test class e.g.





public static Test suite() throws Exception {
TestSuite suite = new TestSuite("HandlerTests");

suite.addTest(AllTestSuite.suite("/home/polrtex/Docs/UofS_SE/Thesis/Implementation/MvpService/test/groovytest","Service*.groovy"));

return suite;
}


3. Finally, the Groovy test has some test methods in it, which get executed when you run the "Test" command on the project.

One final note on the tests themselves. I was using Spring 2.0 for my project, so I wanted to use the same datasource and service classes that the Spring Framework provides. Now, I knew that there were a couple of supporting Spring test classes (e.g. org.springframework.test.AbstractTransactionalDataSourceSpringContextTests), but I wasn't quite sure how to use them when the test are implemented in Groovy. What I ended up doing was to have a base Java class that extended the Spring test class mentioned above, and then have all of my Groovy tests extend that class. One thing that was interesting to note here was that I had to use the Spring autowire by name option, and the population of protected variables e.g.

class DaoTest extends com.troymaxventurs.mvp.test.MvpBaseTest {
//protected ds;);
protected mvpDAO;
protected mvpDataSource;
DaoTest() {
super("DaoTest")
setPopulateProtectedVariables(true)
setAutowireMode(AUTOWIRE_BY_NAME)
}
}


The reason I needed it to populate the protected variables (and not the bean fields) is that when these Groovy tests were instantiated, Spring tried to populate some Groovy specific public properties (e.g. the metaClass property), and thus, it failed along the way. With the population of protected variables, I could specify exactly what I wanted to have populated, without having to worry about any magic that Spring does to discover what dependencies to inject.

Popular Posts

Related Posts with Thumbnails