Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing image files with JUnit

I'm looking for direction on how to test that a dynamically generated image is the expected image with JUnit. A bit of background:

I have code that generates thumbnail images as java.awt.image.BufferedImage's and stores those BufferedImages into a java.io.File object.

I wrote a simple unit test to check a few key items in order to gain confidence that the generated image was correct:

@Test
public void testGenerateDefaultThumbnail() {
    File file = // someGeneratedFile.jpg

    assertNotNull(file);
    assertEquals(10211l, file.length());
}

Basically, I'm just confirming that the file size is what I expect.

This works fine locally on my machine (Mac OSX), but as soon as our tests run on our build server (Ubuntu), one of the tests is failing with the following:

java.lang.AssertionError: expected:<10211> but was:<10158>
  at org.junit.Assert.fail(Assert.java:88)
  at org.junit.Assert.failNotEquals(Assert.java:743)
  at org.junit.Assert.assertEquals(Assert.java:118)
  at org.junit.Assert.assertEquals(Assert.java:555)
  at org.junit.Assert.assertEquals(Assert.java:542)
  at c.v.t.ThumbnailTest.testGenerateDefaultThumbnail(ThumbnailTest.java:53)

Three part question:

  • Why may the file size be different for an image across OS's?
  • Is there a standard approach to unit testing image generation?
  • Should I change my approach to compare two File objects (where a pre-generated file exists as a resource in the project)?

Thanks!

like image 346
adchilds Avatar asked Jul 07 '15 20:07

adchilds


1 Answers

I would guess there's a difference in the metadata being written out? The image data is probably the same. If you only care about the image data and not the metadata for the image file you can just pull out the pixel data as a byte array.

this is probably a good idea anyway since comparing the entire file will be problematic since the metadata may have timestamps of the file generation which will break the tests.

If you already have the image as a BufferedImage you can just do this on the expected and actual variables.

//this gets the actual Raster data as a byte array
byte[] byteArray = ((DataBufferByte) bufferedImage.getData().getDataBuffer()).getData();

Then just compare the byte arrays for equality

assertArrayEqual(expectedArray, actualArray);

If you don't have the data as a bufferedImage yet it's easy to get it from a file

BufferedImage originalImage = 
                          ImageIO.read(new File("path/to/my.jpg"));

or InputStream

  try{
  BufferedImage originalImage = 
                          ImageIO.read(inputStream));
  }finally{
      //close inputstream
      inputStream.close();
  }
like image 55
dkatzel Avatar answered Oct 22 '22 03:10

dkatzel