因为我的项目想要开始测试驱动的开发,所以我决定为我的项目编写一个关于Junit 4(当前使用Eclipse Juno的JUnit 4.10)的小教程。
Bill.java
import java.util.ArrayList;
import java.util.List;
/**
* @author funkymonkey
*
* Class Bill can store an id and a priceList (List<Float>)
* - id with setter and getter
* - prices can be added to the priceList
* - getter for priceList
* - total amount of price in priceList can be calculated
*/
public class Bill {
private Integer id; // invoice number (one for every Bill)
private List<Float> priceList; // list will contain prices of the products
public Bill() {
priceList = new ArrayList<Float>();
}
public Bill(Integer id) {
this.id = id;
priceList = new ArrayList<Float>();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public List<Float> getPriceList() {
return priceList;
}
public void addPrice(Float price) {
if (price <= 0) {
throw new IllegalArgumentException("Value is less or equal zero");
}
priceList.add(price);
}
public float getTotalPrice() {
float totalPrice = 0;
for (Float p : priceList) {
totalPrice = totalPrice + p;
}
return totalPrice;
}
}
BillTest.java
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.matchers.JUnitMatchers.hasItems;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class BillTest {
private static Bill jBill1;
private static final float FLOAT_1 = (float) 1;
private static final float FLOAT_20 = (float) 20;
private static final float FLOAT_3P345 = (float) 3.345;
private static final float FLOAT_0P000001 = (float) 0.000001;
@Before
// initialize objects before running tests
public void setUp() throws Exception {
jBill1 = new Bill();
}
@After
// something which should be done after running a single test
public void tearDown() throws Exception {
}
@Test
// test addPrice()
public final void testAddPrice_priceIsGreaterThanZero() {
jBill1.addPrice(FLOAT_1);
jBill1.addPrice(FLOAT_20);
jBill1.addPrice(FLOAT_3P345);
jBill1.addPrice(FLOAT_0P000001);
// check if expected values == results
// we are comparing lists so we are using assertEquals(expected, result)
List<Float> expectedList = new ArrayList<Float>();
expectedList.add(FLOAT_1);
expectedList.add(FLOAT_20);
expectedList.add(FLOAT_3P345);
expectedList.add(FLOAT_0P000001);
List<Float> resultList = jBill1.getPriceList();
assertEquals(expectedList, resultList);
// we are comparing arrays so we can use assertArrayEquals(expected, result)
Object[] expectedArray = { FLOAT_1, FLOAT_20, FLOAT_3P345, FLOAT_0P000001 };
Object[] resultArray = jBill1.getPriceList().toArray();
assertArrayEquals(expectedArray, resultArray);
// we are comparing strings to we can use assertEquals(expected, result)
String expectedString = expectedList.toString();
String resultString = jBill1.getPriceList().toString();
assertEquals(expectedString, resultString);
// let us compare the size of the lists using assertTrue (boolean condition)
Integer expectedLength = expectedList.size();
Integer resultLength = jBill1.getPriceList().size();
assertTrue(expectedLength == resultLength);
// or use assertTrue(expectedLength.equals(resultLength));
// you can also use your own matchers by using assertThat(result, matcher)
assertThat(resultList, hasItems(expectedList.toArray(new Float[expectedList.size()])));
// or assertThat(resultList, hasItems(FLOAT_1, FLOAT_20, FLOAT_3P345, (float)
// 0.000001));
}
@Test(expected = IllegalArgumentException.class)
// test will pass if exception is thrown from addPrice()
public final void testAddPrice_priceIsZero() {
// this will throw the exception IllegalArgumentException
jBill1.addPrice((float) 0);
}
@Test(expected = IllegalArgumentException.class)
// test will pass if exception is thrown from addPrice()
public final void testAddPrice_priceIsLessThanZero() {
// this will throw the exception IllegalArgumentException
jBill1.addPrice((float) -1);
}
@Test
// test if calculating works via getTotalPrice()
public final void testGetTotalPrice() {
jBill1.addPrice(FLOAT_1);
jBill1.addPrice(FLOAT_20);
jBill1.addPrice(FLOAT_3P345);
jBill1.addPrice(FLOAT_0P000001);
Float expectedValue = FLOAT_1 + FLOAT_20 + FLOAT_3P345 + FLOAT_0P000001;
Float resultValue = jBill1.getTotalPrice();
// we are comparing float values so we can use assertEquals(expected, result)
assertEquals(expectedValue, resultValue);
}
}
我的问题是:
答案 0 :(得分:0)
一般情况下:不要使用魔术硬编码。更好地定义常量,以便您可以在一点编辑它们:
public static final float FLOAT_1 = 1;
public static final float FLOAT_20 = 20;
public final void testAddPrice_priceIsGreaterThanZero() {
expectedList.add((float) FLOAT_1);
expectedList.add((float) FLOAT_20);
List<Float> expectedList = new ArrayList<Float>();
expectedList.add((float) FLOAT_1);
expectedList.add((float) FLOAT_20);
//...
}
像JUnit这样的单元测试被设计为“对一个职责进行一次测试”。因此,对于您的方法#getPriceList()
和getPriceList().toString()
等,定义所有分离的测试(可以在setUp()
中执行添加,因为每个测试都应独立于其他测试运行)。 JUnit是快速失败的,这意味着在第一次失败的测试之后,它将使测试方法失败。因此,如果您在一次测试方法中使用它们,那么在第一次测试失败后您将失去所有测试。
您可以将JavaDoc添加到Test-methods中,以描述他们如何测试功能。随机示例 - 值,预期异常等。