Reputation: 6551
I want to do a batch test like the following, however if there is an error, it does not tell me which value of i
the error occurs in.
@Test
public void simpleMovingAverageBatch() {
for (int i = 1; i < 61; ++i) {
simpleMovingAverage(i);
}
}
public void simpleMovingAverage(int days) {
double sma = -1;
int size = stock.getCloses().size();
stock.calcSMA(days); // <- code that I'm testing
// first days should be -1
for (int index = size - 1; index >= size - days + 1; --index) {
assertEquals(-1, stock.getSMA(days, index), 0.001);
}
for (int index = size - days - 1; index >= 0; --index) {
sma = 0.0;
for (int i = 0; i < days; ++i) {
sma += stock.getCloses().get(index + i);
}
sma /= days;
assertEquals(sma, stock.getSMA(days, index), 0.001);
}
}
This is an example of what happens if I run the code as is:
This is an example of what I want to have happen:
I've taken a look at Parameterized Tests in this tutorial, however I do not know if this the route I want to take.
Any tips?
I don't think this question is a duplicate of these:
Running the same JUnit test case multiple time with different data
Java unit test for different input data
Upvotes: 4
Views: 4338
Reputation: 5093
Durron's answer leads to parameterized JUnit tests via @Parameters
. This is a great answer and fits the question perfectly. However, I've been down that road and found it created complicated and hard to read tests.
Theories are an alternative within JUnit: https://github.com/junit-team/junit4/wiki/Theories
If you are willing to stray from JUnit, testNG's dataproviders are quite versatile: https://testng.org/#_parameters_with_dataproviders
Upvotes: 2
Reputation: 281
Try JUnitParams. Your test will look like:
@RunWith(JUnitParamsRunner.class)
public class ExampleTest {
// this method provides parameters for simpleMovingAverage
public static Iterable<Integer> parametersForSimpleMovingAverage() {
return IntStream.rangeClosed(1, 61).boxed().collect(Collectors.toList());
}
@Parameters
@Test
public void simpleMovingAverage(int days) {
double sma = -1;
int size = stock.getCloses().size();
stock.calcSMA(days); // <- code that I'm testing
// first days should be -1
for (int index = size - 1; index >= size - days + 1; --index) {
assertEquals(-1, stock.getSMA(days, index), 0.001);
}
for (int index = size - days - 1; index >= 0; --index) {
sma = 0.0;
for (int i = 0; i < days; ++i) {
sma += stock.getCloses().get(index + i);
}
sma /= days;
assertEquals(sma, stock.getSMA(days, index), 0.001);
}
}
And when you run the test, you will have a report like you wanted to have. Even better, unlike standard JUnit Parametrized runner JUnitPramsRunner report will contain not only test case index, but the parameter for each case (sorry, I have not enough reputation to post a screenshot).
Note: you will need to add a dependency:
Gradle:
testCompile 'pl.pragmatists:JUnitParams:1.0.2'
Maven:
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
<version>1.0.4</version>
<scope>test</scope>
</dependency>
Upvotes: 2
Reputation: 32323
The right way to do this test is to use a parameterized test as you describe in your question. However, you said you don't want to do that. So, instead, you can always use the String message argument for your failure message.
You appear to be using assertEquals(double, expected, double actual, double delta)
in this line:
assertEquals(-1, stock.getSMA(days, index), 0.001);
Instead, you could use assertEquals(String message, double expected, double actual, double delta)
to give yourself a more informative error message, e.g.
assertEquals(String.format("For index %d,", index), -1, stock.getSMA(days, index), 0.001);
This will give you an error message like:
java.lang.AssertionError: For index 15, expected:<-1.0> but was:<0.0>
Upvotes: 3