591 Numeric spell checker notes
Fall 2004, David Matuszek
Here are the answers to some questions that Gemma, Mirko, and I have received on the "Numeric Spell Checker" assignment.
The assignment said
Random random = new Random(); but it has to be
static Random random = new Random(); because you need to call this method from the static method
To get pseudo-random numbers for this assignment, use the method call
That is, call
nextInt with no parameters. This will give you the
full range of integers, from
Integer.MIN_VALUE (-2147483648) to
Integer.MAX_VALUE (2147483647). In general, about half of these
numbers will be negative.
Don't be surprised if most of your random numbers are extremely large (or extremely small). Remember that there are ten times as many integers with N+1 digits as there are with N digits. Thus, for example, an 8-digit number is a million times more likely to occur than a 2-digit number. Most of your numbers will have nine or ten digits.
How do you test whether the result of calling
really gives you random (actually, pseudo-random) numbers?
The short answer is, there really isn't any good way. Here's what I would test:
size> 1, are the first and last locations different from each other? Or maybe the first and second?
Someone suggested using a fixed seed for the random number generator while testing (so that you can know what numbers are in the array), then changing back to one that used the time of day for the "final" program. Don't do this! It's a bad idea for two reasons: (1) It involves making an untested change in a previously tested method, and (2) it breaks the test method, which will now report failure. One of the key points in having a suite of tests is that you can run them anytime, to make sure everything still works. Always keep a set of working tests!
What this method should do is create another "dictionary" array of
the same size as
numbers, and run through a loop to copy
numbers into this new array.
If, as is good practice, you make your instance variables private, then there is no easy access to the "dictionary" array, so testing becomes difficult. Here are some possible solutions, none of them perfect.
How can you tell that the "dictionary" array is a copy of
numbers, rather than a reference to numbers? Well, if you had easy access
to the "dictionary" array, you could use
But you don't have easy access. I'll leave this as a (fairly easy) puzzle for
you to solve.
Testing, like programming, is as much an art as a science. As you can see, there are tradeoffs, and you just have to pick the option that seems best.
This method is so simple, and so difficult to test, that maybe it isn't worth the effort. Still, I said to test it, so you should do something. You can at least check that you got back an array of the correct size.
Other methods are a whole lot easier to test if you know exactly what is in the "dictionary" array. That's why I separated the action of creating a random array from the action of creating a dictionary. Where possible, use a known array for testing your methods.
Here are some conclusions you might draw from all this:
Testing can be a lot easier if you design the tests first.
You can't test everything. (But with a little thought, you can test more than you might expect.)
It's best to have alternatives from which you can choose. Hence, you shouldn't always do the first thing you think of.
Writing the tests first may make the program better in some ways, but it also tempts you to make things public that really shouldn't be public.