Let’s say this is my code:
public void render(){
GL11.glClearColor(0, 0, 1, 1);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glColor3f(.5f, .5f, 1.0f);
GL11.glBegin(GL11.GL_QUADS);
GL11.glVertex3f(0,0,0);
GL11.glVertex3f(50,0,0);
GL11.glVertex3f(50,50,0);
GL11.glVertex3f(0,50,0);
GL11.glEnd();
}
How can I write a unit test to make sure the square was drawn where it should be and at the right color? Should I also be testing things like, the screen gets cleared on each frame? I was thinking that I’d abstract the openGL code away from the my square code. In other words, I’d create a class that creates “vectors” and then its render function would draw to screen and I wouldn’t test that. However, you SHOULD test every public function. Sooo I guess it comes back to: well how can I tell what was drawn on screen in openGL?
Also, now that I think about it, I shouldn’t really be running my app every time I run the test, which presents another level of complexity potentially…
Absolutely, you’ll need to wrap the GL11 library in another adapter, then mock that adapter out. Then you can show that your class passes the correct coordinates, and the right colour. (Or you could use PowerMock, but honestly, I like Mockito and mocking interfaces better).
If you use a vector abstraction, you could do the same thing to test that too. The wrapper to GL11 should be small enough and simple enough that you can verify it’s correct just by inspection, as you won’t be able to unit-test that without actually drawing on a screen. I would only create that additional abstraction if you use it elsewhere.
As far as showing that the class is “correct”, and draws the square in the “right” place, Matt’s right in that testing rendering behaviour is difficult, and testing aesthetics IMO should only be done manually. With that in mind, if you don’t create the vector abstraction you could just check that the distance between coordinates is the same, so that it’s a “square”, then call it a day, as this helps you keep the test flexible and easily change the size and color of the square if you need to.
These are just options. Automated testing is no substitute for manually testing at least once. If the behavior you’re looking at is something you’d always check manually each time you change it anyway, and it’s abstracted away from anything that might affect the behavior (so nothing can create regression bugs), don’t worry so much about creating a unit test for it and just verify it manually.