Search code examples
junitlarge-data

Testing large input range scenarios with JUnit


I am pondering on how it is best to develop a JUnit test for a function that calculates a number of points and values in time based on a number of inputs. The purpose of the method is to calculate a series of points in time given a series of gradient value pairs, i.e.

Gradient 1 to Value 1, Gradient 2 to Value 2, Gradient 3 to Value 3, and so on...

Given a starting point in time and starting value, the function calculates the points in time each Value is reached (in the gradient value pairs) up until a target value is reached. This is essentially to plot a line on a graph with x-axis having date values and the y-axing having numeric values.

The method to test takes the following inputs:

  • StartTime (Date)
  • StartValue (Double)
  • TargetValue (Double)
  • GradientValuePairs (ArrayList)
  • EnsurePointEvery5Minutes (Boolean)

Where GradientValuePair is like:

class GradientValuePair {
    Double gradient; // Gradient up to Target
    Double target;
    ...
}

The output from this method is essentially ArrayList - a profile - with:

class DatePoint {
    Date date;
    Double value;
    ...
}

The EnsurePointEvery5Minuntes parameter basically adds a date point every 5 minutes for the calcualted profile which is then returned by the method.

To ensure the test has worked I will need to check each date and value is to what is expected by either:

  • Iterating through the array with an array of what is expected.
  • Store minute/second offsets from the StartTime with the expected value in some sort of structure.

Now the difficult part for me is deciding on how to write the TestCase. I want to test a broad/diverse range of inputs so that:

  • StartTime will cover 30 minutes i.e. in range of 2012-03-08 00:00 to 2012-03-08 00:30.
  • StartValue will be in the range of 0 to 1000.
  • TargetValue will be in the range of StartValue to 1000.
  • GradientValuePairs will require around 10 different arrays to be tested.
  • EnsurePointEvery5Minutes will be tested with both true and false.

Now given the number of different input sets will be something like:

30 * (0 to 1000 * 0 to 1000 = 500500) * 10 * 2 = 300,300,000 different test input sets per GradientValuePairs input

Or call us crazy for wanting to do this. Maybe the tests are too diverse for this instance.

I am wondering if anybody has any advice for testing such scenarios like this. I can't think of any other way to do this than implement my own algorithm for calculating the output before each call to the method I am testing - then who is to say that the algorithm I implement to test it is correct.


Solution

  • If I understand correctly. you are proposing that you test every possible set of combination of numeric inputs. That is almost never required of unit tests, as it would be essentially equivalent to testing whether the Java math library works for all numbers for all operations. Generally what you will do is try to identify edge conditions and write tests for those. These would include things like 0's. negatives, numeric overflow, and combinations of inputs which have intermediate computations that result in the same things. Then of course, you would want to test a handful of normal vanilla cases of data as well that are not edge cases.

    So short answer: no you should not need to test 300M+ input sets.