Theories

"Kelly Anderson" <[email protected]>
Newsgroups gmane.comp.windows.dotnet.nunit.devel
Message-ID <[email protected]>
Hope the cross posting isn't too irritating, but this potentially
relates to 3.0 too...

In the recent "Data Driven Addins" thread on nunit-developer, Charlie
pointed to this very interesting paper on Theories.

http://shareandenjoy.saff.net/tdd-specifications.pdf

Recommended reading. I agree with Charlie that this may be among the
more important recent developments in TDD. IMHO, the idea seems to
have more depth and applicability than BDD, for example. One of the
most interesting things that it explains in the paper is Assumptions.
An Assumption is a way of excepting something from a theory. For
example... if you have a theory about dividing integers, (at the
bottom of page 7 in the original paper) it could be expressed in
NUnit-like terms as:

[Theory]
public void multiplyAnyAmountByInteger(int amount, int multiplier)
{
   Assume.That(multiplier, Is.Not(0)); // The original paper
incorrectly put amount here instead of multiplier.
   Assert.That(amount, Is.EqualTo(new
Dollar(amount).times(multiplier).divideBy(multiplier).getAmount());
}

Apologies if I've messed up the Constraint syntax usage... it's still
a bit weird to me.

What you want to have happen here is that if the multiplier is 0, the
function returns before calling the Assert. Of course, you have to
specify what values are passed into such a test.

I've been giving some thought to how we might implement the Assume
part of this... and it seems like it would be fairly straight forward
to implement Assume in a fashion similar to Assert, but if the
condition is satisfied, you would throw a specific exception, say of
type AssumptionException, that NUnit could catch and continue
processing with no negative impact on the validity of the theory. That
is, it's still green if you pass in an amount of 0 because it never
got to the Assert.

You might be able to do it in some other way, but throwing the
exception seems like the most logical to me.

Question... How hard would it be given the current class hierarchy and
structure of Assert to implement Assume? Does it seem like a good
idea?

The paper suggests using something along the lines of Agitator to make
calls to the Theory. I think I would leave that as an exercise to the
reader... so that you could do something like this:

public IEnumerable TestData
{
  get
  {
     // Fill an ArrayList with random data... allowing the user to be
the Agitator.
  }
}

[Theory]
[PropertyData("TestData")]
public void multiplyAnyAmountByInteger(int amount, int multiplier)
{
   Assume.That(multiplier, Is.Not(0));
   Assert.That(amount, Is.EqualTo(new
Dollar(amount).times(multiplier).divideBy(multiplier).getAmount());
}

Does this seem like the right way to go forward? Does Assume feel like
it might be a 3.0 thing, or a 2.5 thing? Does anyone think we should
integrate Agitator type functionality?

Could we implement it so that this would be possible?

[Theory]
[PropertyData("TestData")]
[InlineData(0, 0)]
[InlineData(1, 0)]
[InlineData(0, 1)]
public void multiplyAnyAmountByInteger(int amount, int multiplier)
{
  ...
}

Meaning that it used all the values from the IEnumerable PropertyData
and the InlineData as well? That seems like it would be very cool.

-Kelly

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.