Unit testing plugins that launch external applications

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Unit testing plugins that launch external applications

Justin Holzer
I have just recently started working on an existing Hudson plugin (NAnt plugin) that runs an external command, and I was wondering how others had created unit tests for similar plugins? I figured I would be able to use EasyMock to mock the AbstractBuilder, Launcher, and BuildListener that are passed to the "perform" method of the Builder implementation. However, being new to EasyMock, I didn't realize that it was only able to mock Interfaces and not abstract classes as well. Also, once I dug deeper I realized that regardless of whether or not I had the ability to mock abstract classes, there were some serious impediments to being able to unit test the launching of the external application.

For starters, the Launcher.ProcStarter class, which is eventually used to run the external app, is declared final. Therefore, it's not possible to stub or override any of its methods, leaving me with no way to get around code being called that actually attempts to launch an external application. In my unit tests, I would not want to actually launch the external application, but rather, I would simply want to ensure that the command string and command-line arguments used to launch the app are correct.

I am fairly new to Hudson, but it definitely seems like a system that was designed with testability in mind, so am I missing something here? Should I be able to unit test this functionality using just what Hudson gives me, without having to add my own additional layer of interfaces and dependency injection? Even if it came down to wrapping the Hudson objects in custom interfaces, does Hudson allow you to use a dependency injection tool (like Spring) with your own configuration?

I also noticed, when looking at the tests for hudson-core (release 1.347), that there are no tests for tasks like Ant and Shell that also launch external commands. Is this a coincidence or have the developers working on hudson-core determined that this kind of stuff is difficult to test?

Any help or suggestions would be greatly appreciated.

- Justin Holzer
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing plugins that launch external applications

Kohsuke Kawaguchi-2
Justin Holzer wrote:

> I have just recently started working on an existing Hudson plugin (NAnt
> plugin) that runs an external command, and I was wondering how others had
> created unit tests for similar plugins? I figured I would be able to use
> EasyMock to mock the AbstractBuilder, Launcher, and BuildListener that are
> passed to the "perform" method of the Builder implementation. However, being
> new to EasyMock, I didn't realize that it was only able to mock Interfaces
> and not abstract classes as well. Also, once I dug deeper I realized that
> regardless of whether or not I had the ability to mock abstract classes,
> there were some serious impediments to being able to unit test the launching
> of the external application.
>
> For starters, the Launcher.ProcStarter class, which is eventually used to
> run the external app, is declared final. Therefore, it's not possible to
> stub or override any of its methods, leaving me with no way to get around
> code being called that actually attempts to launch an external application.
> In my unit tests, I would not want to actually launch the external
> application, but rather, I would simply want to ensure that the command
> string and command-line arguments used to launch the app are correct.
>
> I am fairly new to Hudson, but it definitely seems like a system that was
> designed with testability in mind, so am I missing something here? Should I
> be able to unit test this functionality using just what Hudson gives me,
> without having to add my own additional layer of interfaces and dependency
> injection? Even if it came down to wrapping the Hudson objects in custom
> interfaces, does Hudson allow you to use a dependency injection tool (like
> Spring) with your own configuration?
>
> I also noticed, when looking at the tests for hudson-core (release 1.347),
> that there are no tests for tasks like Ant and Shell that also launch
> external commands. Is this a coincidence or have the developers working on
> hudson-core determined that this kind of stuff is difficult to test?

Thanks for bringing up. I just didn't think about this before, but it is
an excellent idea to let you fake a process launch.

I've just committed some work toward this in rev.27995 for the upcoming
1.349. The way it works is that you create a special kind of slave
called PretendSlave, which lets you intercept and selectively fake
process invocations. I added the ShellTest class as an example of using
this.

I believe we can improve this by having a better EasyMock binding here.
I hope someone more familiar with it can chime in and implement a custom
FakeLauncher.

>
> Any help or suggestions would be greatly appreciated.
>
> - Justin Holzer
>


--
Kohsuke Kawaguchi
Sun Microsystems                   http://weblogs.java.net/blog/kohsuke/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]