Testing graphics generation with JUnit

﹥>﹥吖頭↗ 提交于 2019-12-05 03:04:18

You could try testing for specific, known features of the output e.g.:

  • It there a white pixel at (100,100)?
  • It the border completely black?
  • Is the image the expected size?

And/or you could write tests for some "aggregate properties" that allow for some fuzziness in the results:

  • Does the image at least 90% match the reference image? (to allow for different fonts, antialiasing differences etc.)
  • Is the most common colour in the image equal to the background colour?

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

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.

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.

  1. Inject the Font and FontRenderContext into the class rendering the fonts, so they can be controlled under test.
  2. Supply a .ttf file to the unit test and use Font.createFont() to generate a font from the file.
  3. In the unit test, disable anti-aliasing in the 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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!