Contents
FitNesse is a wiki-based framework for writing acceptance tests for software systems. If you are not familiar with FitNesse, Part 1 of this series walks through a complete .NET example from writing the test in your browser to writing the C# code-behind. The remaining articles in the series provide “tips from the trenches”, i.e. an accumulation of tips collected from intensive use of FitNesse on a daily basis to alleviate or avoid frustrations or quirks of FitNesse.
Part 3: Naming and Layout |
|
Most sections in this article have references with actual hyperlinks to the FitNesse, fitSharp, or DbFit reference material. Some also have references to the sample test suite accompanying this series of articles, e.g. CleanCode.ConceptNotes.LayoutShowingEmbeddedNewlines. That path refers to a page on your FitNesse server. Thus if you are running on port 8080 on your local machine, the full URL to visit that page would be:
http://localhost:8080/CleanCode.ConceptNotes.LayoutShowingEmbeddedNewlines
Naming
Fixture Naming Pattern
In C# there are a variety of naming patterns you use when defining classes: somethingObserver
, somethingProvider
, somethingListener
, etc. That gives others in your team, or even you for that matter, some notion of the purpose of the class. Similarly, the fixtures you write (to sit between your FitNesse test pages and your system under test) should use the naming pattern somethingFixture
. Not only does this give the benefit to the reader of knowing what the class is for, but also a benefit to the test writer. When a class uses that naming pattern, you can, and should, refer to it in a test without the Fixture
suffix: Doing so makes the test more quickly understandable to the reader. In the example below, on the right the purpose of this test table is obvious from its name: you intend to delete an incentive invoice. On the left, however, it feels incongruous to have the word ‘Fixture’ in there, needlessly exposing a piece of the inner machinery for no particularly good reason.
Less Clear Format |
More Clear Format |
|
|
|
Naming Your API Elements
This next tip builds on the last technique for naming fixtures, but applies to all your API elements, both fixture classes as well as the fields, properties, or parameters within a fixture class that you expose as your API to FitNesse. Common C# coding convention recommends both your class names and your public elements begin with a capital letter. Beyond the first word, when you have multiple words in a name there are different conventions that Visual Studio (or Resharper for that matter) cannot enforce because it does not know where the word boundaries are. Some people like to Use_Underscores_Between_Words
while others prefer RunTogetherWords
and still others might use a combination of those. For your FitNesse Fixture classes you should use RunTogetherWords (more formally known as Pascal-casing) because, through the magic of FitNesse, you can use either the computer-oriented format (left) or the human-oriented format that allows whitespace between words (right) shown below. The choice is left to the reader!
Computer-oriented Format |
Human-oriented Format |
|
|
|
Naming Your Test Pages
When you create a FitNesse test page in your browser, the name of the test (or test page-they are the same) must be a valid WikiWord and must therefore:
- Use Pascal casing, i.e. initial capital for each word
- Use only letters or numbers
- Have at least two capital letters in the word
- Have no spaces between words
Thus the perfectly reasonable seeming names on the left are not allowed and must be coerced into a form like that shown on the right to pass muster. On the bright side, FitNesse gives you immediate feedback as you type the name as to whether your name is a valid or not.
Illegitimate Names |
Legitimate Names |
|
HTMLTest myTestPage e-LearningTest Test2 |
HtmlTest MyTestPage ElearningTest TestPage2 |
Rule 4 above might seem strange, given that FitNesse permits-nay, even enthusiastically encourages-whitespace in API element names, as shown in the previous tip. Well it is still doing that though it is not immediately obvious. When you are on a given test page, the test name is shown without whitespace. But if you traverse up to the parent of the test page, there it is shown with the words automatically separated out with white space.
On Each Test Page |
On Parent Page |
|
|
|
Layout
Embed Line Breaks in your Test Tables
All the test tables I have been using are deliberately narrow, perhaps just two or three columns and anything in their cells is relatively short. In actual practice, particularly if you start using database queries in a test, the contents of a single cell can get quite wide.
A test table, as you now know, consists of vertical bars delimiting cells. The contents of a single cell must be all on one line because FitNesse will otherwise stop looking for those vertical bars, get rather confused, and just decide it is not a test table after all.
Imagine that you have a database query that is typed on a single line that scrolls off the right edge of your browser, simulated here with this box being a proxy for your browser-if you could scroll horizontally you would see the query go on and on, both in the source and in the output:
!|query|SELECT ProductId, CurrentPrice, LastPrice, PriceIncreaseDate, TransactionC |
|||
|
But FitNesse provides a handy mechanism to create a literal zone. Put anything between these brackets !- anything -! and the contents are preserved exactly as is including, in particular, line breaks:
|
|||
|
References: CleanCode.ConceptNotes.LayoutShowingEmbeddedNewlines
Order Your Columns Correctly
Inputs must appear before outputs! FitNesse processes columns sequentially from left to right. Thus calling the Result
method before defining the Value
property in the Echo
fixture would result in unexpected output. In this example I am showing C# pseudocode rather than FitNesse test source code to make the issue obvious:
Outputs before Inputs (incorrect) |
Inputs before Outputs (correct) |
|||||||||||||
function Result { return Value; } Result(); Value = “one”;
|
function Result { return Value; } Value = “one”; Result();
|
|||||||||||||
|
|
References: CleanCode.ConceptNotes.OrderOfParametersMatters
Use Block Structure
Approach writing a test just as you would writing code, i.e. do not have just one big blob of test tables. Unlike a unit test, where each test typically tests just one thing, an acceptance test in FitNesse may encompass a complex user story where, for instance, you may need to prepare bank data and customer data, validate preconditions before running a transaction, run the transaction and validate data from different database tables.
FitNesse provides these key syntactic elements to aid you:
Element |
Token |
Begin expanded block |
!* |
Begin collapsed block |
!*> |
Begin hidden block |
!*< |
Close any of these blocks |
*! |
Add horizontal rule |
—- |
This example shows how to use the three types of block elements:
|
|||
Invisible block here to sanity check some preconditions: Collapsed block here to set up data for the upcoming transaction test.
Expanded block here for the stuff you really care about in this test.
|
The references below include two pages in my sample project illustrating good block style.
References: Line and Block Formatting,
CleanCode.ConceptNotes.LayoutShowingDifferentBlocks, CleanCode.DataBaseNotes.CrudOperations
Ensure Your Blocks are Blocks
A block must have a title in order to be recognized as a block.
Title Missing (incorrect) |
Title Present (correct) |
||
|
|
||
|
|
Use Collapsed Blocks for Setup Pages
Generally you should collapse all your setup and teardown blocks. You can globally control whether they are expanded or collapsed with these two constants, typically defined on the root page. This affects SetUp
, TearDown
, SuiteSetUp
, and SuiteTearDown
pages.
!define COLLAPSE_SETUP {true}
!define COLLAPSE_TEARDOWN {true}
The latest version defaults to true for these, so you really only need to add these to your root page if you want to turn them off.
Reference: Global Variables
Keep Your Layout Tight
Compact your test vertically by eliminating blank lines between blocks. This is particularly helpful in compactly displaying a sequence of several closed blocks as shown.
Loose Vertical Space |
Tight Vertical Space |
|||||||||
|
|
|||||||||
|
|
References: CleanCode.DataBaseNotes.CrudOperations
Deaden Portions of Your Test Page
Generally speaking, everything on your test page is active content-if FitNesse recognizes it as a valid token or construct it will engage with it, whether this is rendering text between vertical bars as a table and then executing it or embedding hyperlinks on any text in a WikiWord format, and so forth. There are several types of constructs that let you mask things from FitNesse.
Comment tables allow you to define a test table in the usual way and have it nicely formatted by FitNesse, but the content is not executed when you run the test page. Create a comment table with the Comment
fixture:
|
|||||||
|
Character escaping allows you to mark any amount of text to be used “as is”: no WikiWord evaluation (if the page exists as a reference it becomes a link; otherwise, it gets a [?]
notation appended), line breaks (if present) are preserved, and the text itself appears just like its neighboring text.
Enter a !-LineOfText-! with character escaping to prevent the [?] suffix from appearing. Here is OneWithoutTheEscape for comparison. |
|
Enter a LineOfText with character escaping to prevent the [?] suffix from appearing. Here is OneWithoutTheEscape[?] for comparison. |
Block escaping allows you to mark any amount of text to be formatted as a code sample, i.e. it is rendered in a fixed-width font, line breaks (if present are preserved), and there is always a line break before and after the block:
|
|
|
Reference: Comment Fixture, Character Formatting, Line & Block Formatting
More to Come…
There are many more aspects to review and issues to alleviate-stay tuned for Part 4!
Load comments