Charlie Poole
2008-03-17 01:02:49 UTC
Hi All,
We've had much discussion on the need for parameterized
or data-driven tests in 2.5. I thought I'd outline here
some thoughts about where I see it going.
[NOTE: This is separate from the discussion of Theories,
which is taking place on NUnitV3 currently. In fact, I'm
writing this to put down my thoughts about data-driven
tests before I jump into the Theories disussion.]
types of data-driven tests:
1. Those whose data arguments are specified right in
the metadata through a custom attribute.
2. Those whose data is provided separately - from a
file, an array or collection or an iterator.
For purposes of this discusssion, I'm calling the first
category "static" data, the second "dynamic." Bear in
mind it's actually all dynamic, but what I mean by
"static" in this context is that the actual values
used are contained in the metadata. For "dynamic"
data, the metadata only contains instructions for
how to get the data - a method name for example.
For static data, NUnit can construct separate
test cases at load time for each set of arguments.
For dynamic data, this would be possible with some
changes, but I'm making a design decision not to
do it at this point.
That means that test cases created with static data
will show up in the tree of tests individually.
Those constructed with dynamic data will not show
up separately, but will produce separate results
when the tests are run. Tests are already capable
of returning multiple results in NUnit but the
Gui will need to be modified to display them.
Internally, NUnit will support an extension point
for providing data to tests. The extension will
return one of two things to NUnit:
1) An actual data source, if the data is static.
2) An object for use at runtime to get the actual
data source, if the data is dynamic.
The actual interfaces involved still need to be
worked out.
For static test methods, I'm thinking of supporting
the following natively:
[TestFixture]
public class StaticDataSample
{
[TestCase( 1000, 10, 100.0000)]
[TestCase(-1000, 10, -100.0000)]
[TestCase( 1000, 7, 142.85715)]
[TestCase( 1000, 0.00001, 100000000)]
[TestCase(4195835, 3145729, 1.3338196)]
public void DivisionTest(double numerator, double denominator,
double result)
{
Assert.AreEqual(result, numerator / denominator, 0.00001);
}
}
If you're familiar with RowTest, you'll see that this is
essentially the same thing, with TestCase substituted for Row.
In fact I took the example from Andreas and I think we can
incorporate his code right into NUnit.
For dynamic data, I'm thinking of supporting something
like this...
[TestFixture]
public class DynamicDataSample
{
[Test, DataSource( typeof(MyDataSource)]
public void DivisionTest(double numerator, double denominator,
double result)
{
Assert.AreEqual(result, numerator / denominator, 0.00001);
}
}
Where MyDataSource is a class provided by the user. I'm
still working on the details of this, so please throw in
your ideas. I'd like to have a typesafe interface for
data, rather than using a string.
More to come on this - your comments are welcome.
Charlie
-------------------------------------------------------------------------
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/
We've had much discussion on the need for parameterized
or data-driven tests in 2.5. I thought I'd outline here
some thoughts about where I see it going.
[NOTE: This is separate from the discussion of Theories,
which is taking place on NUnitV3 currently. In fact, I'm
writing this to put down my thoughts about data-driven
tests before I jump into the Theories disussion.]
From all that has been said and my own research and
experimentation, I think there is a need for twotypes of data-driven tests:
1. Those whose data arguments are specified right in
the metadata through a custom attribute.
2. Those whose data is provided separately - from a
file, an array or collection or an iterator.
For purposes of this discusssion, I'm calling the first
category "static" data, the second "dynamic." Bear in
mind it's actually all dynamic, but what I mean by
"static" in this context is that the actual values
used are contained in the metadata. For "dynamic"
data, the metadata only contains instructions for
how to get the data - a method name for example.
For static data, NUnit can construct separate
test cases at load time for each set of arguments.
For dynamic data, this would be possible with some
changes, but I'm making a design decision not to
do it at this point.
That means that test cases created with static data
will show up in the tree of tests individually.
Those constructed with dynamic data will not show
up separately, but will produce separate results
when the tests are run. Tests are already capable
of returning multiple results in NUnit but the
Gui will need to be modified to display them.
Internally, NUnit will support an extension point
for providing data to tests. The extension will
return one of two things to NUnit:
1) An actual data source, if the data is static.
2) An object for use at runtime to get the actual
data source, if the data is dynamic.
The actual interfaces involved still need to be
worked out.
For static test methods, I'm thinking of supporting
the following natively:
[TestFixture]
public class StaticDataSample
{
[TestCase( 1000, 10, 100.0000)]
[TestCase(-1000, 10, -100.0000)]
[TestCase( 1000, 7, 142.85715)]
[TestCase( 1000, 0.00001, 100000000)]
[TestCase(4195835, 3145729, 1.3338196)]
public void DivisionTest(double numerator, double denominator,
double result)
{
Assert.AreEqual(result, numerator / denominator, 0.00001);
}
}
If you're familiar with RowTest, you'll see that this is
essentially the same thing, with TestCase substituted for Row.
In fact I took the example from Andreas and I think we can
incorporate his code right into NUnit.
For dynamic data, I'm thinking of supporting something
like this...
[TestFixture]
public class DynamicDataSample
{
[Test, DataSource( typeof(MyDataSource)]
public void DivisionTest(double numerator, double denominator,
double result)
{
Assert.AreEqual(result, numerator / denominator, 0.00001);
}
}
Where MyDataSource is a class provided by the user. I'm
still working on the details of this, so please throw in
your ideas. I'd like to have a typesafe interface for
data, rather than using a string.
More to come on this - your comments are welcome.
Charlie
-------------------------------------------------------------------------
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/