Thursday, October 7, 2010

JUnit and Jacoco

This past week, I had the pleasure of using JUnit and Jacoco for the first time in my career.  JUnit is a tool that helps developers to quickly perform white-box and black-box testing.  Jacoco is another tool that builds upon JUnit by providing code coverage reports.  In other words, Jacoco checks which lines of source code have or have not been executed during runtime or tested by JUnit.

In this post, I will share my experiences in creating tests for RobotFighter (version 1.0).  I created 2 acceptance tests, 2 unit tests, and 2 behaviorial tests.

Acceptance Tests:

  • RobotFighter vs. SittingDuck
    • Tested whether RobotFighter could beat SittingDuck every round.  This ensures that my robot is able to perform the basic functionalities of aiming and firing.
  • RobotFighter vs. SpinBot
    • Tested whether RobotFighter lost against SpinBot most of the time.  From my previous post, RobotFighter lost 79% of the time against SpinBot.  This confirms that improvements need to be made in the next version of RobotFighter.
Unit Tests:
  • Bullet Power
    • Tested if the function for determining bullet power was consistently above 0.25.  Anything below 0.25 could be deemed as "not worth it" because a robot is vulnerable for the period when it stays still to fire.
  • Random Generator
    • Tested whether the random number generator did indeed generate unique numbers most of the time.  This generator is used to determine how far RobotFighter will move.  By maintaining random travel distances, RobotFighter has a greater chance of beating robots that use predictive firing.
Behaviorial Tests:
  • Movement
    • Tested if RobotFighter moved at least once every 15 turns.  This is important in dodging bullets.
  • Firing
    • Tested if RobotFighter fired at least once every 50 turns.  A robot that does not fire often has a lower ability to beat other robots.

The acceptance and unit tests were by far the easiest to implement.  Behavioral tests were difficult to implement because it required a good understanding of the specifications and the background processes of Robocode itself.  

Originally, I wanted to test whether RobotFighter successfully exhibited the behavior of rushing towards the enemy when the distance was >= 150 pixels and moving away when the distance was <150.  However, this was extremely painful as I spent hours trying to figure out how to extract robot information during the middle of a turn.  I relied mostly on the onRoundStarted, onTurnEnded, and onBattleCompleted methods to implement the JUnit tests.  For this reason, I did not feel that my test cases adequately ensured the quality of my robot.

Jacoco indicated that my project had an overall code coverage of 95%.  Upon further inspection, Jacoco revealed a major flaw in the movement system of RobotFighter.  For example, RobotFighter is supposed to turn left when randomGenerator() % 2 == 0.  Based on the current formula for generating a random number (Math.random() + 0.27 * 100), this condition is never true, and thus, the line of code is never executed and RobotFighter never turns left.  Jacoco also revealed that the original structure of was unsuitable for testing.  In the future, I will separate different functions into different modules instead of lumping everything into the onScannedRobot method.  This will facilitate the ease of testing.

My project is available

No comments:

Post a Comment