Some FitNesse tricks: Classpath and debugging

On my project, we use Maven to build our software and FitNesse to write functional specifications. However, it was obvious that FitNesse wasn’t designed by Maven-fans. When I use Maven, I already have control over my classpath, and specifying it in every FitNesse test gets to be old really fast. Why can’t I just inherit the project class path, and start FitNesse using maven-antrun-plugin or just from my IDE?

I found a neat way to implement this by overriding FitNesse. Using the same technique, I’m also able to debug FitNesse tests.

Taking control of FitNesse

Fixing the classpath is exceedingly simple. But you need to understand a bit of the inner workings of FitNesse to get it to work. When you press the “test” button on a test, or the suite button on a test suite, FitNesse instantiates a class based on the registered “responder”. Our first order of business is to override this, but in order to do that, we need to take control over FitNesse.

You can do this by adding fitnesse.jar and fitlibrary.jar to your classpath, either manually in Eclipse, or by using a Maven dependency on org.fitnesse:fitnesse and org.fitnesse:fitlibrary. The latest version in the Maven repository is 20060719, which is old, but I’ve seen nothing that was worth the hassle of the manual download.

Once FitNesse is in you IDE’s classpath, you can run the Java class “fitnesse.FitNesse”. This starts FitNesse on port 80. Navigate to, say “http://localhost:8080/MyFirstTest”, and you’re ready to add a test.

In order to get it to work, though, you will have to do something like the following:

Ugh! Bad FitNesse!

Taking control of the classpath

After examining the class fitnesse.FitNesse, you will find that there is no simple way to modify the responder. So I basically copied that class into my own main class:

Again: FitNesse really should provide better hooks for this!

The cool part is of course InheritClasspathTestResponder, which overrides the standard FitNesse TestResponder:

Running your new main class instead of fitnesse.FitNesse will add the current class path to the executing FitNesse class path. This means an end to monkeying around with FitNesse classpath.

In order for suites to work, you also have to override SuiteResponder identically to TestResponder.

Debugging FitNesse

Add the following line after registering the test responder:

Here is DebugTestResponder:

To use it, run the test in FitNesse as usual, but then replace the “?test” part with “?debug”. FitNesse will now start running, but then freeze, while it is waiting for a debugger to connect. Connect a remote debugger from your IDE to the debug port (1044) in my example. In Eclipse, this is done by selecting Run -> Open Debug Dialog, right click “Remote Java Application” and choose new.

In conclusion

FitNesse has a powerful mechanism for overriding the default behavior built in to the ResponderFactory framework. It is a bit hard to stuff things into the framework until you learn how to do it. I demonstrated how by replacing the “test” and “suite” verbs, we can address one of the most common complaint I get from FitNesse users: Class path struggles. But adding a “debug” verb, we can make a test suspend at start up while waiting for us to attach a remote debugger.

Both these techniques have been huge time savers for me. I hope you like them, too.

Copyright © 2008 Johannes Brodwall. All Rights Reserved.

About Johannes Brodwall

Johannes is Principal Software Engineer in SopraSteria. In his spare time he likes to coach teams and developers on better coding, collaboration, planning and product understanding.
This entry was posted in Java. Bookmark the permalink.
  • Ole Morten Amundsen

    Finally, I might assist you, Johannes! Nice work, but sadly, I think you're reinventing the weel here. I meant to write a blog post about this, including how to use the pom. No excuses!

    We include the pom in the Fitnesse page by writing “!pom path_to_the_pom_he_fixtures_were_built_from/pom.xml”. See http://boss.bekk.no/fitnesse-pom-widget/usage.html

    Now you may set up a debugger in eclipse. Java Application->new->
    Main class: fitnesse.runner.TestRunner
    Arguments: localhost 8091 YourWikiPathToTestOrSuite -v -html fitnesse.html

    Bonus tip to your many readers: add “-e 0” to the startup of your FitNesse server to avoid those dreadful zips. Isn't FitNesse intuitive?

  • Ole Morten Amundsen

    Finally, I might assist you, Johannes! Nice work, but sadly, I think you’re reinventing the weel here. I meant to write a blog post about this, including how to use the pom. No excuses!

    We include the pom in the Fitnesse page by writing “!pom path_to_the_pom_he_fixtures_were_built_from/pom.xml”. See http://boss.bekk.no/fitnesse-pom-widget/usage.html

    Now you may set up a debugger in eclipse. Java Application->new->
    Main class: fitnesse.runner.TestRunner
    Arguments: localhost 8091 YourWikiPathToTestOrSuite -v -html fitnesse.html

    Bonus tip to your many readers: add “-e 0” to the startup of your FitNesse server to avoid those dreadful zips. Isn’t FitNesse intuitive?

  • http://brodwall.com/johannes/ Johannes Brodwall

    Hi, Ole Morten

    Three reasons why I don't like solutions like the fitnesse-pom-widget:

    1. You have to install fitnesse yourself. PLUS: You have to micky around with the installation. For me, maven is my only installer
    2. You have to start up stuff with special commands and stuff. For me, Eclipse is my only application runner.
    3. You still have to specify a path to the pom that will vary from workstation to workstation in your tests. For me, there is no changes when you relocate the workspace.

    Close, but no cigar.

    The debugger is nice, but the result of running the test won't be displayed in your web browser, right?

  • http://brodwall.com/johannes/ Johannes Brodwall

    Hi, Ole Morten

    Three reasons why I don’t like solutions like the fitnesse-pom-widget:

    1. You have to install fitnesse yourself. PLUS: You have to micky around with the installation. For me, maven is my only installer
    2. You have to start up stuff with special commands and stuff. For me, Eclipse is my only application runner.
    3. You still have to specify a path to the pom that will vary from workstation to workstation in your tests. For me, there is no changes when you relocate the workspace.

    Close, but no cigar.

    The debugger is nice, but the result of running the test won’t be displayed in your web browser, right?

  • Ole Morten Amundsen

    I share your philosophy. I want to run everything locally, including the fitnesse server. This is my startup script

    java -cp fitnesse.jar;libfitnesse-pom-widget-1.0-SNAPSHOT.jar;libmaven-embedder-2.0.4-dep.jar fitnesse.FitNesse -p 8091 -r FitNesseRoot -l logs -o -e 0

    Guess you'd find a way to execute the fitness server from Eclipse, but I don't see why. It uses near to nothing of resources and don't need to be restarted to notice updates. A simple .bat or .sh is good enough.

    RELOCATION
    I presume you have your fixtures in source control, why not have fitnesse ialongside it? They definetly belong together.

    /trunk/fitnesse
    /trunk/fixtures (or wherever the fixtures are located)

    Then you may use the relative path “!pom ../fixtures/pom.xml”

    DEBUGGER
    The option -html fitnesse.html in the debugger outputs the results in the same manner as pressing Test in the fitnesse page.

    Sadly, there is no cigar with FitNesse. I say, use it to communicate requirements, supplement with a few test tables. It's a wiki, terrible to maintain and opposes refactoring. I've committed my share of sins. Do you have any rules/guidelines for this Johannes?

  • Ole Morten Amundsen

    I share your philosophy. I want to run everything locally, including the fitnesse server. This is my startup script

    java -cp fitnesse.jar;lib\fitnesse-pom-widget-1.0-SNAPSHOT.jar;lib\maven-embedder-2.0.4-dep.jar fitnesse.FitNesse -p 8091 -r FitNesseRoot -l logs -o -e 0

    Guess you’d find a way to execute the fitness server from Eclipse, but I don’t see why. It uses near to nothing of resources and don’t need to be restarted to notice updates. A simple .bat or .sh is good enough.

    RELOCATION
    I presume you have your fixtures in source control, why not have fitnesse ialongside it? They definetly belong together.

    /trunk/fitnesse
    /trunk/fixtures (or wherever the fixtures are located)

    Then you may use the relative path “!pom ../fixtures/pom.xml”

    DEBUGGER
    The option -html fitnesse.html in the debugger outputs the results in the same manner as pressing Test in the fitnesse page.

    Sadly, there is no cigar with FitNesse. I say, use it to communicate requirements, supplement with a few test tables. It’s a wiki, terrible to maintain and opposes refactoring. I’ve committed my share of sins. Do you have any rules/guidelines for this Johannes?

  • Nils-Helge Garli Hegvik

    As the author of the fitnesse plugin that Ole Morten kindly enough has mentioned, I do agree with you that it is pretty obvious that FitNesse was not built with Maven in mind, and worse, it's practically impossible to customize! It's not modular and extensible at all (you wouldn't believe the troubles and hacks I had to go through to get that thing to work…)!

    Anyway, you seem to have found a good solution for running FitNesse for a Maven project. I still think there's cases where the pom widget is useful, especially when having a common FitNesse server installation and multiple projects within it.

    As for me, I've left FitNesse and use plain Fit instead. We use Excel spreadsheets as the source and convert them to HTML tables when the tests are run. Then our build run Fit with these converted HTML tables. It's fast, simple and more importantly, just what we need.

  • http://portletwork.blogspot..com Nils-Helge Garli Hegvik

    As the author of the fitnesse plugin that Ole Morten kindly enough has mentioned, I do agree with you that it is pretty obvious that FitNesse was not built with Maven in mind, and worse, it’s practically impossible to customize! It’s not modular and extensible at all (you wouldn’t believe the troubles and hacks I had to go through to get that thing to work…)!

    Anyway, you seem to have found a good solution for running FitNesse for a Maven project. I still think there’s cases where the pom widget is useful, especially when having a common FitNesse server installation and multiple projects within it.

    As for me, I’ve left FitNesse and use plain Fit instead. We use Excel spreadsheets as the source and convert them to HTML tables when the tests are run. Then our build run Fit with these converted HTML tables. It’s fast, simple and more importantly, just what we need.

  • http://brodwall.com/johannes/ Johannes Brodwall

    Hei, Nils-Helge

    Using plain old Fit is indeed an option that I considered, too. But now I am actually glad I didn't. I hope you'll like to try out the code from this article.

    FitNesse is definitely not designed with embedding and extending in mind. But when I was willing to dive into it, I found it wasn't that bad. I really wish my “trick” with writing my own main class was closer to the intended use, though.

  • http://brodwall.com/johannes/ Johannes Brodwall

    Hei, Nils-Helge

    Using plain old Fit is indeed an option that I considered, too. But now I am actually glad I didn’t. I hope you’ll like to try out the code from this article.

    FitNesse is definitely not designed with embedding and extending in mind. But when I was willing to dive into it, I found it wasn’t that bad. I really wish my “trick” with writing my own main class was closer to the intended use, though.

  • http://andypalmer.com Andy Palmer

    If you use
    !path {java.class.path}
    You get the classpath that fitnesse was called with, without the need for changing the fitnesse code.

    Also, if you create a page with the following (eg. .DebugSettings)
    !define COMMAND_PATTERN {java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1044 -cp %p %m}

    Then, on pages you want to debug, you can just add
    !include .DebugSettings

    not as nice as a Debug responder, but solves the problem without writing code for FitNesse.

  • Joe Hoover

    Just built this on OS X with Intellij. Had to remove the quotes around the classpath elements and then it worked. Also seems like Intellij attached automatically when launching RunFitnesse in debug mode. Hit a breakpoint in InheritClasspathTestResponder, this without adding DebugTestResponder. Very nice, thanks.

  • Joe Hoover

    Just built this on OS X with Intellij. Had to remove the quotes around the classpath elements and then it worked. Also seems like Intellij attached automatically when launching RunFitnesse in debug mode. Hit a breakpoint in InheritClasspathTestResponder, this without adding DebugTestResponder. Very nice, thanks.

  • krishna

    Four years later, how do we get this working for the latest Fitnesse library?

  • http://www.johannesbrodwall.com/ Johannes Brodwall

    Hi, Krishna – I haven’t been using FitNesse much the last two years and not at all last year. (Feels great, by the way) I think that Andy’s approach is still the best and that it still works. Just add this to a FitNesse page:

    !path {java.class.path}

    This makes the page inherit the classpath that FitNesse was launched with.