Mobile Tech Talk

#TechTalk: Unit testing – better to be safe than sorry

Tech folks will agree that Unit testing and test driven development is a good concept but is seldom practiced. Its usefulness and importance is much eulogised by doyens like Bob Martin, Kent Beck et al.

I wanted share a relatively less talked about aspect of unit testing that I noticed when I set out to write input field validation lately, which allows developers to be a tad lazy and carefree.

As with many developers, I tend to copy-paste related implementations a lot and modify them to suit the current requirement. Sometimes, I fail to do all necessary changes and if luck is not on my side it manifests as very subtle bugs which are caught neither by compiler nor by QA. But, if you write adequate unit tests such inadvertent things will almost always get caught as a failing test. So, you can copy , paste and modify as needed relatively freely without fearing subtle bugs.

To give an example, I was validating Date Of Birth, which needed to have three post conditions:

  • Should be valid a date in strictly dd/mm/yyyy format
  • No future dates should be allowed
  • DOB should be such that current age should > 12 years

My test was like below and it passed.

[code lang=”js”]-(void)testDOBValidation{
XCTAssert([self.validator isValidDOB:@“09/06/1983”], @“Pass”);
XCTAssert([self.validator isValidDOB:@“9/6/1983”], @“Pass”);

XCTAssert([self.validator isValidDOB:@“29/02/1996”], @“Leap year test”);
XCTAssert([self.validator isValidDOB:nil] == NO, @“Pass”);

XCTAssert([self.validator isValidDOB:@“29-02-1996”] == NO, @“Only DD/MM/YYYY supported”);
XCTAssert([self.validator isValidDOB:@“29/02/96”] == NO, @“Only DD/MM/YYYY supported”);

XCTAssert([self.validator isValidDOB:@“29/02/2005”] == NO, @“Age should be minimum 12 years”);
}[/code]

 
But the validation code had a subtle bug where third post condition was not properly validated. However, my tests were passing, as you can notice, I was using invalid date 29/02/2005 to test age > 12 case. (same copy-paste problem). So, test was passing because it was invalid date. (First post condition)

Then, proceeded to added logic to report reasons for failing validation via error codes. I updated the test as below. Voila, the subtle bug was caught as the below test failed!

[code lang=”js”]XCTAssert([[self.validator lastValidationErrorsForType:kDOBValidator][0] isEqualToString:VAL_ERR_008 ],@“Age should be minimum 12 years”);[/code]

 

[code lang=”js”] -(void)testDOBValidation{
XCTAssert([self.validator isValidDOB:@“09/06/1983”], @“Pass”);
XCTAssert([self.validator isValidDOB:@“9/6/1983”], @“Pass”);

XCTAssert([self.validator isValidDOB:@“29/02/1996”], @“Leap year test”);
XCTAssert([self.validator isValidDOB:nil] == NO, @“Pass”);

XCTAssert([self.validator isValidDOB:@“29-02-1996”] == NO, @“Only DD/MM/YYYY supported”);
XCTAssert([self.validator isValidDOB:@“29/02/96”] == NO, @“Only DD/MM/YYYY supported”);

XCTAssert([self.validator isValidDOB:@“19/02/2005”] == NO, @“Age should be minimum 12 years”);
XCTAssert([[self.validator lastValidationErrorsForType:kDOBValidator][0] isEqualToString:VAL_ERR_008 ],@“Age should be minimum 12 years”);

}[/code]

 
Without unit testing, we would have spent frustrating time to chase down the bug when QA eventually managed to find it out, at a very later cycle of product development. Also, adding error codes needed some refactoring to the original validation code. With the safety net of unit tests, I was less apprehensive to do those refactoring.

Unit testing does take additional effort and time which need to factored in project planning. Agreed,unit testing is not a panacea and we need to deal with hard realities of life of resource and time crunch. However, when used judiciously for tasks for which it is apt, unit testing gives rich dividends.

An aside, I have encountered a query by a few as to whether unit testing is going to catch every single bug. My take is that life is too complicated and unpredictable for that to happen. In sport, injuries (sometimes fatal) happen despite wearing protective gear. But, that does not diminish the need to wear protective gear and take preventive measures – it is better to be safe than sorry!

H N Ramkumar
H N Ramkumar is a Technical Architect at Robosoft and has led the design & developments of many projects across Mac, iOS and Android.

Leave Your Comment

Your Comment*

Your Name*
Your Webpage