Home   Profil   Angebot   Artikel  
Partner   Kontakt   Links   Privates

ReFit for FitNesse

Refactoring of FitNesse test pages can be very burdensome. This Groovy-based tool tries to mitigate some of the effort for doing reorganizations in test pages and suites.

How to Use It

Installation & Starting the ReFit console

  1. Make sure you have a Java Runtime Environment (>= 1.5) properly installed
  2. Download refit-0.9.zip
  3. Unzipping the file wherever you want results in a folder called refit-x.y
  4. Start a command shell and cd to refit-x.y
  5. Use ./refitConsole (or refitConsole.bat on Windows systems) to start up the ReFit console window

Loading a FitNesse Suite

ReFit is basically a scripting environment for running ReFit scripts. The console window works exactly like the Groovy console with the exception of an additional ReFit menu. Try "Refit->Load Suite..." to choose (a) your current FitNesse root directory and (b) the base suite you want to restrict your refactoring to (e.g. FitNesse). Separate subwikis by using a dot inbetween (e.g. FitNesse.AcceptanceTests) or leave the base suite name empty - in that case all tests within your FitNesse root directory will be considered.

Now ReFit will try to load all pages and sub pages of the specified suite and list all loaded pages in the console's stdout (the lower half of the app window). Now you are ready to type in - or load - any Groovy scripts into the upper half of the application window. ReFit will give you access to the loaded suite via the globally visible varaible suite.

Collecting information

Let's try our first script. Given a standard FitNesse installation (fitnesse20070619.zip), using "fitnesse/FitNesseRoot" as root dir and "FitNesse" as base suite, we try the following:

suite.pages.size()

will show "501" as result.

suite.pages.each {
    println it.fullName
}
null

will print out all 501 page names to stdout. Only the last few thousand characters will remain visible, though. I added the null line to make the scripts result value null instead of the whole collection of all pages.

Performing Refactorings

Our next task will be a refactoring: Change all fixtures named "Summary" - in other words: all tables whose first cell equals "Summary" - to "Digest":

suite.allFixtures.findAll { it.name.normalize() == "summary" }.each { fixture ->
    fixture.rename("Digest")
}

Running this script will open the refactorings view: a table enumerating all details of refactorings which have been performed but not yet committed; in this case 5 renamings. You can now choose to rollback or commit all listed refactorings by pressing the appropriate button. Committing will, as you probably expect, change all files in the file system and print out the update, remove and move messages to stdout.

A more complex example:

suite.pages.findAll { page -> 
    page.name.normalize() == "setup" && page.fixtures.any { it.name.normalize() == "import"}
}.each {page ->
    page.fixtures[0].remove()
}

This script will find all "SetUp" pages that also have an "Import" fixture and then remove the first fixture of those pages. Your imagination is the limit!

Capabilities

What kind of refactorings are possible? You can be derive the details from the object model described below. Among ReFit's capabilities you find:

There is much more that is not supported explicitly (yet) but can be performed by doing a bit of Groovy scripting, e.g.: Melting fixtures, renaming variables or symbols, commenting in/out lines etc.

Basic Rules

ReFit tries to keep all FitNesse syntax working, like comments (#) and literals (!- -!). Thus, a table starting with "!" will keep the "!" during refactoring.

Most of the time you can just change a property to make the refactoring work, e.g. fixture.rename("new name") will have the same effect as fixture.name = "new name". This works only within the ReFit console; when you use ReFit as an external library you should use the specialized refactoring methods like rename(..) or fixture.replaceArgs(..).

Global Properties and Functions

There is one global property called suite that will be set to an instance of FitnesseSuite when a suite has been loaded.

There are a few global functions available in the console:

Special String Methods

You have seen the normalize() method in use. There are a few of those special String methods available within the ReFit console:

The ReFit Object Model

There are a couple of relevant classes. Below I enumerate their public properties and methods. The specified types might or might not be statically checked - Groovy allows both ways. However, most of them are not.

refit.FitnesseSuite

Public Properties:
Public Methods:

refit.FitnessePage

FitnessePage has a few subclasses which support the same interface.
Public Properties:
Public Methods:

refit.PageContent

Public Properties:
Public Methods:

refit.Fixture

Public Properties:
Public Methods:

refit.UnparsedLine

Public Properties:

Open Issues

Release Notes

Version 0.9 2008-03-04