1

I have a program that is generating pseudo random numbers(Only lowercase, uppercase and digits are allowed).

/**
 * 
 * @return - returns a random digit (from 0 to 9)
 * 
 */
int randomDigits() {

    return (int) (Math.random() * 10);
}

/**
 * 
 * @return - returns a random lowercase (from "a" to "z")
 */
char randomLowerCase() {

    return (char) ('a' + Math.random() * 26);
}

/**
 * 
 * @return - returns a random uppercase (from "A" to "Z")
 */
char randomUpperCase() {

    return (char) ('A' + Math.random() * 26);
}

/**
 * 
 * @return - returns a random number between 1 and 3.
 * 
 */
char randomChoice() {

    return (char) ((char) (Math.random() * 3) + 1);
}

/**
 * 
 * @param length
 *            - the length of the random string.
 * @return - returns a combined random string. All elements are builder side
 *         by side.
 * 
 *         We use the randomChoice method to get randomly upper, lower and
 *         digits.
 */
public String stringBuilder(int length) {
    StringBuilder result = new StringBuilder();
    int len = length;

    for (int i = 0; i < len; i++) {
        int ch = randomChoice();
        if (ch == 1) {
            result.append(randomDigits());
        }
        if (ch == 2) {
            result.append(randomLowerCase());
        }
        if (ch == 3) {
            result.append(randomUpperCase());

        }
    }
    return result.toString();

}

How can i make a test for that code. I try to test the range for the digits (form 0 to 9)

    int minRange = 0;
    int maxRange = 0;

    for (int i = 0; i < 100000; i++) {
        int result = item.randomDigits();
        if (result == 52) {
            minRange++;

        } else {
            if (result == 19) {
                maxRange++;

            }
        }
    }
    LOGGER.info("The min range in the digit is 0, and in the test appeared: {}", minRange);
    LOGGER.info("The max range in the digit is 9, and in the test appeared: {}", maxRange);

But i cant find how to test the lower or upper?

P.Peev
  • 13
  • 1
  • 3

2 Answers2

2

Testing code which uses any randomness is tricky. There are two approaches you can take:

  1. Your test can have sufficient iterations that it has a good chance to show any errors in your logic. For many cases iterating 1000 or 1000000 times and checking consistency of the answers is reasonable. This is your only option if you are also looking to check some required distribution across a range.

This might look something like:

for (int i = 0; i < 1000000; i++)
    assertTrue(isValid(new RandomVal()));

If you want to check that all your characters appear at least once:

assertEquals(26 * 2 + 9, IntStream.range(0, 1000000)
    .mapToObj(n -> stringBuilder(6))
    .flatMap(String::chars)
    .collect(Collectors.toSet())
    .size());

This uses Java 8 and essentially adds every character (as an integer) to the set and then checks how large it is afterwards.

  1. Using a mocking framework (such as Mockito) to check the result is the expected one for specific outputs from whatever you are using to generate randomness. This is the best way to test that you get the correct result boundary conditions (i.e. the generator returning results at each end of its range).

This might look something like:

Random mockRandom = mock(Random.class);
when(mockRandom.nextFloat()).thenReturn(0.0f);
assertTrue(isValid(new RandomVal(mockRandom));
when(mockRandom.nextFloat()).thenReturn(1.0f - Float.MIN_VALUE);
assertTrue(isValid(new RandomVal(mockRandom));

For completeness it's worth doing both of these.

sprinter
  • 24,103
  • 5
  • 40
  • 71
  • I didn't get the mock /i'm new in the testing and etc./ But how to test the chars / upper and lower case/ or how to test the random string /asd2Ad/ – P.Peev Aug 17 '15 at 15:52
  • @P.Peev I'll add an example of tests for the range – sprinter Aug 18 '15 at 05:40
-1

If I understand your problem resolution is simple

    int minRange =  999999; //improbable big value
    int maxRange = -999999; //improbable low value

    for (int i = 0; i < 100000; i++) {
        int result = item.randomDigits();
        minRange = Math.min(result, minRange);
        maxRange = Math.max(result, maxRange);
    }

Please try it. If you don't like Math library you can of course do it without it

    for (int i = 0; i < 100000; i++) {
        int result = item.randomDigits();
        if (result < minRange) {
            minRange = result;
        }
        if (result > maxRange) {
            maxRange = result;
        }
    }
marekzbrzozowa
  • 314
  • 1
  • 3
  • 10
  • Doesn't even come close to addressing the problem. You're capturing the lowest and highest values found. OP is trying to count the 0 and 9. – Erick G. Hagstrom Aug 16 '15 at 22:33
  • well in that test i'm trying to see those it goes to max and min range(the 52 and 9 is for the make the test fail but it didn't ) – P.Peev Aug 16 '15 at 22:51