DEV Community

Cover image for Writing Maintainable Tests : Comparing Objects
DevByJESUS
DevByJESUS

Posted on

Writing Maintainable Tests : Comparing Objects

Hello ๐Ÿ˜„
Today it is a small post , about writing maintainable test , we will talk about a problem that we have done or we are doing now in the projects we are working on.

Asserts In Unit Testing

Asserts are powerful elements in our unit tests , because when one assert fails , we can localize exactly which use case has encounter an error. Saying This we have seen in this post why multiple asserts are bad , but we tend to fall into another bad practise Have Multiple Asserts on the same Object

look at the code below :

[Test]
public void
Analyze_SimpleStringLine_UsesDefaulTabDelimiterToParseFields()
 {
   LogAnalyzer log = new LogAnalyzer();
   AnalyzedOutput output =
     log.Analyze("10:05\tOpen\tRoy");
   Assert.AreEqual(1,output.LineCount);
   Assert.AreEqual("10:05",output.GetLine(1)[0]);
   Assert.AreEqual("Open",output.GetLine(1)[1]);
   Assert.AreEqual("Roy",output.GetLine(1)[2]);
}
Enter fullscreen mode Exit fullscreen mode

We can say , no it is good we are making asserts against one output , but we are wrong each assert in the code below can fail and when it fails we want to know exactly where the error happens.
This is called Comparing Objects and it is a bad practise .

How To Solve This Problem

Read what Roy Osherove says :

Instead of adding multiple asserts, you can create a full object to compare against, set all the properties that should be on that object, and compare the result and the expected object in one assert. The advantage of this approach is that itโ€™s much easier to understand what youโ€™re testing and to recognize that this is one logical block that should be passing, not many separate tests

And He gives Us the solution to the the previous code with the code below

[Test]
public void Analyze_SimpleStringLine_UsesDefaulTabDelimiterToParseFields2()
{
   LogAnalyzer log = new LogAnalyzer();
   AnalyzedOutput expected = new AnalyzedOutput();

   //Sets up an expected object
   expected.AddLine("10:05", "Open", "Roy");

  AnalyzedOutput output =
   log.Analyze("10:05\tOpen\tRoy");

   //Compares expected and actual objects
  Assert.AreEqual(expected,output);
}
Enter fullscreen mode Exit fullscreen mode

Better isn't it ? ๐Ÿ˜† . I think you agree with me.

What I think About It

I Agree with the solution , even if for most part of my time i will go with 4 differents unit tests for the previous unit test , sometimes i do this bad practise when the case fully requires it or when the Arrange part of Arrange-Act-Assert is some kind of long. Sometimes we should be Pragmatic ;)

Tanks for reading ๐Ÿ˜Š

The Roy Osherove's Book

Discussion (0)