Thursday, August 4, 2011

Updating FitNesse for color blind users

The importance of designing for the color blind has always been at periphery of my awareness while building applications but was recently brought to the foreground when presenting a suite of Fitnesse test results to my boss. When he asked how to determine whether a test passed or failed, I was a little puzzled by the question. I thought the red and green colors were quite obvious. That's when he had to remind me that he is color blind (most likely protanopia or a variant, as red/green seems to be particularly problematic).

Of course, I was embarrassed at neither remembering this nor coming up with a solution before having it pointed out. Nonetheless, I remembered when first getting acquainted with Fitnesse a mention of customization of the stylesheets in the user guide.

Digging around a bit, I discovered a very simple solution. I created two png files, pass.png and fail.png and placed them in c:\fitnesse\files\images. Then I modified c:\fitnesse\files\css\fitnesse.css as follows:
@import url( "/files/css/fitnesse_base.css" );

.pass {
background-color: #AAFFAA;
padding: 0px 0px 0px 20px;
background-image: url("../images/pass.png");
background-repeat: no-repeat;
}

.fail {
background-color: #FFAAAA;
padding: 0px 0px 0px 20px;
background-image: url("../images/fail.png");
background-repeat: no-repeat;
zoom: 1;
}

#test-summary {
padding: 0px 0px 0px 20px;
}

Wednesday, July 27, 2011

Using FitNesse and TFS

Getting Fitnesse to work with an external source control system is not possible "out-of-the-box," though it does implement a source control provider interface that supports other providers. Thanks to Lars-Erik ?, there is a FitNesseTFS plugin available on SourceForge.

Caveats:
  1. This is an alpha product, and we've only tested it for a couple of weeks so far. Your mileage may vary.
  2. All users will be editing the same instance of fitnesse. There is no way to track who made changes to the wiki (all changes will be committed as the account under which the service runs), and there is no way to provide commit comments.

On the fitnesse server:
The first thing to do is to edit your path environment variable to include the path to TFS (for me, C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE) and Java (C:\Program Files (x86)\Java\jre6\bin).

I'll assume a Fitnesse root of c:\fitnesse.

Download the latest Fitnesse jar file.

Open a command prompt and run java -jar fitnesse.jar -p 8080 -e 0. This will run the Fitnesse unpacking process to give you a base install (and disable built-in versioning). Once it's done, close the command window.

Create a plugins folder at c:\fitnesse\plugins. Add the fitnesseTFS jar file.

You'll want Fitsharp, so download it and add the binaries to c:\fitnesse\fitsharp.

Run java -jar fitnesse.jar -p 8080 -e 0.
Run tf.exe workfold $/Infrastructure/fitnesse c:\fitnesse
Run tf.exe get c:\fitnesse /noprompt /all /overwrite /force /recursive
Run attrib *.* -R /S

Open a browser and navigate to http://localhost:8080/root

Click the edit button and enter the following:
!define TEST_SYSTEM {slim}
!define COMMAND_PATTERN {%m -r fitSharp.Slim.Service.Runner,c:\fitnesse\fitsharp\fitsharp.dll %p}
!define TEST_RUNNER {c:\fitnesse\fitsharp\Runner.exe}
!define CM_SYSTEM {fitnesseTfs.SourceControlPlugin C:\Users\me\Documents\Fitnesse\ "C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\"}

Click the Save button, and close your browser.

Follow the instructions in this article to set up fitnesse as a service.

For developers who need to work locally,
  • get latest from TFS on the Fitnesse project
  • Run the following:

  • cd c:\fitnesse
    attrib *.* -R /S
    java -jar fitnesse.jar -p 8080 -e 0

  • Start a browser and navigate to http://localhost:8080/FrontPage

  • Click the Properties button

  • In the Remote Wiki Url text box, enter the path to the server's wiki (something like http://buildserver:8080/FrontPage).

  • Check the Automatically update imported content when executing tests checkbox, then click the Import button.


You can now work on a local version of the fitnesse wiki while you work on fixtures without impacting other users.

Thursday, June 17, 2010

Upgrading Visual Studio Projects to 2010

Just a couple of notes that may be helpful:

Certificate Issues
Problem: Build error similar to "Cannot import the following key file: [your_key_file].pfx. The key file may be password protected. To correct this, try to import the certificate again or manually install the certificate to the Strong Name CSP with the following key container name: [your_key]"

Solution: Open the Visual Studio Command Prompt, then execute the following - sn -i [your_key_file].pfx [your_key]


Target Framework Issues
Problem: Build error similar to "The referenced assembly "log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL" could not be resolved because it has a dependency on "System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" which is not in the currently targeted framework ".NETFramework,Version=v4.0,Profile=Client". Please remove references to assemblies not in the targeted framework or consider retargeting your project."

Solution: Change the target framework of the project to one of the non-client frameworks (e.g., .NET Framework 4 instead of .NET Framework 4 Client Profile).

Friday, November 13, 2009

Using NUnit with log4net

Those who know me are aware that my obsessive-compulsive nature has latched on to TDD over the past few years. While I don't slavishly pursue 100% code coverage, I'll admit that anything below 80% really starts to get me pacing and much lower than that gives me the shakes for more green bars.

One of the areas I hadn't spent much time on was logging coverage. Partly because I hadn't found a good solution and partly because the types of applications I had been working on didn't really require much in the way of logging. My latest assignment, however, is another integration framework with lots of moving parts that screams logging and lots of it, particularly as I try to refactor a legacy code base I inherited.

Thanks to articles by David Hogue and Robert Prouse, the solution is incredibly simple.

The first step is to create a custom appender. The easiest way I found was to create a class that derives from AppenderSkeleton. I had it write to a static List<string> for the sake of simplicity.

1 namespace Integrations.Framework.Tests

2 {

3 class ListAppender:log4net.Appender.AppenderSkeleton

4 {

5 public static List<string> logTable = new List<string>();

6

7 protected override void Append(log4net.Core.LoggingEvent loggingEvent)

8 {

9 logTable.Add(RenderLoggingEvent(loggingEvent));

10 }

11 }

12 }



The next step was to programatically configure log4net. Something that initially tripped me up here was that I had defined a log4net configuration in an app.config in my test project. This apparently takes precedence over programmatic configuration (or else I just had something mucked up). Anyway, my programatic configuration would not take effect until I deleted the app.config.

1 namespace Integrations.Framework.Tests

2 {

3 [TestFixture]

4 public class DataGathererTests:DataGathererBase

5 {

6 private ListAppender appender;

7 private static ILog log;

8

9 [TestFixtureSetUp]

10 public void OneTimeSetup()

11 {

12 appender = new ListAppender();

13 appender.Layout = new log4net.Layout.SimpleLayout();

14 appender.Threshold = log4net.Core.Level.Fatal;

15 log4net.Config.BasicConfigurator.Configure(appender);

16 log = LogManager.GetLogger(typeof(ListAppender));

17 }



Notice above that I've derived my test class from my base class that implements logging. I want to make sure I'm not creating an artificial layer, so I'm deriving from that base class just as I expect my "real" code to do. Now I can call any of the logging methods, setting log level appropriately and check that messages are getting logged. Once I see that simple tests like log message count are passing, I can move on to more complicated tests that examine actual log messages to make sure the text is as expected, the correct log level, etc. Also, make sure to put a logTable.Clear() call in a TearDown method to make sure tests don't interfere with one another or become dependent upon one another for system state.

19 [Test]

20 public void TestLogging()

21 {

22 this.LogDebug("Debug");

23 Assert.AreEqual(0, ListAppender.logTable.Count());

24

25

26 appender.Threshold = log4net.Core.Level.Debug;

27 this.LogDebug("Debug");

28 Assert.AreEqual(1, ListAppender.logTable.Count());

29 }

Tuesday, March 3, 2009

Slim...Fast!

For those who haven't read the blog posts or tweets, Uncle Bob has been slaving away on a new addition to Fitnesse.

In addition to Uncle Bob's intro and video, Brett Schuchert has written up an excellent article on Mike Stockdale's .NET implementation of Slim (as well as an example Slim implementation).

As with Fitnesse, Slim can be set up to run as a service.

Setting up Slim and Fitnesse

  1. Download the latest Fitnesse release.

  2. Download the latest slim release.

  3. Configure slim as the test runner.
    !*****> System-wide settings
    !define TEST_SYSTEM {slim}
    !define TEST_RUNNER {..\nslim\build\Debug\Runner.exe}
    !define COMMAND_PATTERN {%m -r fitnesse.slim.Runner,..\nslim\build\Debug\fitnesse.dll %p}
    ******!




Running Fitnesse as a service

  1. Get the Windows Resource Kit.

  2. Install the Windows 2003 Resource Kit. You will only need the instsrv.exe and srvany.exe programs. So you can copy those out and deinstall the kit if you don't want it around.

  3. Use the instsrv.exe program to install the srvany.exe program by using it like this from the command-line:

    instsrv.exe FitNesse "[path]\srvany.exe"

  4. Run the regedit.exe program to set the last parameters.

  5. Find the key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\FitNesse

  6. Create a subkey with the name Parameters

  7. In the parameters key, create a string value called Application and set its value to the full path of the java.exe file. For me it was:
    C:\Program Files\Java\jre6\bin\java.exe.

  8. Create another string value called AppDirectory and set its value to the path where you want the executable to run. The directory where your FitNesse files are located : c:\Program Files\FitNesse

  9. Create a last string value called AppParameters containing the parameters passed to the java executable above : -cp fitnesse.jar -Xrs fitnesse.FitNesse -p 8080

  10. Open the service control panel and start the service.


A few observations that may make your implementation smoother:


  • Although instsrv supports passing credentials, I don't advise it. On some machines, it didn't seem to set up the correct rights for the service account. Just add the account on the Log On tab of the service.

  • For errors that you may encounter, see this article


I hope you find these instructions helpful. Happy testing.

-David

Sunday, June 1, 2008

How I Learned to Stop Worrying and Love Fitnesse and .NET 2.0

*update - 2008/12/23* Most of the problems this article describes have now been resolved with the latest release of Fitnesse (which finally includes a working version of the .NET fitlibrary). Ignore the Installing Fitnesse section, but the Running Fitnesse as a Service steps still apply.

If you’re anything like me, you like to find a solution that works the first time without a lot of hassle. Unfortunately, Fitnesse with the .NET 2.0 framework was neither. Here’s a step-by-step guide to avoiding the many pitfalls along the path to test enlightenment.

Installing Fitnesse

  1. Download the 06/2007 release of Fitnesse.
  2. Unzip the archive. Note the dotnet folder will be empty.
  3. Edit the fitnesse\run.bat file to include -p 8080 if IIS is running on the same server:java -cp fitnesse.jar fitnesse.FitNesse -p 8080 %1 %2 %3 %4 %5pause
  4. Download the .NET fit library.
  5. Unzip the archive to the dotnet folder of fitnesse (e.g., c:\fitnesse\dotnet).
  6. Double-click the run.bat file (e.g., c:\fitnesse\run.bat).
    1. A command window will open with the following:>java -cp fitnesse.jar fitnesse.FitNesse -p 8080FitNesse (20070619) Started…port: 8080root page: fitnesse.wiki.FileSystemPage at ./FitNesseRootlogger: noneauthenticator: fitnesse.authentication.PromiscuousAuthenticatorhtml page factory: fitnesse.html.HtmlPageFactorypage version expiration set to 14 days.
    2. If you see something like the following, you need to install Java:‘java’ is not recognized as an internal or external command, operable program or batch file.
  7. Fire up your favorite browser, and enter http://localhost:8080/FrontPage. This will take you to the main fitnesse page.
  8. Start editing.
    1. If you want to be able to edit the main page, browse to http://localhost:8080/FrontPage?properties and select the Edit checkbox, then click the Save Properties button.
    2. Otherwise, enter a new page name (e.g., http://localhost:8080/MyNewTest). This will ask you if you want to create a new page.
  9. Whichever path you choose on the previous step, go into the edit page and enter the following:
    !***> root config
    !define COMMAND_PATTERN {%m %p}
    !define TEST_RUNNER {dotnet\FitServer.exe}
    !define PATH_SEPARATOR {;}
    ***!
  10. Make sure your fixture projects reference fit and FitLibrary (though you’ll refer to FitLibrary as fitlibrary in code) in the fitness\dotnet folder if you want to use DoFixtures.
    Make sure you set the Fit reference to copy local=false. This will prevent hours of lost productivity trying to figure out what the heck "Couldn't cast YourFixtureNameHere to Fixture. Did you remember to extend Fixture" errors mean.
  11. Edit each test page (alternatively, you can just add this to a root page — it will be inherited by all child pages) with:
    !path path_to_your_test_fixture_dll

That’s it! You’re on your way to creating tests with Fitnesse and the 2.0 framework.

Running Fitnesse as a service

  1. Get the Windows Resource Kit.

  2. Install the Windows 2003 Resource Kit. You will only need the instsrv.exe and srvany.exe programs. So you can copy those out and deinstall the kit if you don't want it around.

  3. Use the instsrv.exe program to install the srvany.exe program by using it like this from the command-line:
    instsrv.exe FitNesse "\srvany.exe" -a MYMACHINE\fitnesse -p soSecret

  4. Run the regedit.exe program to set the last parameters.

  5. Find the key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet[?]\Services\FitNesse

  6. Create a subkey with the name Parameters

  7. In the parameters key, create a string value called Application and set its value to the full path of the java.exe file. For me it was : C:\Program Files\Java\jre1.5.0_04\bin\java.exe.

  8. Create another string value called AppDirectory and set its value to the path where you want the executable to run. The directory where your FitNesse files are located : c:\Program Files\FitNesse

  9. Create a last string value called AppParameters containing the parameters passed to the java executable above : -cp fitnesse.jar -Xrs fitnesse.FitNesse -p 8080

  10. Open the service control panel and start the service.

You can now write the same fixtures and reference them from Fit or Fitnesse. I hope you find these instructions helpful. Happy testing.

-David

Wednesday, May 14, 2008

A Practical Guide to Becoming Agile (on a latte-a-day budget)

Agile Software Development is so much a part of what we do in my company that many of us forget that parts of the industry have barely heard of it, much less scratched the surface.

While we are by no means experts on the topic (and many of the technologies/techniques we use have perfectly acceptable alternatives), I thought I would record how we got to this point for the benefit of others who may be interested in improving their own software development processes and need some ideas on how to make Agile work for them.

Interestingly enough, the company I worked for in 1999 was one of the most Agile environments I’ve been in, though none of us had heard the term at the time. It was a start-up company developing a transaction management platform for the real estate industry.

One of the senior developers I had the good fortune to work with had all kinds of crazy ideas I’d rarely seen implemented: collaborative development (pair programming), weekly code reviews, coding standards that make sense, etc. Additionally, the product manager, who I had followed from Houston to Indiana (having worked with her a couple of times and realizing that she was one of the most competent people I would ever work with), had similar ideas about having an on-site customer, making sure we were consistently and accurately gauging the value of feature requests to make the best use of resources. For those of you familiar with Malcolm Gladwell, maven meets connector and Great Things happen (not the least of which was their eventual marriage).

The Importance of the Agile Coach

Though we didn’t have a term for it at the time, Jason was what many Agile shops refer to as an Agile Coach: someone who is extremely knowledgeable about software development and has a passion for identifying areas that need improvement, researching alternatives, and proposing solutions. An Agile Coach constantly looks for the part of the process with the highest cost for the lowest reward and finds a way to improve that.

Finding an Internal Champion

Once we had an Agile Coach in place to convince all the people doing the actual work why we should be Agile, we needed someone to convince management and customers. This is the part where Agile often breaks down in typical organizations. People who have not seen the evidence of Agile’s efficacy often have difficulty getting past breaking down user stories, using points instead of time estimates, or why pair programming is not half as efficient.

We had the luxury of having a team that largely flew under the radar as a testbed for many of these practices. I cannot recommend highly enough finding a way to start small when implementing Agile. There are dozens (if not hundreds) of different Agile flavors. Find the one that makes the most sense for your team and organization. By implementing one or two techniques/practices/solutions at a time, we were able to assess what worked, gather evidence on why it worked, and present data on how much better it worked.

Getting a Real Source Control Solution

For anyone still working with SourceSafe, I empathize. Any source control solution whose standard operation requires a repair process is fundamentally flawed. Then there’s performance (local and remote), administration, functionality…

But I digress.

Switching to Subversion was one of the highest value, lowest cost elements of Agile we adopted. For one thing, it’s free. It’s been pounded on by the open source community. The performance beats the stuffing out of SourceSafe (particularly in remote development scenarios), and I shudder to think how we would accomplish the level of branching we do today with SourceSafe.

Implementing a Requirements Automation Framework

One of the more expensive and labor-intensive methods of failure we discovered was the waterfall method of requirements gathering. There may be situations where requirements need to be documented so extensively prior to development. Unfortunately, we consistently spent so much of our time correcting the documentation of requirements that had changed during the six to nine months it took to document them that we inevitably abandoned the documentation. “Oh, you can ignore that; the requirements changed and we didn’t have time to update all the documentation” was a frequently heard phrase.

Using fitnesse, we were able to more closely tie documentation of requirements to test plans. Instead of existing as disparate documents (and, yes, we tried all sorts of schemes to track the relationship between requirements and test criteria), the two co-exist in the same wiki format. Whenever a change in requirements is identified, it’s easy enough to change the test cases, since they are usually on the same page.

Using Test-Driven Development

For the traditional developer, learning to write tests before code is like learning to ride a bicycle…backwards…blindfolded. Some people take to it freakishly easy and make the rest of us secretly despise them as we work to master something that goes against all our experience. Having become accustomed to TDD, I can’t imagine writing code any other way. Before adopting the practice, I had made a concerted effort to limit the scope of whatever I was working on at any given time. I realized that a lot of the coding quandaries I got myself into were the result of trying to take on too much at the same time. And I thought I had really made good progress on this until I started really implementing TDD and realized how much smaller I could make that scope. Focusing on a test at time really brings clarity to the requirements and how I am trying to implement them. We use NUnit and TestDriven.net.

Frequent Builds

You’ve heard it before: “Works on my machine.” DLLs, folder dependencies, permissions…all ticking timebombs on a developer’s machine waiting to go off when you try to deploy the application elsewhere. Our initial approach to resolving this issue was a daily build. We used NAnt (supplemented occasionally with batch files, bailing wire, and duct tape) to script a teardown, retrieval from source control, build, and test of the system. This took a fair amount of effort to put together after the fact, so I recommend doing it as you build your application. It immediately paid dividends, as we found issues within 24 hours of being introduced when the nightly build was run and reported. It even became a contest amongst the team to see who could go the longest without breaking the build.

For many projects, a nightly build is sufficient. Since we were working on a custom event broker and translation engine to integrate various systems, we needed a little more. We implemented continuous integration using CruiseControl.NET. Now, each time a change is made, the solution is built, all smoke tests are executed, and the team is alerted to the result. We keep the continuous integration tests as minimal as possible while still being a representative test of the system’s functionality. Productivity is hindered if developers have to wait around for 30 minutes at the end of the day to make sure the changes they just checked in didn’t break the build.

There’s certainly more to Agile development than I’ve mentioned here, but this is a good snapshot of most of the technologies involved as well as the rationale behind them. I hope to post more detailed articles on the use of each.