Sometimes, you do have to test randomness

Alonso Del Arte
3 min readOct 12, 2023

--

Photo by Free Walking Tour Salzburg on Unsplash

“You shouldn’t write a JUnit test for randomness,” Bob said to Alice. “You have no control over the random number generator,” he added. Bob felt very proud of himself for saying that, thinking he had just said something very profound that Alice would be eternally grateful for.

Bob knows that the Java Runtime Environment (JRE) and the Java Development Kit (JDK), like most everything else for general purpose programming, provide for the generation of pseudorandom numbers.

But Bob assumed that Alice was testing something that’s already provided in the JDK. And he was wrong. She was testing a function that chooses an emoji out of a certain category pseudorandomly.

The JDK doesn’t provide that function, so Alice had to write it herself. Specifically, she needed food symbol emoji, such as “🍟” (U+1F35F) or “🍪” (U+1F36A).

Those symbols come from the Miscellaneous Symbols and Pictographs block in Unicode’s Supplemental Multilingual Plane (SMP). The first one is “🌭” (U+1F32D) and the last one is “🍿” (U+1F37F). But Alice might want to skip symbols like “🌲” (U+1F332) and “🍽” (U+1F37D).

Also, the Supplemental Symbols and Pictographs block (also in the Unicode SMP) has other emoji Alice might want to use, like “🥐” (U+1F950), “🥑” (U+1F951), etc.

How will Alice’s random food emoji function deal with all these scattered food emoji and produce them with a reasonably random distribution?

Maybe her function assigns a number to each range of consecutive emoji that she wants to use, uses java.util.Random’s nextInt() function to choose a range ID, then nextInt() again to choose a number in the range.

The problem with that is that emoji from smaller ranges might be selected more frequently than emoji from larger ranges. For example, “🍿” might come up way more often than in any character in the previous range if Alice decides to isolate it from “🍾” (U+1F37E), since “🍿” would be in a range by itself.

Alice might instead tally up the total number of emoji her function can draw from, have it call nextInt() just once to come up with a number at least 0 and less than the total number, then use a helper function to map that pseudorandom number to a food emoji.

Also consider that Java’s char primitive type is limited to the characters of Unicode’s Basic Multilingual Plane (BMP). So Alice might need to figure out how to decompose the emoji from the SMP into pairs of high and low surrogates from the BMP.

In short, there are a lot of things that can go wrong with Alice’s random food emoji function, and those things are all within Alice’s control.

Therefore, it makes sense for her to write tests to ensure her function returns the characters she wants with the frequency she wants.

More generally, any time you want something fancier than pseudorandom numbers from a single range of consecutive integers, you need to test randomness.

Also, Bob assumed that Alice was using JUnit, when in fact she was using TestNG. Both JUnit and TestNG are readily available from within Apache NetBeans and JetBrains IntelliJ IDEA.

Whether or not Bob learns anything from this experience, I don’t know. Hopefully we do.

--

--

Alonso Del Arte
Alonso Del Arte

Written by Alonso Del Arte

is a Java and Scala developer from Detroit, Michigan. AWS Cloud Practitioner Foundational certified

No responses yet