一:实验内容
- Install Junit(4.12), Hamcrest(1.3) with Eclipse
- Install Eclemma with Eclipse
- Write a java program for the triangle problem and test the program with Junit.
a) Description of triangle problem:
Function triangle takes three integers a,b,c which are length of triangle sides; calculates whether the triangle is equilateral, isosceles, or scalene.
二:实验步骤
(1)安装Junit、Hamcrest
打开eclipse,点击eclipse下的project->properties->java build path->libraries->Add External JARs,导入Junit和Hamcrest包即可。
(2)安装Eclemma
打开eclipse,点击eclipse下的Help->Eclipse Marketplace->搜索EclEmma,Install即可。
安装成功后,将会出现如下图标:
(3)用java代码写三角形程序并用Junit来测试三角形类型
1:首先创建一个java工程,命名为jhtest。
2:在src下创建两个包,一个包叫code,一个包叫test,code的里面存放被测程序,而test里面存放测试程序。
3:创建一个三角形类triangle.java,并将该类放在code包下。这个类将包含三个属性值,side1、side2、side3,代表三角形的三条边;包含一个含参构造参数,初始化三条边;还包含一个判断类型的函数whatType(),该函数根据边的值判断三角形的类型,并返回类型值。三角形的类型分为"right and isosceles triangle"(等腰直角三角形)、"right triangle"(直角三角形)、
"isosceles triangle"(等腰三角形)、"equilateral triangle"(等边三角形)、
"common triangle"(一般三角形)、"not a triangle"(不能构成三角形)这6种。
4:创建一个三角形测试类triangleTest.java,并将该类放在test包下。该类包含4个属性值(3条边、一个期望类型值);一个含参构造函数,用于初始化属性值;一个创建测试数据集合的函数data();一个测试函数testTriangle()用于测试。
5:运行测试程序。
三:实验代码
(1)triangle.java类
package code;
import java.text.DecimalFormat;
public class triangle {
//三条边
private double side1;
private double side2;
private double side3;
//构造函数
public triangle(double side1,double side2,double side3){
this.side1 = side1;
this.side2 = side2;
this.side3 = side3;
}
//判断三角形类型函数
public String whatType(){
String type = null;
if((side1 + side2 > side3) &&
(side1 + side3 > side2) &&
(side2 + side3 > side1)){
//判断是否为等腰直角三角形
if(((side1 == side2) && (Math.pow(Math.pow(side1,2.0) + Math.pow(side2,2.0),0.5) == side3))||
((side2 == side3) && (Math.pow(Math.pow(side2,2.0) + Math.pow(side3,2.0),0.5) == side1)) ||
((side1 == side3) && (Math.pow(Math.pow(side1,2.0) + Math.pow(side3,2.0),0.5) == side2))
){
type = "right and isosceles triangle";
}
//判断是否为直角三角形
else if(Math.pow(Math.pow(side1,2.0) + Math.pow(side2,2.0),0.5) == side3 ||
Math.pow(Math.pow(side2,2.0) + Math.pow(side3,2.0),0.5) == side1 ||
Math.pow(Math.pow(side1,2.0) + Math.pow(side3,2.0),0.5) == side2){
type = "right triangle";
}
//判断是否为等腰三角形
else if(((side1 == side2) && (side1 != side3)) || ((side1 == side3) && (side1 != side2)) ||
((side2 == side3) && (side1 != side2))){
type = "isosceles triangle";
}
//判断是否为等边三角形
else if((side1 == side2) && (side2 == side3)){
type = "equilateral triangle";
}
else{
type = "common triangle";
}
}
else{
type = "not a triangle";
}
//返回类型
return type;
}
}
(2)triangleTest.java类
package test;
import static org.junit.Assert.assertEquals;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import code.triangle;
@RunWith(Parameterized.class)
public class triangleTest{
//4个属性值,三个代表边,expected代表期望的三角形类型值
private double side1;
private double side2;
private double side3;
private String expected;
//有参构造函数
public triangleTest(double side1,double side2,double side3,String expected){
this.side1 = side1;
this.side2 = side2;
this.side3 = side3;
this.expected = expected;
}
//设置测试数据集合
@Parameters
public static Collection<Object[]> data(){
return Arrays.asList(new Object[][]{
{3,3,3,"equilateral triangle"},
{3,4,5,"right triangle"},
{3,3,5,"isosceles triangle"},
{5,8,1,"not a triangle"},
{5,6,7,"common triangle"},
{1,1,Math.pow(2.0, 0.5),"right and isosceles triangle"},
{4,6,Math.pow(52.0, 0.5),"right triangle"},
});
}
//执行测试
@Test
public void testTriangle(){
triangle tri = new triangle(side1,side2,side3);
String type = tri.whatType();
assertEquals(expected,type);
}
}
四:测试结果
(1)
(2)
五:实验中所遇到的问题
(1)问题:由于所设置的边为double类型,double的大小为8个字节,所以当表示无理数时,计算机存储的值总是于实际的值有所偏差。比如理论上1^2 + 1^2 = (√2)^2 = 2 ,但是实际上计算机计算√2时出现了微小偏差,导致平方后的值不与实际值相等。所以在判断等腰直角三角形和直角三角形的时候可能由于计算机存储位数的限制而导致一些测试用例不能顺利通过。
解决方法:1:在测试是否为直角三角形时,判断条件程序代码写成(Math.pow(Math.pow(side1,2.0) + Math.pow(side2,2.0),0.5) == side3 ||
Math.pow(Math.pow(side2,2.0) + Math.pow(side3,2.0),0.5) == side1 ||
Math.pow(Math.pow(side1,2.0) + Math.pow(side3,2.0),0.5) == side2)的格式,现将两边先平方相加后开方,然后再判断是否相等。这样就可以顺利通过所有测试用例。
2:当比较两个数是否相等时,为了防止计算机因存储位数有限而导致的偏差,可以将两个数相减,当差小于某个精度时就默认两个数是相等的。