Testing graphics generation with JUnit

淺唱寂寞╮ 提交于 2020-02-01 22:33:06

问题


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?


回答1:


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?



回答2:


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



回答3:


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.




回答4:


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.



来源:https://stackoverflow.com/questions/3400660/testing-graphics-generation-with-junit

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