I agree that CombinatorialTest is fantastic but it takes some work to
set up when you have multiple values to pass in at once because you have
to declare a new type to hold them (sadly no tuples in C#). So I tend
to use RowTest more because of its convenience.
Then there are features like MbUnit's TypeFixture. Unfortunately these
don't play nice with CombinatorialTest or RowTest because they want to
bind other values to test method parameters. To remedy this, there must
be a single coordinated mechanism that tests can use for data binding.
For the purposes of automated system testing by our Quality Engineering
group, I wanted to design some simpler data binding schemes.
Specifically, I wanted the ability to use different data providers as
with CombinatorialTest or DataFixtures without the burden of having to
declare data structures and serialization schemes for them. Also the
proliferation of attributes was confusing for our QE members (who have
somewhat mismatched skillsets sadly).
So the trick is for MbUnit to expose data binding to test method
parameters as a core facility that can be used by multiple data sources
with little extra work.
Let's start with a simple case:
[DataTest]
public void Test(int a, string b) { }
There's a lot of information here. We know the test has two parameters,
we know their types and we know their names. We can leverage this to
good effect to reduce the amount of work required on the part of the
programmer for data-binding.
In my extension, I built something called a BindingInfo that holds the
name of the code member to be bound, its type and its
ICustomAttributeProvider. The code member can be a method parameter, or
a property or field of the test fixture. Data sources are provided with
a list of BindingInfo's and asked to return a list of values to bind to
them.
So the data sources have the benefit of knowing the name, type and
custom attributes associated with each binding. This lets me do things
like this:
[DataTest]
[CsvResource("TestData.csv")]
public void Test(int a, string b) { }
Where the "TestData.csv" resource contains the following:
A,B
2,abc
4,def
-1,"bar bar bar"
By convention we case-insensitively match up the names of the parameters
with the names of the columns in the CSV file. We can do similar things
for XML. Like this:
[DataTest]
[XmlResource("TestData.xml")]
public void Test(int a, string b) { }
And the "TestData.xml" resource contains something like:
<Rows>
<Row><A>2</A><B>abc</B>
etc...
</Rows>
It's not a great format for sure and not everyone's cup of tea either
but it's a reasonable default for us. But if we want to bind to Xml
that looks like this:
<Users>
<User userId="2" username="abc" />
</Users>
We can always use the other features in the data binding scheme here:
[DataTest]
[XmlResource("FancyTestData.xml", RowXPath="//User")]
public void Test(
[XmlBind("@userId")] int a,
[XmlBind("@userName")] string b) { }
And what if we want to pass in the XmlNode straight up or a deserialized
structure? Well since the data source knows the type of the value being
bound, it can be a little intelligent about type conversions. So the
following notations are possible.
[DataTest]
[XmlResource("FancyTestData.xml", RowXPath="//User")]
public void Test(XmlNode userInfo) { }
[DataTest]
[XmlResource("FancyTestData.xml", RowXPath="//User")]
public void Test(UserInfo userInfo) { }
public class UserInfo
{
[XmlAttribute("userId")]
public int UserId;
// etc...
}
So then we come back to the issue of making TypeFixture and RowTest work
together. Again we can use conventions to good effect. Suppose the
TypeFixture recognizes a binding named "instance" by default. Then we
can do this:
[TypeFixture]
public class Fixture
{
[DataTest]
[Data(2, "abc")]
public void Test(MyType instance, int a, string b) { }
}
Or because we have access to the attributes we can customize things...
public void Test(
[TypeInstanceBind] MyType foo, int a, string b) { }
Pretty powerful huh? We get to leverage naming and typing conventions
to make life easier in the common case (a la Ruby) but we can still do
fancier things when needed.
Jeff.
-----Original Message-----
From: [email protected] [mailto:[EMAIL PROTECTED]
On Behalf Of Marc
Sent: Wednesday, August 09, 2006 7:57 AM
To: MbUnit.User
Subject: MbUnit Re: Extending TestFixtureAttribute.
> For v3, I think we should try to make test data binding orthogonal
> with respect to test execution. I have a few ideas about how we might
> implement such a notion.
What are your ideas? I think the whole test data binding thing is really
the "killer" feature of MbUnit.
I have found myself using CombinatorialTest for almost everything
because it seems to be the most flexible, even when what I'm doing is
not really combinatorial.
- Marc
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"MbUnit.User" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/MbUnitUser
-~----------~----~----~----~------~----~------~--~---