Unit tests are a a great way to ensure that a function behaves as intended and returns the expected result. The idea is to only test a specific function or method and thus ensure the reliability of a small brick in the wall, which shall not be tested all over again and again by the user.
Anyone has already recognized the necessity of Unit Tests and of course you are aware of them, nevertheless, we want to mention them again for the sake of completeness. In the software testing pyramid Unit Tests bear the largest amount of test cases being written.
Of course, certain constraints have to be regarded and especially edge cases have to be handled. If a software engineer is not able to define these edge cases, as a consequence the unit test itself might not be considered functional.
It would be even better if the software engineer would not have to figure out all the edge cases oneself. Instead, specifications, requirements or acceptance criteria should have already been defined.
Example Password Form
The following example shall simply illustrate the approach and the benefits you gain from writing unit tests. Of course, password field validators are always a topic for discussion: still, I think it’s an easy example to illustrate the approach.
Most favorite – feedback from password validators: “Password not strong enough”. Not strong enough by specification. And specification may vary.
As an example, in our password field we will only allow numbers and letters (capital and small ones). Including a minimum (5) and maximum length (10)
One would now implement a user’s password form field, which is related to a certain function, which validates its input. We could go on and type all password combinations one can think of.
- abcd1 (valid)
- abcde (invalid)
- 12345 (invalid)
Nevertheless, a lot of edge cases are not covered and additionally, it is a bit annoying to type all these strings into the form field by hand.
But the solution is quite obvious: simply implement two kinds of lists (valid passwords and invalid passwords) let a unit test run and validate the given return value of our validation function.
Of course it is not always that easy to figure out all possible types of text inputs. But luckily, most of the time the constraints of the given input are well specified.
- Small Letter Type
- Large Letter Type
- No special characters
- At least one character
Way easier to test all possible combinations of a user’s input. Thus more reliable and most of the time less time-consuming. If you even want to, you can now simply extend the validator function with specific return values, what of the password was not correct: length, character types, etc.
And best of all: you only need few lines of code to easily evaluate the code written and can just maintain as fast as this your functions in case there are changes being made required.
For illustratuon purposes, i have added some „old-fashioned“ Objective-C code for the above test case.
Ow, and please: As we do not want to build the tests‘ required property lists into our productive application: set the plist’s target to only be the test’s target ;-)
// make sure that we load the property list for the specific test target, which got this file added before
NSString *passwordsListPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"passwords-invalid" ofType:@"plist"];
NSArray *passwords = [NSArray arrayWithContentsOfFile:passwordsListPath];
for (NSString *str in passwords)
XCTAssertFalse(stringIsValidPassword(str), @"Password [ \"%@\" ] is considered as being valid, it should be invalid", str);