对Rectangle程序进行测试:根据已经学习的测试思想,对函数getArea()、getPerimeter()和findMax()进行测试。
import java.util.Comparator; public class Rect { private int length; private int width; public Rect(int length, int width) { this.length = length; this.width = width; } public int getLength() {return length;} public void setLength(int length) {this.length = length;} public int getWidth() {return width;} public void setWidth(int width) {this.width = width;} public int getArea() {return length*width;} public int getPerimeter() {return 2*length + width;} public String getObject() { return "("+length+","+width+")"; } public static <AnyType> AnyType findMax(AnyType[] arr, Comparator<? super AnyType> cmp) { int maxIndex = 0; for(int i = 1; i < arr.length; i++) if(cmp.compare(arr[i], arr[maxIndex]) > 0) maxIndex = i; return arr[maxIndex]; } public static class areaCompare implements Comparator<Rect> { @Override public int compare(Rect o1, Rect o2) { // TODO Auto-generated method stub if(o1.getArea() < o2.getArea()) { return 1; }else if(o1.getArea() == o2.getArea()) { return 0; }else{ return -1; } } } public static class perimeterCompare implements Comparator<Rect> { @Override public int compare(Rect o1, Rect o2) { // TODO Auto-generated method stub if(o1.getPerimeter() > o2.getPerimeter()) { return 1; }else if(o1.getPerimeter() == o2.getPerimeter()) { return 0; }else{ return -1; } } } public static void main(String[] args) { Rect[] arr = new Rect[] { new Rect(10, 20), new Rect(2, 65), new Rect(3, 10), new Rect(6, 20) }; System.out.println("面积最大:"+findMax(arr, new areaCompare()).getObject()); System.out.println("周长最长:"+findMax(arr, new perimeterCompare()).getObject()); } }
{% note primary %}
若对代码中实现比较器的写法不理解,请看“四、参考文献” Comparator接口的使用
{% endnote %}
public int getArea() { return length*width; }
测试分析
根据Rect类可得成员变量length、width为int型,含义为矩形的长宽,故合法输入为正数,负数和0位非法输入。
此处假设非法输入返回值为-1。
设计测试用例如下:
用例编号 | 测试用例(length,width) | 预期结果(返回值) |
---|---|---|
1 | (3,4) | 12 |
2 | (-3,4) | -1 |
3 | (4,-3) | -1 |
4 | (-5,-6) | -1 |
5 | (3,0) | -1 |
6 | (0,4) | -1 |
7 | (0,0) | -1 |
测试代码
import junit.framework.TestCase; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.Arrays; @RunWith(Parameterized.class) public class TestRectArea extends TestCase { private int length; private int width; private int expected; public TestRectArea(int length, int width, int expected){ this.length=length; this.width=width; this.expected=expected; } //假设要测试的getArea方法遇到非法输入时返回-1 @Parameterized.Parameters(name="{index}:{0}*{1}={2}") public static Iterable<Object []> data(){ return Arrays.asList(new Object[][]{ {3,4,12}, {-3,4,-1}, {4,-3,-1}, {-5,-6,-1}, {3,0,-1}, {0,4,-1}, {0,0,-1} }); } @Test public void testGetArea(){ assertEquals(new Rect(length,width).getArea(),expected); } }
测试结果
用例编号 | 测试用例(length,width) | 预期结果(返回值) | 实际结果 |
---|---|---|---|
1 | (3,4) | 12 | 12 |
2 | (-3,4) | -1 | -12 |
3 | (4,-3) | -1 | -12 |
4 | (-5,-6) | -1 | 30 |
5 | (3,0) | -1 | 0 |
6 | (0,4) | -1 | 0 |
|7|(0,0)|-1|0|
由此可见,此方法代码并没有考虑输入为0和负数的非法情况。
public int getPerimeter() { return 2*length + width; }
测试分析
同理于测试getArea(),此处需要的参数只有length、width,所以考虑负数和0的非法输入。
设计测试用例如下:
用例编号 | 测试用例(length,width) | 预期结果(返回值) |
---|---|---|
1 | (5,6) | 22 |
2 | (-3,4) | -1 |
3 | (3,-4) | -1 |
4 | (-3,-4) | -1 |
5 | (3,0) | -1 |
6 | (0,4) | -1 |
7 | (0,0) | -1 |
测试代码
import junit.framework.TestCase; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.Arrays; @RunWith(Parameterized.class) public class TestRectPerimeter extends TestCase { private int length; private int width; private int expected; public TestRectPerimeter(int length,int width,int expected){ this.length=length; this.width=width; this.expected=expected; } //假设要测试的getPerimeter方法遇到非法输入时返回-1 @Parameterized.Parameters(name="{index}:({0}+{1})*2={2}") public static Iterable<Object []> data(){ return Arrays.asList(new Object[][]{ {5,6,22}, {-3,4,-1}, {3,-4,-1}, {-3,-4,-1}, {3,0,-1}, {0,4,-1}, {0,0,-1} }); } @Test public void testGetPerimeter(){ assertEquals(new Rect(length,width).getPerimeter(),expected); } }
测试结果
用例编号 | 测试用例(length,width) | 预期结果(返回值) | 实际结果 |
---|---|---|---|
1 | (5,6) | 22 | 16 |
2 | (-3,4) | -1 | -2 |
3 | (3,-4) | -1 | 2 |
4 | (-3,-4) | -1 | -10 |
5 | (3,0) | -1 | 6 |
6 | (0,4) | -1 | 4 |
| 7 | (0,0) | -1 |0|
可见,方法代码并没有考虑输入为0和负数的非法情况,且计算过程存在问题,返回去看代码发现没有加括号,应
return 2*(length+width);
AnyType findMax(AnyType[] arr, Comparator<? super AnyType> cmp) { int maxIndex = 0; for(int i = 1; i < arr.length; i++) if(cmp.compare(arr[i], arr[maxIndex]) > 0) maxIndex = i; return arr[maxIndex]; }
public static class areaCompare implements Comparator<Rect> { @Override public int compare(Rect o1, Rect o2) { // TODO Auto-generated method stub if(o1.getArea() < o2.getArea()) { return 1; }else if(o1.getArea() == o2.getArea()) { return 0; }else{ return -1; } } }
测试分析
需要参数length、width,所以考虑负数和0的非法输入。
需注意⚠️:若比较面积时输入的矩形数组都为非法输入(矩形长宽都存在0或负数),getArea()因为非法输入都return -1,则areaCompare比较器中比较函数compare都会return 0,则findMax中return arr[0],返回一个非法矩形,显然错误。故此处findMax也要有一个对应非法输入时的输出,假设为null。
设计测试用例如下:
用例编号 | 测试用例Rect[] | 预期结果 |
---|---|---|
1 | (10,20),(2,65),(3,10),(6,20) | (10,20) |
2 | (-4,3),(5,-6),(-10,-10),(1,1) | (1,1) |
3 | (0,3),(6,0),(0,0),(1,1) | (1,1) |
4 | (0,3),(6,0),(0,0),(-1,-1) | null |
测试代码
import junit.framework.TestCase; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.Arrays; @RunWith(Parameterized.class) public class TestRectFindMaxArea extends TestCase { private Rect[] arr; private Rect expected; public TestRectFindMaxArea(Rect[] arr,Rect expected){ this.arr=arr; this.expected=expected; } @Parameterized.Parameters public static Iterable<Object[]> data(){ return Arrays.asList(new Object[][]{ {new Rect[] { new Rect(10, 20), new Rect(2, 65), new Rect(3, 10), new Rect(6, 20) },new Rect(10,20)}, {new Rect[] { new Rect(-4, 3), new Rect(5, -6), new Rect(-10, -10), new Rect(1, 1) },new Rect(1,1)}, {new Rect[] { new Rect(0, 3), new Rect(6, 0), new Rect(0, 0), new Rect(1, 1) },new Rect(1,1)}, {new Rect[] { new Rect(0, 3), new Rect(6, 0), new Rect(0, 0), new Rect(-1, -1) },null} }); } @Test public void testFindMax(){ Rect temp=Rect.findMax(arr, new Rect.areaCompare()); String stemp,sexpected; if(temp!=null) stemp=temp.getObject(); else stemp="null"; if(expected!=null) sexpected=expected.getObject(); else sexpected="null"; assertEquals(stemp,sexpected); } }
测试结果
| 用例编号 | 测试用例Rect[] | 预期结果 |实际结果| | :------: | :---------------------------: | :------: | :------: | | 1 | (10,20),(2,65),(3,10),(6,20) | (10,20) |(3,10)| | 2 | (-4,3),(5,-6),(-10,-10),(1,1) | (1,1) |(5,-6)| | 3 | (0,3),(6,0),(0,0),(1,1) | (1,1) |(0,3)| | 4 | (0,3),(6,0),(0,0),(-1,-1) | null |(0,3)|可见,代码没有考虑输入矩形数组存在矩形长宽非法or全部矩形长宽均非法的情况,且通过第一个测试用例可知,计算过程存在问题,返回去看代码发现areaCompare比较器中比较函数compare存在逻辑错误,应返回最大矩形对象,却返回最小矩形对象,应
public int compare(Rect o1, Rect o2) { if(o1.getArea() > o2.getArea()) { return 1; }else if(o1.getArea() == o2.getArea()) { return 0; }else{ return -1; } }
public static class perimeterCompare implements Comparator<Rect> { @Override public int compare(Rect o1, Rect o2) { // TODO Auto-generated method stub if(o1.getPerimeter() > o2.getPerimeter()) { return 1; }else if(o1.getPerimeter() == o2.getPerimeter()) { return 0; }else{ return -1; } } }
测试分析
同理于areaCompare,需要参数length、width,所以考虑负数和0的非法输入;设置null为全非法输入的返回值。
设计测试用例
用例编号 | 测试用例Rect[] | 预期结果 |
---|---|---|
1 | (10,20),(2,65),(3,10),(6,20) | (2,65) |
2 | (-4,3),(5,-6),(-10,-10),(1,1) | (1,1) |
3 | (0,3),(6,0),(0,0),(1,1) | (1,1) |
4 | (0,3),(6,0),(0,0),(-1,-1) | null |
测试代码
import junit.framework.TestCase; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.Arrays; @RunWith(Parameterized.class) public class TestRectFindMaxPerimeter extends TestCase { private Rect[] arr; private Rect expected; public TestRectFindMaxPerimeter(Rect[] arr,Rect expected){ this.arr=arr; this.expected=expected; } @Parameterized.Parameters public static Iterable<Object[]> data(){ return Arrays.asList(new Object[][]{ {new Rect[] { new Rect(10, 20), new Rect(2, 65), new Rect(3, 10), new Rect(6, 20) },new Rect(2,65)}, {new Rect[] { new Rect(-4, 3), new Rect(5, -6), new Rect(-10, -10), new Rect(1, 1) },new Rect(1,1)}, {new Rect[] { new Rect(0, 3), new Rect(6, 0), new Rect(0, 0), new Rect(1, 1) },new Rect(1,1)}, {new Rect[] { new Rect(0, 3), new Rect(6, 0), new Rect(0, 0), new Rect(-1, -1) },null} }); } @Test public void testFindMax(){ Rect temp=Rect.findMax(arr, new Rect.perimeterCompare()); String stemp,sexpected; if(temp!=null) stemp=temp.getObject(); else stemp="null"; if(expected!=null) sexpected=expected.getObject(); else sexpected="null"; assertEquals(stemp,sexpected); } }
测试结果
用例编号 | 测试用例Rect[] | 预期结果 | 实际结果 |
---|---|---|---|
1 | (10,20),(2,65),(3,10),(6,20) | (2,65) | (2,65) |
2 | (-4,3),(5,-6),(-10,-10),(1,1) | (1,1) | (5,-6) |
3 | (0,3),(6,0),(0,0),(1,1) | (1,1) | (6,0) |
4 | (0,3),(6,0),(0,0),(-1,-1) | null | (6,0) |
可见代码同样没有考虑输入矩形数组存在矩形长宽非法or全部矩形长宽均非法的情况。
import java.util.Comparator; public class Rect { private int length; private int width; public Rect(int length, int width) { this.length = length; this.width = width; } public int getLength() {return length;} public void setLength(int length) {this.length = length;} public int getWidth() {return width;} public void setWidth(int width) {this.width = width;} public int getArea(){ if(length>0 && width >0) return length*width; else return -1; } public int getPerimeter() { if(length >0 && width >0) return 2*(length + width); else return -1; } public String getObject() { return "("+length+","+width+")"; } public static <AnyType> AnyType findMax(AnyType[] arr, Comparator<? super AnyType> cmp){ int maxIndex = 0; for(int i = 1; i < arr.length; i++) if(cmp.compare(arr[i], arr[maxIndex]) > 0){ maxIndex = i; } if(((Rect)arr[maxIndex]).getLength()<=0 || ((Rect)arr[maxIndex]).getWidth()<=0) return null; else return arr[maxIndex]; } public static class areaCompare implements Comparator<Rect> { @Override public int compare(Rect o1, Rect o2){ // TODO Auto-generated method stub if(o1.getArea() > o2.getArea()) { return 1; }else if(o1.getArea() == o2.getArea()) { return 0; }else{ return -1; } } } public static class perimeterCompare implements Comparator<Rect> { @Override public int compare(Rect o1, Rect o2) { // TODO Auto-generated method stub if(o1.getPerimeter() > o2.getPerimeter()) { return 1; }else if(o1.getPerimeter() == o2.getPerimeter()) { return 0; }else{ return -1; } } } public static void main(String[] args) { Rect[] arr = new Rect[] { new Rect(10, 20), new Rect(2, 65), new Rect(3, 10), new Rect(6, 20) }; Rect rect1=findMax(arr, new areaCompare()); Rect rect2=findMax(arr, new perimeterCompare()); if(rect1 == null) System.out.println("输入的矩形数组中所有矩形长宽均非法!"); else System.out.println("面积最大:"+rect1.getObject()); if(rect2 == null) System.out.println("输入的矩形数组中所有矩形长宽均非法!"); else System.out.println("周长最长:"+rect2.getObject()); } }
为方便测试,使用测试套件Suite,代码如下:
import org.junit.runner.RunWith; import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses({TestRectArea.class,TestRectPerimeter.class,TestRectFindMaxArea.class,TestRectFindMaxPerimeter.class}) public class TestRectSuite { }
测试结果:
程序执行结果:
Comparator接口的使用