Reputation: 1488
I have many tests - in different test classes - that should run using the same sets of sample data. Here is an example test method.
@Test
public void testTracerErrorPerPixel() {
// Iterate over all sample images
// ** This is the line I want to refactor out **
for (Image image : SampleImages.values()) {
// Do some tests on those images
Assert.assertTrue("Tracer error in " + image + " too large after tracing, error per pixel is " + someValue, someValue);
}
}
@Test
public void testTracerCorrectPixelPercent() {
// Iterate over all sample images
// ** This is the line I want to refactor out **
for (Image image : SampleImages.values()) {
// Do some different tests on those images
Assert.assertTrue("Correct pixel percent in " + image + " too low after tracing, % correct " + someValue, someValue);
}
}
Is there a standard more concise way of doing this? Having for (Image image : SampleImages.values()) {
feels like the wrong way of doing this.
Using another framework such as TestNG would be acceptable.
Upvotes: 0
Views: 536
Reputation: 9500
We are using the Parameterized
runner for this matter. More information is found in the junit docs.
In your case you can write
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class ParameterTest {
@Parameters
public static Iterable<Object[]> data() {
// extract to some class for readability and reuse
return Arrays.asList(new Object[][] {
{ new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB) },
{ new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB) }
});
}
private Image image;
public ParameterTest(Image aImage) {
image = aImage;
}
@Test
public void testTracerErrorPerPixel() {
// Do some tests on those images
System.out.println(image);
}
@Test
public void testTracerCorrectPixelPercent() {
// Do some different tests on those images
System.out.println(image);
}
}
Upvotes: 1
Reputation: 1488
By swapping to TestNG, I was able to make use of DataProviders to clean this up.
This is the example from above, changed to use DataProviders.
@Test(
dataProvider = "images",
dataProviderClass = Images.class
)
public void testTracerErrorPerPixel(Image image) {
// Do some tests on those images
Assert.assertTrue("Tracer error too large after tracing, error per pixel is " + someValue, someValue);
}
@Test(
dataProvider = "images",
dataProviderClass = Images.class
)
public void testTracerCorrectPixelPercent(Image image) {
// Do some different tests on those images
Assert.assertTrue("Correct pixel percent too low after tracing, % correct " + someValue, someValue);
}
A DataProvider was also added in Images.class.
@DataProvider(
name = "images",
parallel = true
)
public static Object[][] createImages() {
// Make the array of images
}
I'll accept this answer tomorrow unless someone else provides an answer that works without swapping to TestNG.
Upvotes: 1
Reputation: 817
package stackoverflow.q_24932384;
import org.junit.Test;
import junit.framework.TestCase;
public class CommonJUnitData extends TestCase{
private boolean areImageEqual= false;
@Override
protected void setUp() throws Exception {
//Your image code which will set value of areImageEqual value, like:
areImageEqual = compare.compare(original, tracedAndRedrawn);
}
@Test
public void testTracerError() {
//Use areImageEqual variable value
}
}
Upvotes: 0
Reputation: 7894
I would refactor this test as follows:
@Test
public void testVectorError() {
// Iterate over all sample images
for (Image image : SampleImages.values()) {
PixelComparer comparer = compare(image);
// Ensure that traced image is close to original image
Assert.assertTrue("", comparer.rootMeanSquareErrorPerPixel < 0.01d);
}
}
private PixelComparer compare(Image image) {
Pixels original = image.getPixels();
// Trace image to vector
Tracer tracer = new Tracer();
tracer.trace(pixels);
// Redraw image at same resolution
Pixels tracedAndRedrawn = tracer.render(original.width, original.height);
PixelComparer comparer = new PixelComparer();
comparer.compare(original, tracedAndRedrawn);
return comparer;
}
The compare method could either be an internal method to the test class (as shown) or placed into a test utility class and then re-used by multiple test classes.
I think it is important to apply the DRY principle to tests as well as application code. That is what is important here, not what tool you use (JUnit, TestNG).
Upvotes: 0