Reputation: 572
I'm just learning JUnit testing and I have been given examples of testing with parameters so I'm applying this and the documentation and examples of sites like Daniel Mayer's Our Craft and Mkyong.
I'm asked to test the fill() method with a parameterized class. This is the original class:
package FuelTankTestPractice;
/**
* FuelTank is the class which represents the fuel tank of a car.
* A FuelTank object encapsulates the state information needed for describing the state of the tank:
* <ul>
* <li> tankMax capacity of the tank
* <li> tankLevel fuel level of the tank
* </ul>
*
* class invariant 0.0 <= tankLevel <= tankMax
*
* @author UC3M MOOC Team
*
*/
public class FuelTank {
private double tankMax;
private double tankLevel;
/**
* FuelTank is a constructor of the class.
*
* <hr>
* <br> precondition tankMax > 0.0 and 0.0 <= tankLevel <= getTankMax()
* <br> postcondition tankMax > 0.0 and 0.0 <= tankLevel <= getTankMax()
* <hr>
*
* @param tankMax is the amount of fuel (measured in liters) that the tank can hold
* @param tankLevel is the amount of fuel (measured in liters) that the tank will have initially
*
*/
FuelTank(double tankMax, double tankLevel) {
this.tankMax = tankMax;
this.tankLevel = tankLevel;
}
/**
* getTankLevel is an accessor method
*
* @return the amount of fuel in the tank
*/
public double getTankLevel(){
return tankLevel;
}
/**
* getTankMax is an accessor method
*
* @return the capacity (in liters) of the tank
*/
public double getTankMax(){
return tankMax;
}
/**
* isEmpty gives a status report
*
* @return <code>true</code> if the tank is empty
* <code>false</code> otherwise.
*/
public boolean isEmpty(){
return tankLevel == 0;
}
/**
* isFull gives a status report
*
* @return <code>true</code> if the tank is full
* <code>false</code> otherwise.
*/
public boolean isFull(){
return tankLevel == tankMax;
}
/**
* fill is a mutator method that adds fuel to the tank
*
* <hr>
* <br> precondition 0.0 < amount <= getTankMax() - getTankLevel()
* <br> postcondition not empty
* <br> postcondition tankLevel > tankLevel_initial
* <hr>
*
* @param amount the quantity of fuel to add
*
*/
public void fill(double amount){
tankLevel = tankLevel + amount;
}
/**
* consume is a mutator that consumes amount of fuel
*
* @param amount the amount of fuel to consume
*
*/
public void consume(double amount){
tankLevel = tankLevel - amount;
}
}
First I had to create a simple test class, that worked without problems:
package FuelTankTestPractice;
/**
* Tests for class FuelTank.
*
* All tests in the folder "test" are executed
* when the "Test" action is invoked.
*
*/
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.Before;
public class FuelTankTest {
FuelTank tank = null;
@Before
public void setUp() throws Exception {
tank = new FuelTank(60.0,10.0);
}
@Test
public void testGetTankLevel() {
tank.getTankLevel();
assertTrue(tank.getTankLevel()==0.0);
}
@Test
public void testGetTankMax() {
tank.getTankMax();
assertTrue(tank.getTankMax()==60.0);
}
@Test
public void testIsEmpty() {
tank.isEmpty();
assertTrue(!tank.isEmpty());
}
@Test
public void testHalfFullTank() {
assertTrue(tank.getTankMax()/2==30.0);
}
}
But now this is my test class with parameters (the idea is to test the fill() method:
package FuelTankTestPractice;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class FillingTest extends FuelTankTest{
private double amount;
private double result;
//constructor
public FillingTest (double amount, double result) {
this.amount = amount;
this.result = result;
}
FuelTank tank = new FuelTank(60, 10);
//Declares parameters here
public static Collection<Object[]> fillAmounts(){
Object[][] amounts = new Object[][]{
{10.0,20.0},
{15.0,35.0},
{20.0,30.0},
{35.0,45.0}};
return Arrays.asList(amounts);
}
@Test
public void TestFill() {
tank.fill(amount);
assertTrue(amount + tank.getTankLevel() == result);
}
}
The main class and method is pretty simple but I'll add it if it helps:
public class Main {
public static void main(String[] args) {
// create the tank
FuelTank tank = new FuelTank(40.0,0.0);
System.out.print("The tank with capacity " + tank.getTankMax() + " liters has been created. ");
System.out.println(" Its initial fuel level is " + tank.getTankLevel() + " liters.");
}
}
I've made many changes to fit with examples, but most of them dont consider another test class (which I require to create a JUnit Test Suite in the end, as instructed). Sometimes it throws:
java.lang.Exception: No public static parameters method on class FuelTankTestPractice.FillingTest
at org.junit.runners.Parameterized.getParametersMethod(Parameterized.java:299)
at org.junit.runners.Parameterized.<init>(Parameterized.java:246)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createUnfilteredTest(JUnit4TestLoader.java:84)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:70)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:43)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
I Hope all this info helps. It's not about to solve my "homework" but about learning. Pleas ask me anything you need before consider as a noob question, I've done all the research I can but I believe examples dont match my question, or maybe I dont know enought to see the difference.
Upvotes: 4
Views: 3139
Reputation: 572
This is the final working code that passed the test:
package FuelTankTestPractice;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
//Part 1: Runwith
@RunWith(Parameterized.class)
public class FillingTest {
private double amount;
private double result;
//Part 2: Constructor
public FillingTest (double amount, double result) {
this.amount = amount;
this.result = result;
}
//Part 3: Declares parameters here
@Parameters
public static Collection<Object[]> fillAmounts(){
Object[][] amounts = new Object[][]{
{10.0,20.0},
{15.0,25.0},
{20.0,30.0},
{35.0,45.0}};
return Arrays.asList(amounts);
}
// Part 4: Test method
FuelTank tank = new FuelTank(60.0,10.0);
@Test
public void TestFill() {
tank.fill(amount);
assertEquals(result, tank.getTankLevel(), 0.0001);
// Or assertTrue(tank.getTankLevel() == result);
}
}
Compared to the question code, Part 3 lacks the @Parameters
line.
Also, the assertTrue() line in Part 4 was wrong, since tank.fill(amount);
already added "amount" to TankLevel.
For purposes of the course,I used assertEquals instead of assertTrue (which had me looking for the meaning of "delta").
Upvotes: 1
Reputation: 140613
You are declaring that your test class should be used as @RunWith(Parameterized.class)
That implies that it provides a method that carries the@Parameters
annotation.
Thus: add this annotation to your method fillAmounts()
and you should be good.
The error message is basically telling you that the runner can't find the method it needs in order to do its job.
Upvotes: 4