Friday, October 8, 2010

19.RoboTesting

Testing Bubonic with JUnit was an interesting experience. After you figure out how JUnit works, using ant with the command line and through eclipse, and jump through all the configuration hoops, you can finally think about how you wish to test your robot.

I found that the acceptance tests were the easiest to create. Since my robot was able to beat Walls and SittingDuck 100% of the time, I did not have to extensively modify the sample test case, provided by Professor Johnson. These tests were valuable to insure that my robot had a baseline standard and was affective against both a trivial robot and a not so trivial robot.

The second easiest tests to create were the Bubonic simple movement behavioral tests. Since Bubonic’s strategy heavily relies on hugging a wall and scaling up and down, I thought these would be good tests to create. Thus, I had two cases that I wanted to test for: the robot seeking the left or right wall, and the robot moving to the top and bottom of the map (this case is dependent on another robot’s movement).  These were easy to test for in that it simply came down to a simple the position checks. The RobotSnapShots were enough to get the position of the robot at the end of a round. From these snapshots, I was able to use the getX() and getY() functions to find out whether my robot was indeed on a wall, and if it made it to the top or bottom of the map, respectively. These tests were valuable in that I wanted to make sure that the intended movement actually occurred and thus would be a good type of test to run. It should be noted that the vertical movement of Bubonic is dependent on an enemy robots movement so for that particular test case, the sample.Walls  robot was used to promote Bubonic’s movement. The Jacoco coverage for the horizontal movement test and the vertical movement test were 92% and 98%, respectively.

The hardest tests to create involved the testing for more specific behaviors. Since some of Bubonic’s behaviors are fairly complicated, the test cases became proportionally complicated to design. One test I wanted to check was whether my radar swept the top and bottom of the battlefield at least once after the robot reached the left or right wall and was moving vertically.  Since an enemy’s robot movement determines my robot’s vertical movement, I needed to load an enemy robot that moves unconditionally (not SittingDuck). Thus, I used test subject, Walls again, to generate the typical movement done by Bubonic. The test case only checked the radar heading after the robot has gotten into its specific position and is doing the intended movement. In retrospect, I could have spawned the robot on one of the sides of the map, but it would still initiate the same algorithm of movement. This was a valuable test in that proper scanning of the field insures that Bubonic knows where all the robots are.  Assuming that the radar alternates between 0 and 180 degrees, it wasn’t hard creating a boolean that would store whether the 0 or 180 case had been reached upon the end of a turn. The Jacoco coverage for the radar sweep test was 99%.
  public void onTurnEnded(TurnEndedEvent event) {
    IRobotSnapshot robot
= event.getTurnSnapshot().getRobots()[1];
    
double currentRadarHeading;
    
double xPos = robot.getX();
    
//Checks to see if the robot is on either the left or right wall
    
if (xPos < 40 || xPos > (width - 40)) {
      robotOnWall
= true;
    
}
 
    
if (robotOnWall) {
      currentRadarHeading
= Math.toDegrees(robot.getRadarHeading());
      
if (currentRadarHeading == 0) {
        radarHasSweptTop
= true;
      
}
      
else if (currentRadarHeading == 180) {
        radarHasSweptBottom
= true;
      
}
    }
  }
The hardest test involved checking if Bubonics intended behavior would be triggered by a stationary target. In theory, Bubonic should stop and fire at this target with the hardest bullet until the target starts moving again. So the test subject for this experiment was SittingDuck. The method I used involved the comparing of an initial radar heading with a previous radar heading to see if the radar has not moved. If the values are equal, it can be assumed that the radar has locked onto a target. Then it is a necessary check to see if Bubonic’s gunheat is increasing, which shows the Bubonic is indeed firing at the target. The Jacoco coverage for the stationary target behavior test case was 99%.
  public void onTurnEnded(TurnEndedEvent event) {
    IRobotSnapshot robot
= event.getTurnSnapshot().getRobots()[1];
 
    
double currentRadarHeading;
    
double xPos = robot.getX();
    
//Checks to see if the robot is on either the left or right wall
    
if (xPos < 40 || xPos > (width - 40)) {
      robotOnWall
= true;
    
}
 
    
if (robotOnWall) {
      currentRadarHeading
= Math.toDegrees(robot.getRadarHeading());
      
if (previousRadarHeading == currentRadarHeading) {
        radarIsNotMoving
= true;
        
checkGunHeat(robot.getGunHeat());
      
}
      previousRadarHeading
= currentRadarHeading
    
}
  }
The overall coverage for my test classes, as well as the Bubonic robot itself was pretty good. I had done some intensive testing on my robot vs. various other robots at high speed before the robocode competition to figure the weaknesses of my robot. Had I known how to successfully implement JUnit test cases, I think I could have further optimized my robot. I feel though, however, that my robot is fairly simple. Thus it was fairly easy to test. Had I created an advanced robot with really advanced features and behaviors, testing would not have been as straightforward. A link to my project file can be found here.


No comments:

Post a Comment