Unit testing graphics code

I recently worked on a project that involved heavy use of custom graphics.  Specifically, lots of lines.  The code was sufficiently important and complex that it needed to be unit tested.  However, I had never unit tested drawing code before.

A simple strategy would be to paint to an image, then compare the result with a target image.  However, this has a few disadvantages:

  • It’s impossible to tell if unnecessary graphics calls were made (outside the clipping region, for example).
  • Graphics may render slightly differently on different platforms.
  • This can tell you where the output image is wrong, but it does not automatically tell you which part of the test failed.

I decided to mock a Graphics object and check that various calls were correct.  To avoid writing a lot of boilerplate code to keep track of color, line style, clipping, etc., I created a GraphicsProxy class, added a base field, and used Eclipse to generate methods that pass the call on to the delegate.  (This would have been perfect for the Proxy class, but Graphics is an abstract class, not an interface.  Poor foresight on the part of the original writers, but I digress.)

This proxy class is then subclassed to count calls to drawLine and drawPolyline, and to keep track of the line segments drawn.  I also wrote a LineChecker class to compare the expected line segments with the actual line segments.  This is slightly trickier than it might sound, because the segments may be drawn in a different order, and the endpoints of individual segments may be switched.  All in all, a test method looks like this:

public void testPaint() {
	BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_3BYTE_BGR);
	Graphics2D imageG = image.createGraphics();
	CountingGraphics g = new CountingGraphics(imageG);

	// draw here

	LineChecker c = new LineChecker();
	c.require(19, 180, 19, 160);
	c.require(19, 160, 39, 160);
	c.require(159, 40, 159, 20);
	c.require(159, 20, 179, 20);

Here’s the code:

One Comment

  1. Posted July 12, 2020 at 11:46 pm | Permalink

    I do believe all the ideas you’ve offered for your post.

    They’re really convincing and can definitely work.

    Nonetheless, the posts are very short for novices. Could
    you please extend them a little from subsequent time? Thanks for the post.

Post a Comment

Your email is never shared. Required fields are marked *