Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

My Sprite class has a method:

private void updateWithBitmap(Bitmap b, int x, int y)

This will 'lay on top' the bitmap that's passed in, the top left corner of the passed in bitmap being at the x,y position of the parent bitmap.

Now I want write unit tests to check that this method is working correctly.

For example, we'll need to check that an exception is thrown when the passed in bitmap is larger, or is out of bounds of the parent bitmap.

    [TestMethod]
    [ExpectedException(typeof(System.ArgumentOutOfRangeException))]
    public void TestUpdateWithBitMap_SmallerParent_ThrowsOutOfRangeException()
    {
       Sprite parent =  new Sprite(new Bitmap(10,10));
       Bitmap child = new Bitmap(20, 20); 
       parent.updateWithBitmap(child,0,0)


    }

    [TestMethod]
    [ExpectedException(typeof(System.ArgumentOutOfRangeException))]
    public void TestUpdateWithBitMap_PassedBitMapOutOfBounds_ThrowsOutOfRangeException()
    {
        Sprite parent =  new Sprite(new Bitmap(10,10));
        Bitmap child = new Bitmap(3, 3); 
        parent.updateWithBitmap(child, 9,9)


    }

Good so far.

But also we want to test that the method genuinely is updating correctly.

enter image description here

For example, if the left most image is our parent bitmap, and the middle is the child bitmap, and we call our method with:

parent.updateWithBitmap(child, 3,3);

we get the rightmost bitmap as a result.

The question is:

Is it appropriate to store these bitmaps as resources, and then check the results are equal?

eg.

    [TestMethod]        
    public void TestUpdateWithBitMap_UpdatesCorrectly()
    {
        Sprite parent =  new Sprite(Properties.Resources.TestBitmapParent1);
        Bitmap child = Properties.Resources.TestBitmapChild1; 
        parent.updateWithBitmap(child, 3,3)
        #something like Assert.Equal(parent.getBitmap(), Properties.Resources.TestBitmapResult1); 



    }
share|improve this question

3 Answers 3

  > Is it appropriate to store these bitmaps as resources, 
  > and then check the results are equal?

In my opinion i would say yes, but instead of coding these comparisons yourself i would use approvaltests for dotnet or java for this.

So instead of hiding the bitmap-comparison behind a junit-testmethod the approval test shows every test-result where the bitmaps are not equal any more to the tester, who can decide this result is ok or is not ok. if it is ok the expected result is overwritten.

so on the next run the approvaltest will not complain any more.

share|improve this answer

Is it appropriate to store these bitmaps as resources

Well, whatever will work for you is appropriate, isn't it? Your unit tests should run quick, be functional, should be easy to maintain and to extend, and if they fail, they should make root cause analysis easier for you.

  • "quick" can be fulfilled by using very small bitmaps

  • "functional": to include significant cases, the bitmaps must be actually not too small. For your case, I guess bitmaps with a side length of minimum of 3 or 4 will probably make sense.

  • easy to maintain and to extend: well, as long as your tool set allows easy bitmap manipulation, storing of bitmaps in a resource and retrieving it again, that should not be much of an issue

  • "make root cause analysis easy": for this, you may have to make some provisions. If you just "check if the results of a bitmap comparison are equal", you might not easily see how your "testBitmap" looks like and why it does not match the expected results. But it should be pretty simple to add some code which in case the equality test fails, writes your test bitmap to disk so you can check it easily with an imager viewer (either just visually, or by creating something like a "difference image" between the expected bitmap and your test bitmap)

Of course, the alternative would be to create some per-pixel tests with hard-encoded colors and coordinates, but though that will surely work, IMHO that's not easier to maintain and can become very tedious.

Some related posts on other SE sites:

http://stackoverflow.com/questions/16217982/comparing-images-as-byte-arrays-for-unit-tests

http://sqa.stackexchange.com/questions/3136/how-to-test-the-graphical-contents-of-a-bitmap-or-a-pdf-file

share|improve this answer
    
I agree that per-pixel unit testing could be a burden and an overkill. But how do you suppose to test some real DSP methods, complex transformations? Using your eyes isn't the best idea either. –  Eugene Podskal Jun 20 at 6:34
    
@EugenePodskal: well, "DSP" or "complex transformation" is not the scenario of the question. Don't get me wrong. I don't suppose to check the unit test results visually in each run of the test, only when it fails. And if I say visually, I mean you can always use the "visual diff" capabilities of your favorite imaging tool. –  Doc Brown Jun 20 at 7:34
    
Nonetheless it won't be the actual unit testing(you yourself have described their main qualities in your post). But your idea is very good and easy applicable for most tasks that do not require any rigid and formalized procedures. –  Eugene Podskal Jun 20 at 7:40
1  
+1 Great Scott! –  Pureferret Jun 20 at 8:13
    
@EugenePodskal: Well, if the images tend to fail binary equality tests due to complex, mostly imperceptible (to humans) differences, a diff that tests for near-equality might work. E.g., PerceptualDiff. If your application supports dependency injection, injecting a randomization service with hard-coded values or seeds should allow your system to maintain binary equality (well, unless randomness is also introduced by parallelization artifacts and the like). –  Brian Jun 20 at 18:43

As I understand you are using your own custom sprite and not some sprite from DirectX or from DirectXMobile.

What you could try:

1) If your class provides some per-pixel indexer like SomeColorInfo this[int x, int y] or the ToBitmap() method:

You could try to use small parent and child (like few pixels per few pixels) where you could manually calculate all desired pixels and compare resulting and desired images(sprites). For example, supposing for simplicity that you are using greyscale pictures:

[TestMethod]
void Test_Sprite_UpdateWithBitmap_GreyScaleSprite3x3_GreyScaleBitmap2x2()
{
    // Create 3 x 3 greyscale Sprite from 
    Sprite sprite = new Sprite(3, 
    3, 
    new Byte { 
    1, 2, 3,
    4, 5, 6,
    7, 8, 9});

    // Create 3 x 2 bitmap to update with
                Bitmap bitmap = new Bitmap(2, 
    2, 
    new Byte { 
    101, 102
    103, 104});

    // Coordinates of update point
    Int32 x = 1;
    Int32 y = 1;

    // Expected sprite
    Sprite expectedSprite =  new Sprite(3, 
    3, 
    new Byte { 
    1, 2, 3,
    4, 101, 102,
    7, 103, 104});

    // Update  sprite
    sprite.updateWithBitmap(child, 3,3);

    // Assert
    CollectionAssert.AreEqual(expectedSprite, sprite);
}

Well your sprite and bitmap should have constructors like Sprite(Int32,Int32, IEnumerable<Byte>); and your Sprite should be IEnumerable(you will just have to make sprite.ToList() in assert) or ICollection

2) If your sprite cannot be calculated(painted) other than in the actual user interface environment or you do not want to add some unneeded members, you should consider some way to get his pixels through other channels. I don't know what UI you use, but most of them provide some sort of a PaintingContext for your custom painting objects. Such an object can be an interface like:

public interface IPaintingContext : IDisposable
{
    void PutPixel(Int32 x, Int32 y);

    void PutImage(IImage image);

    //... And so on
}

that will allow you to mock it and use in your test method like:

...
IPaintingContext expectedPaintingContext = new MockPaintingContext(3, 3, new Byte[]{...});
...
IPaintingContext paintingContext = new MockPaintingContext();
...
sprite.PaintOn(paintingContext);
...
CollectionAssert.Assert(expectedPaintingContext, paintingContex);

If your environment provides such functionality in a not an interface way, then you could create your own custom infrastructure of a such kind: IPaintingContext context = new MyUiPaintingContextWrapper(UI.GetPaintingPlane())

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.