Crono
Crono

Reputation: 10478

Step-by-step functional testing automation

I have a basic class in C# from which I create inherited classes for databinding scenarios. You can think of it as a substitute for .NET's DataRow class.

I want to automate testing of a typical row's lifetime, making sure that things such as object state and changes detection remains coherent throughout.

My first thought was to simply use unit test class with a method that would do multiple operations and consequent assertions, like this:

/*
For the sake of keeping this as simple as possible, let's just assume
that new instances can be created with a public constructor, as "unchanged".
*/

var row = new PocoTest(); // Derived from aforementionned base class

Assert.AreEqual(RecordStates.Unchanged, row.RecordState);
Assert.IsFalse(row.IsPropertyModified("MyProperty"));

row.MyProperty = "this is a new value";

Assert.AreEqual(RecordStates.Modified, row.RecordState);
Assert.IsTrue(row.IsPropertyModified("MyProperty"));

row.AcceptChanges();

Assert.AreEqual(RecordStates.Unchanged, row.RecordState);
Assert.IsFalse(row.IsPropertyModified("MyProperty"));

However, this doesn't feel right in the unit testing paradigm in which it is recommended to have only one thing at a time being tested.

So I'm kind of looking for some advice, here. Am I overthinking this? Should I just keep doing it this way? Or is there another, better and more adapted way to accomplish something like this?

Upvotes: 1

Views: 1123

Answers (2)

Sam Holder
Sam Holder

Reputation: 32936

your tests should each be testing one logical thing. This may require several steps or assertions to verify. This is fine.

However your tests look to me like 3 tests. 1 which verifies that upon creation the property is unchanged, and then one which verifies that when its changed the object reflects that and then one which verifies that after accepting changes the state is unchanged again.

What have you called your test currently. I suspect that you have had trouble giving it a name, or it has a long convoluted name. Splitting it it should give you nice descriptive names.

I'd go with this:

public void WhenRowIsCreatedItShouldBeInAnUnchangedState()
{
  var row = new PocoTest(); // Derived from aforementionned base class

  Assert.AreEqual(RecordStates.Unchanged, row.RecordState);
  Assert.IsFalse(row.IsPropertyModified("MyProperty"));
}


public void WhenPropertyIsChangedItShouldBeInAModifiedState()
{
  var row = new PocoTest(); // Derived from aforementionned base class
  row.MyProperty = "this is a new value";

  Assert.AreEqual(RecordStates.Modified, row.RecordState);
  Assert.IsTrue(row.IsPropertyModified("MyProperty"));
}

public void WhenChangesAreAcceptedItShouldBeInAnUnchangedState()
{
  var row = new PocoTest(); // Derived from aforementionned base class
  row.MyProperty = "this is a new value";
  row.AcceptChanges();

  Assert.AreEqual(RecordStates.Unchanged, row.RecordState);
  Assert.IsFalse(row.IsPropertyModified("MyProperty"));
}

Upvotes: 3

PhillipH
PhillipH

Reputation: 6212

I'll have to be controversial here - I think the "one test, one test method" is a dogma rather than a useful tool. Its a matter of whether your test is whole, complete and predictable. I'd say go with your current approach - after all what is to be gained by splitting it up and adding complexity. Your code currently has lower cyclomatic complexity than adding in an extra function call for each Assert.

Upvotes: 2

Related Questions