Previously we were looking at testing random number distribution, which was a little complex. Before we wrap up on unit testing, I have one more test to include before we look at summing up unit testing.
Anything else worth testing?
So far we've checked that each number 1-6 occurs when we define a 6 sided dice. We've also checked over large data sets that each number comes up about 1/6 of the time within a tolerance.
Today's test is less obvious, simple, but really useful. Do only the numbers 1-6 come up? We want to check there's no occasional 0, 6 or anything else?
The way to do that is a modification of our test from yesterday - we'll run 600,000 times, and confirm all the values for 1, 2, 3, 4, 5 and 6 add up to 600,000.
@Test
public void noUnexpectedValues()
{
...
int totalRolls = 600000; int grandTotal = 0; ... //Add each value to the grand total for(counter = 0; counter < numSides; counter++) { grandTotal += countArray[counter]; } //If this fails, there must be some values outside of range assertTrue("Some dice rolls must be outside 1-6 range", grandTotal == totalRolls ); }
...
int totalRolls = 600000; int grandTotal = 0; ... //Add each value to the grand total for(counter = 0; counter < numSides; counter++) { grandTotal += countArray[counter]; } //If this fails, there must be some values outside of range assertTrue("Some dice rolls must be outside 1-6 range", grandTotal == totalRolls ); }
Running that we get ....
JUnit is really happy with that - which is probably the simplest test we've done so far!
When it unit checking appropriate?
Yesterday we were running a check that used 600 million dice rolls. Let me Bibically put that into perspective ...
In the Bible, it's said that soldiers at the feet of Jesus's crucification threw dice to divide up his possessions. Let's suppose for a moment that Jesus cursed them (although it would throw out all Jesus's teachings if he was that kind of a guy) to stay there until they'd rolled their dice 600 million times.
Well, they'd be there, assuming a roll every 2 seconds (I'm a wargamer, I know how long dice take to roll), then they'd be there for 40 years. With no sleep or toilet breaks.
But all this shows how in 2 seconds of unit testing we've achieved more than many years of real life experience. Okay - now let's assume we wanted to do the same test with a GUI check system. I know we've not really covered GUI checks yet. But as I've said a limiting factor vs unit checks is screen refresh.
Let's say we're able to reduce the screen refresh problem down to even 0.01 seconds. We're still looking at about 70 days to run the same test which it took 21 seconds on my machine. And believe me, my machine isn't state of the art, but you're welcome to donate me a Macbook Pro if you want.
[Knowing my luck - that will mean I'll be spammed with "Apple are giving aware free Macbook Pros, click here to find out more]
What this does show though is how much faster unit checks can be than GUI checks. If they're appropriate you can do checks which that are order of magnitudes faster than what you can achieve with GUI checks.
This leads back again to the third iron rule - we want always to make a check we want to run as simple as possible. If we want to run a lot of checks in the volume we did previously, it makes sense to run them where they are simplest and fastest - in the unit check area,
But there's a drawback
How many of you testers out there can see what's in your developer's unit tests? They're kind of squirreled away - you assume if it built, it must have passed, right?
We don't tend to make these things visible, but we should. Because as we've shown they can be useful at checking an aspect of the system in depth, and to a volume that's ordinarily unfeasible.
Extension material
Ask around your current project about the unit tests used. Can someone help you to see them? Can you suggest some?
If you're following with Eclipse, try writing some similar tests for 8 or 20 sided dice.
If you want a real challenge, create a parent class which rolls multiple dice, and create some JUnit tests for that.
Currently in our environment, due to legacy code, there are very few unit tests - hence there is a lot of responsibility on QA to perform all testing. However, the QA always assume this is the case and so develop tests anyway to assure themselves that they have sufficient coverage. If then a bug is found by QA, the question has to be - why did unit tests not find it!
ReplyDelete