Reputation: 641
I'm using Java's Graphics2D to generate a graphical representation of a graph. I'm also using ImageIO to write a PNG file. (ImageIO.write(image, "png", out);
)
I'm wondering how should I write JUnit tests to test whether the generated graphics is what is expected. I could pre-generate the PNG files but what if the font is a bit different on a different machine?
Upvotes: 9
Views: 3343
Reputation: 5867
I've found this to be effective at making rendered fonts identical cross-platform for pixel perfect graphics unit tests of simple things like text overlaid on a static image.
Font
and FontRenderContext
into the class rendering the fonts, so they can be controlled under test.Font.createFont()
to generate a font from the file.FontRenderContext
used. If you skip this step, the results do vary cross platform it seems.I'm curious if others think this is brittle or failure-prone for any reason, but I've had good results with it so far.
Upvotes: 1
Reputation: 1706
For me, this concrete implementation seems to work:
private void compareRasterImages(BufferedImage expectedPngIo, BufferedImage actualPngIo) throws AssertionError {
int minX = expectedPngIo.getMinX();
int minY = expectedPngIo.getMinY();
int maxX = expectedPngIo.getMinX() + expectedPngIo.getWidth();
int maxY = expectedPngIo.getMinY()+ expectedPngIo.getHeight();
assertEquals(minX, actualPngIo.getMinX());
assertEquals(minY, actualPngIo.getMinY());
assertEquals(expectedPngIo.getHeight(), actualPngIo.getHeight());
assertEquals(expectedPngIo.getWidth(), actualPngIo.getWidth());
for (int x_i = minX; x_i < maxX; x_i++){
for (int y_i = minY; y_i < maxY; y_i++) {
assertEquals(expectedPngIo.getRGB(x_i, y_i), actualPngIo.getRGB(x_i, y_i));
}
}
}
I retrieve the BufferedImage from my PNG (as byte[]) using ImageIO:
BufferedImage expectedPngIo = ImageIO.read(new ByteArrayInputStream(expectedPng));
enter code here
Upvotes: 2
Reputation: 76719
You could read all the RGB values of the generated images into an array and compare that 2D-array against one representing a pre-generated image, if you are really specific about the complete image.
If you wish to ignore the fonts, you could do the same for the same for regions of the image that do not contain any variable data depending on the environment where the images are generated. Building in correction and normalization routines for unit tests would be a waste of time, unless the application is expected to generate images of such high accuracy as warranted.
Upvotes: 1
Reputation: 106381
You could try testing for specific, known features of the output e.g.:
And/or you could write tests for some "aggregate properties" that allow for some fuzziness in the results:
Upvotes: 1