I like to share some FitNesse refactorings which I think are quite useful. These refactorings will help you prepare your tests for those eternally changing requirements. This is the scenario:
I need to assert that if the user changes a property in a file that eventually it is changed in the database as well. What you could do is create methods for each property like property[PropertyName]IsChangedInto. With the check keyword in FitNesse you can assert whether or not the new value matches the expected value (There are more table rows before and after this one but I omitted those for readability):
TestPage
|check|property phone|is changed into|020 6666666|
This will of course result in many methods in your Fixture if you have many properties to check.
IntroduceParameter
You can solve this by making the phone property a parameter so then the fixture code will look like this:
|check property|phone|is changed into|020 6666666|
Now all we need is a mapping that maps phone to some field in our code that needs to be checked. The downside here is that if you are not careful your mappings wind up in different places in different Fixtures and if you refactor your Java code you also need to refactor the mappings. But like a great dutchman always says “Elk voordeel heb zijn nadeel” (there is a downside to everything).
Now I choose to put the mappings in the FitNesse page (you could also define 1 mapping class that contain all the mappings).
TestPage
|map|phone|to|contactDetails.phoneNumber|
|check|property|phone|is changed into|020 6666666|
I think the advantage of putting it into the FitNesse page over the Fixture code is that is more readable and clear what is mapped to what. Although the customer would not really care about this it is surely more readable for the programmer, and I think tests are for both customer and programmer. If the mapping becomes to big you could create a seperate page for it and include it in the TestPage see ExtractPage how to do this.
Now if we have that mapping in place the implementation of the propertyChangedInto method is fairly easy, escpecially if you use something like PropertyUtils from common-beanutils.
public String propertyChangedInto(String propertyName) { return PropertyUtils.getNestedProperty(instanceFromDatabase, mapping.get(propertyName)).toString(); }
ExtractPage and ExtractVariable
If you want to check more properties you could of course copy-paste the fitnesse table and change the phone to another field and change the contactDetails.phoneNumber accordingly. But that will result in too much repetition.
The solution I came up with is to extract a FitNesse page for the table and extract to variables. After refactoring the extracted FitNesse page, let’s call it PageForTest, looks like this:
PageForTest
|map|${fieldName}|to|${mappedFieldName}|
|check |property|${fieldName}|is changed into|${newValue}|
And the resulting TestPage would then look like:
TestPage
!define fieldName {phone}
!define mappedFieldName {contactDetails.phoneNumber}
!define newValue {+31 020 666666}
!include TableForTest
And if you also need to test for instance the faxnumber:
TestPage
----Test for phone-----
!define fieldName {phone}
!define mappedFieldName {contactDetails.phoneNumber}
!define newValue {+31 020 666666}
!include TableForTest
----Test for fax-----
!define fieldName {fax}
!define mappedFieldName {contactDetails.faxNumber}
!define newValue {+31 020 777777}
!include TableForTest
By using refactorings like IntroduceParameter, ExtractPage and ExtractVariable you can create robust FitNesse tests. This way your tests are better prepared for coming changes in the requirements (and they will come).
Lars