I have a class (of many) that have properties. Some have logic in them and some don't. Assuming I want to test these properties, how do I go about doing that?
Recently, I've been interested in BDD style for creating unit tests.
see here and here.
So I'd do a setup of the context - basically create the SUT and load up whatever is needed.
Then in each Observation (test method), I'd verify that a particular property contains what it should contain.
Here's my question. If the SUT has 20 properties, then do I create 20 Observations/Tests? Could be more if one of the properties contained more interesting logic I guess.
[Observation]
public void should_load_FirstName()
{
Assert.Equals<string>("John", SUT.FirstName);
}
[Observation]
public void should_load_LastName()
{
Assert.Equals<string>("Doe", SUT.LastName);
}
[Observation]
public void should_load_FullName()
{
Assert.Equals<string>("John Doe", SUT.FullName);
}
But would it be better if aggregated the simple ones in a single observation?
[Observation]
public void should_load_properties()
{
Assert.Equals<string>("John", SUT.FirstName);
Assert.Equals<string>("Doe", SUT.LastName);
Assert.Equals<string>("John Doe", SUT.FullName);
}
Or what if I used a custom attribute (that can be applied multiple times to a method). So that I can possible do, something like:
[Observation(PropertyName="FirstName", PropertyValue="John")]
[Observation(PropertyName="LastName", PropertyValue="Doe")]
[Observation(PropertyName="FullName", PropertyValue="John Doe")]
public void should_load_properties()
{
}
In general you should strive after having only one logical assertion per test. The excellent book xUnit Test Patterns contains a good discussion about that, but the salient point is that it makes it easier to understand where a violation occurs if there's only one reason a test can fail. That's probably a bit more relevant for Regression Testing than BDD, though...
All this implies that your option of writing a single test that verifies all properties is probably the least attractive, although you could argue that verifying all properties is a single logical assertion...
A more central tenet of xDD (TDD, BDD, whatever) is that tests should act as Executable Specifications. In other words, it should be immediately apparent when you look at the test not only what is being tested, but also why the expected value is as it is. In your examples, it is not very clear why SUT.FirstName is expected to be "John" and not, say, "Jane".
If at all possible, I would write these tests to use Derived Values instead of hard-coded values.
For writable properties, I often write tests that simply verify that the getter returns the value assigned to the setter.
Fore read-only properties, I often write tests that verify that the value matches a constructor argument.
Such tests can be encapsulated into reusable test code that encapsulates common testing idioms. I'm currently working on a library that can do just that.
Have a look at the other SubSpec syntax (the [Specification]
example) - in that case, each one of Assert
s at the end represents a separate execution of the test. I originally discounted the syntax as lambda abuse but like it now I've been using it for a while.