ArticleS. DavidChelimsky.
WhyLimitFit [add child]

Why Limit Fit?

There is a common notion that FIT is for customer tests and xUnit is for programmer tests. I've certainly lived by this thinking. I've even blogged about acceptable duplication between customer and programmer tests. But I've been struggling with it lately. In many FIT tables, especially the ones that describe business rules based on conditions:

validation rules
a b c valid?
yes yes yes yes
yes yes no yes
yes no yes no
etc etc etc etc

I've noticed that these tables lead me and my team to classes that operate directly on the basis of the described conditions. In this case, the table itself *could* double as a unit test. In fact, the unit tests end up looking very much like a different (less expressive) expression of the same thing:

[Test] public void ShouldBeValidIfAandBandC()
{
classUnderTest.a(true);
classUnderTest.b(true);
classUnderTest.c(true);
Assert.IsTrue(classUnderTest.IsValid());
}


Maybe that's expressive enough, but there are one of these test methods for every row in the table above, which is much more compact and therefore easier to understand, in my view.

The school of thought that says FIT is for customers and xUnit is for programmers leads us to keep both of these tests around. But why do we need that one thing expressed in two places, or in two languages? DRY, right?

There are arguments (that I'll confess that I've made with some passion) that FIT tables don't compile with the code, the don't *belong* to developers, etc. There are two problems I have w/ this thinking (and I have to reiterate here that it's MY thinking I'm criticizing - if yours is in alignment that's pure coincidence :) ) - one is that we're assigning a tool to a class of people (or roles) and thereby limiting its potential usefulness as is - two is that we're subconsciously limiting the directions in which FIT might grow. If we *think* FIT is for one thing, then it will be so.

What if, for example, we had an xUnit extension that would execute specific FIT pages as part of our unit test run? If we kept these with our source code (and in source control), then we have a great new way to express our unit tests. The big missing piece here becomes the compile step in the TDD cycle - and I don't see that getting resolved very easily. But things that IntelliJ[?] and TestDriven.[?]NET allow you to do, like clicking on a failed test and jumping to the point of failure - that becomes a matter of tools. And who knows what these tools might look like if we accept tabular expression of tests as a normal way to do unit testing.

The other thing that's been weighing on me is that I see a lot of functional/integration testing showing up in the xUnit test suites. I think this may be OK in some cases, but in others I think it's a problem. A perfect example would be the unit tests for FitNesse.NET - many of which I wrote myself. There are *unit* tests that describe entire tables in html in text strings and then verify that the counts are right after processing. Unit tests? I think not. Plus, they are much more difficult to read than the rendered HTML. So why express them this way when we can just use FixtureFixture[?]? In fact, I've been planning to re-express them using FixtureFixture[?]. If I do this, do I keep the NUnit tests?

If I get rid of them, then some of the artifacts of TDD are gone. So I guess to really do that justice I'd have to rewrite everything starting w/ FixtureFixture[?]. But then again, we refactor our xUnit tests as a matter of course in order to make them more expressive. Why not refactor them across the execution environment barrier?


!commentForm
 Fri, 2 Dec 2005 09:30:01, David Chelimsky, regarding cells
There's also been some discussion amongst fitsters about the relative value of being able to use ?, ! or () in column headers to tell FIT to execute a method. Seems like the table above might be more clear if it read like this:

validation rules
a? b? c? should be valid
yes yes yes yes
yes yes no yes
yes no yes no
etc etc etc etc
 Sun, 4 Dec 2005 19:03:27, Michael Feathers, I agree
I don't think we have to be limited. One of the cool things about FIT is that we get to pick our level. In fact, I think that one of the key cases for FIT use is: you have a setup (fixture) that is very common, and you want to reduce the cost of adding new tests to almost zero. Adding a row to an HTML table is about as close to zero as I can imagine.
 Mon, 9 Jan 2006 20:47:45, Paul Pagel, pick your level
I agree that unit tests can become too specific. This becomes painful when you try to change the design and it is expensive due to tests needing to be changed. This is a good fact of TDD. Yet when you see tests which are large, they seem to feel unnecisarily complicated. Sometimes there is a certain amount of setup which makes these test unavoidably large. Fit integrated testing can provide a layer of developer tests which are larger than a specific unit test for a specific class. It should not be limited, as David is implying, to customer acceptance tests. A FitUnit[?] which would test a few classes which were intimatly related, rather than unit tests, which should have a one to one ratio with production class files.

The downside is you are putting in a new layer of technology. One a single project you can now possibly have three levels of tests which are different. Confusion follows.
 Tue, 10 Jan 2006 05:28:56, ,
Unit tests give you rapid feedback on the quality of your APIs. FIT tests don't.
 Thu, 12 Jan 2006 22:01:00, Dave Astels, Fit for low level tests
Using Fit for repetitive, tabular tests is somethign I've done in thye past with great success. And, just as you suggest, we had them run from a jUnit test. It worked great.
 Mon, 23 Jan 2006 13:50:52, Andreas Voellmy, I agree
Thanks for writing about this. I've been thinking about it too. I've heard people say that you should do Fit tests for customer tests and then junit tests for developer tests and this has never really made sense to me.

My current approach is to write Fit tests that express business rules and use them to TDD fixtures and application code. I'm only writing junit tests when I'm testing code that doesn't relate directly to a feature expressed by Fit. A good example are equals() and parse() methods on classes.

I'd also like to explore using different sets of fixtures for my specs. It would be interesting to develop one set of fixtures that test as directly as possible against application classes implementing business logic and a second set of fixtures that test the same logic, this time using as much of the application as possible. With 2 sets of fixtures, you can get the benefit of using Fit tests to do TDD, while not losing the benefit of doing integration tests.
 Mon, 23 Jan 2006 18:52:39, David Chelimsky, rapid feedback
"Unit tests give you rapid feedback on the quality of your APIs. FIT tests don't."

Can you please expand on this in the context of the validation rules example I gave above? How would a unit test give me more rapid feedback than the table shown?