Few tips for writing swift and effective unit test cases

05 / Jan / 2015 by Imran Mir 0 comments

To a beginner writing unit tests may seem to be an overhead and a low productive affair. But this could be due to the way he chooses to write tests. One can quite easily be productive at writing unit test cases as well. Following are a few things that I follow to write the spock unit tests cases in the grails application. I hope these tips may help you write the tests very swiftly and effectively:

1. While unit testing a piece of code, it may seem to be tedious to set up domain class objects, especially when the hierarchy involved is too deep. Infact it is, but in many cases the full object initialization may just not be needed. I have seen many people falling into this trap. Consider the following domain classes:

[code]
class ExaminationPaper {
String name
Integer marks
..
//other mandatory fields
static belongsTo = [student: Person]
}

class Person {
String name
String address
..
//other mandatory fields
}
[/code]
and the function to be tested is like:
[code]
String getGrade(Person student) {
Integer totalMarks = createCriteria().get {
eq(‘student’, student)
projections { sum(‘marks’) }
}
totalMarks /= 2
String grade = ""
if (totalMarks > 100) {
grade = "A"
} else if (totalMarks > 80 && count < 100)
grade = "B"

return grade
}
[/code]

To test the method, you just do not need to initialize every field of the person, just the id and marks will be fine, like this:
[code]
setup:
Person p = new Person(id: 1).save(validate: false)
new ExaminationPaper(id: 1, student: p, marks: 85).save(validate: false)
new ExaminationPaper(id: 2, student: p, marks: 80).save(validate: false)
when:
..
[/code]

2. All the clean code principles that stand true for the application code are also true for the test code. For example, it helps to create a CommonSpec which is extended by other specs. The CommonSpec contains some common utility methods which are repeated across specs. Some common initialization may go into it.
[code]
class CommonSpec extends Specification{
void initializeCurrentUser(){
//your code
}
}
[/code]

Similarly, it also becomes mandatory to refactor the tests to keep them readable and manageable as the test code grows.

3. Sometimes we just need to run just one test case in a test file, and ignore rest to save time. All we need to do is to add the annotation @IgnoreRest (spock.lang.IgnoreRest) on top of the test case you want to run. All other test cases will be ignored. Isn’t it fast. But, beware there lies the pitfall of forgetting to remove the annotation once you are done and you may end up ignoring all other test cases in the class after checking the test file into the VCS. I usually add a todo alongside the annotation reminding me to remove the annotation.

4. To run the tests using the command grails test-app unit: while writing test cases is wasteful. Try grails Interactive mode to run the test cases. To do so you just type the grails command and hit Enter:
[code]grails[/code]
and then just type
[code]grails> test-app unit: SomeClassName[/code]

Next time, after editing, you can just use the arrow keys to repeat the previous test command.

5. You can even create an alias for the long test-app commands using:
[code]
grails alias rut test-app unit:
[/code]
So now you can just write
[code]
grails> rut SomeClassName
[/code]

6. Adding Code Coverage plugin can help to write effective unit tests, as you can easily visualize which lines or parts are tested and which ones or parts are not. It also can keep you focussed and motivated as you can also see the percentage of code covered in the tests.

Apart from the #1, all of these are also applicable for Integration and Functional tests as well.

Hope this helps.
Imran Mir
imran[at]intelligrape.com

FOUND THIS USEFUL? SHARE IT

Leave a Reply

Your email address will not be published. Required fields are marked *