Wednesday, October 7, 2009

Verifying StrafeNShoot's Strategy: Failure

The topic for this week in my Software Engineering class was about building test cases using JUnit and verifying certain aspects of my robot, StrafeNShoot. The aspects in question for movement, firing, and targeting strategies.

Here's a quick recap of StrafeNShoot's strategy:

Movement: Moves in a four corners style, starting from the upper left, lower right, upper right, then lower left. I chose this movement pattern because although it doesn't seem random, it provides a good path for my robot to always be in motion.

Targeting: The gun is initially positioned at the rear flank of the robot as it moves. When StrafeNShoot sees another robot, it attempts to keep an active lock on the target, while still maintaining it's movement patter.

Firing: As long as there's an enemy in it's sights, fire at will.

The assignment details can be found here. We were to create 6 test cases, at most 2 of them could be acceptance tests, which merely checked to see if StrafeNShoot could consistently beat another robot; behavioral tests, which tests the movement, targeting, and firing strategies; and lastly unit tests, to verify that the output of these methods were correct.

Sadly, I was only able to create 2 out of the 6 requried for the assignment, 2 of which acceptance tests.

The easiest of the tests were obviously the acceptance tests, mainly because Prof. Johnson had already included such a test in his pmj-dacruzer file which was easily adaptable, but also there was no real calculation involved, nor did I have to modify the source code of StrafeNShoot.

When it came time to implement a test for behavors, I began thinking of how I could test if StrafeNShoot does in fact move to the four corners. I then realized there was no concrete test I could do that would test for this, as StrafeNShoot "attempts" to move in the four corners style. It's possible that throughout the entire battle that StrafeNShoot will never reach a corner, since the way I coded the movement, if StrafeNShoot runs into another robot, it immediately attempts to go to the next corner without reaching the one it was trying to get at.

As for unit tests, it was hard to think of a solid unit test that I could use. The main problem with the unit tests was that I could not find a way to directly access StrafeNShoots internal variables. The trigonometry I used to calculate to turn to a corner, which would have been an ideal choice to verify, was hard coded into StrafeNShoot's source code. And the only way for me to verify the angle was correct, was by using the exact same steps I used to calculate the angle in the first place. There were other issues such as verifing that StrafeNShoot would correctly calculate the angle to turn towards the enemy.

With my test cases seriously lacking, I can firmly say that my test cases do not adequately ensure the quality of my robot. Sure it has the capacity to beat other robots, but being able to verify it's strategy without actually watching the battlefield is a whole nother problem.

For my EMMA coverage, there isn't much to tell, overall my block coverage was 43% and line coverage was 55%. But I've uploaded the whole results, which can be viewed here.

When I first started working with Robocode, I had no idea that the analysis would get this deep, I thought that the only thing that matters was coming up with a unique strategy, and beating other robots. But now, even if you have a unique strategy, it can be a pain trying to verify the things it does. When I decided to implement my strategy for StrafeNShoot, I did not code in modules, or even think about refactoring certain pieces of code. It ran sufficient enough to not look twice. But after this week, it shows how much modules, organization, and coding with verification in mind can lead to a well documented, quality source code.

My distributed StrafeNShoot package with it's lone, 2 test cases, can be downloaded here.

No comments:

Post a Comment