Adding Specifications
Part 1 – Part 2 – Part 4 – Part 5
As with any sort of Test-Driven Development or Behaviour-Driven Development we should start by writing our tests or specifications first.
First, let’s do some basic setup of our specification assembly, Calculator.Spec.
Style Sheet
I like to cheat a little bit and steal from David’s style sheet included with the original Concordion. It’s simple, clean and very easy to read so we’ll use it. You will want to drop it at the top level of your Calculator.Spec project. You should change the Build Action on this file to Embedded Resource and set the Copy To Output Folder action to Copy Always.
This will ensure that the style sheet file is always included with the output when you build. Here is what it looks like
Folder Structure
Now that we have a style sheet we need a place to put our documentation. I like to have a top-level folder that is used as an entry point to all of the other fixtures. So let’s make a folder at the top-level of the Calculator.Spec project and call it Calculator. In this folder we will place two files: Calculator.html and CalculatorTest.cs
Calculator.html will be our HTML specification and CalculatorTest.cs will be the fixture class for Calculator.html. Note the naming convention here: The fixture name is the specification with the word ’Test’ appended. You should now see something like this
Filling in the Specification
The next step is to fill in the specification html file. To do this I will do a little more cut and paste magic from the main Concordion.Net specifications. You will want to replace the DOCTYPE and HTML tags that Visual Studio inserts with the following statement
<html xmlns:concordion="http://www.concordion.org/2007/concordion">
This statement declares the xml namespace for all of the concordion elements that we will be decorating our HMTL with.
Note: while I intend for Calculator.html to be a specification that doesn’t actually check anything I am still declaring the xml namespace. This is because it is required by Concordion.
Now we should add a link to our style sheet at the root of our folder structure like so
<link href="../concordion.css" rel="stylesheet" type="text/css" />
Now we can start adding text. I will add a little blurb about our calculator on this page and then add some “Further Details” reference links. In the end our Calculator.html page should resemble this
Last, but not least, you will need to set the Build Action to Embedded Resource and the Copy To Output Folder action to Copy Always
IMPORTANT: You should set those two properties on every html specification file you write! If you do not then they will not copy tot he output folder and Concordion.Net will not be able to find them.
Writing the Specification
We haven’t actually written any code to support this fixture yet so we should probably do that next! The discerning reader may even be wondering why haven’t we added a reference to Concordion.Net yet? We must add a reference to Concordion.Net to the project now. I will create a folder at the level of the solution called ‘lib’ and place the Concordion.Net assembly there and then add a reference to it in the project.
Now we will need to open up CalculatorTest.cs and do some touch-up work to it so that Concordion.Net can find it properly:
- Make the class public. If you do not it won’t be exported and if it isn’t exported then the test runner will not find it. Then you will be sad and I will be too!
- Decorate the class with the [ConcordionTest] attribute. This tells the test runner that this class is intended to be a test. It also allows you to use other classes that support the tests without the test runner trying to find and run them.
Your final class should look like this
using Concordion.Integration;
namespace Calculator.Spec.Calculator
{
[ConcordionTest]
public class CalculatorTest
{
}
}
One last thing … Concordion Files and Namespaces
Concordion has to have some means of linking a specification with a fixture class. The way that Concordion.Net does this is based on the namespace of the class. Thus, if a class has a fully-qualified name of Calculator.Spec.Calculator.CalculatorTest (like above) then Concordion.Net will look in the path Calculator\Spec\Calculator for the Calculator.html file.
Since we are embedding our specifications and they will be copied directly to the output it is necessary to modify the namespace a bit so that Concordion.Net can link the fixture to the specification. We do this by trimming the namespace like so:
using Concordion.Integration;
namespace Calculator
{
[ConcordionTest]
public class CalculatorTest
{
}
}
Notice that namespace has been reduced to just Calculator? Now Concordion.Net will look for Calculator\Calculator.html which is exactly where the html file will be when the project is built.
Next we will look at how to add some real specifications … that actually run tests!
Looking great so far, but two niggles:
ReplyDelete1. Copy Always can cause workstation builds in the IDE to do unnecessary work, slowing things down for the developer. If this is an issue with the description above, I would suggest changing it (copying when newer should do the trick). If this is a Concordion .net issue, I would suggest fixing it. (You may also wish to change the need to both embed AND copy to the output folder, as your runner should really only need one or the other.)
2. The requirement to change the namespace, as described in the "One last thing" section, breaks every .net coding standard I have encountered at a client site. I would highly suggest fixing this behavior by changing Concordion .net to account for the assembly name/type namespace convention appearing at the beginning of the test class's full type name and search for the spec html location on a relative basis from there.
Otherwise, it is definitely shaping up very nicely, and I am looking forward to having an opportunity to test this out on a client project!
@jeremy: see latest dev build of Concordion on the TeamCity server. Concordion now reads the .html files as embedded resources so it removes the need to change the namespaces (I felt it clunky too, but it was part of the evolution) and no need to copy the .html to the output directory as they are embedded directly in the assembly.
ReplyDeleteI will update this post accordingly in the near future.
p.s. thanks for your feedback thus far, it's great to see someone is looking seriously at it. I hope to hear more from you!