目录
一、实验目的
- 学习并了解Junit框架。
- 掌握Junit的常见方法。
- 学习测试用例的书写。
二、实验环境
- 硬件环境:PC 机一台
- 软件环境:Java 编程环境:Java SDK + Eclipse+Junit5
- 待测程序:计算机程序
三、实验内容与步骤
1、搭建Junit单元测试环境,请自行完成JDK,java开发环境的搭建,推荐使用eclipse或者idea集成开发平台。完成Junit的安装与集成。
2、学习Junit常见用法,详见《Junit教程》,完成以下内容的练习。
(1)固定片断方法(Fixture)
(2)异常处理
(3)条件测试
(4)参数注入方法
3、完成以下实验任务的测试工作,体现对上述方法的应用。
实验:BMI计算问题
(实现方法参考如下:)
// 根据BMI值判断健康状况
public String getBMIType(){
double bmi = 0.0;
String result = "";
if( weight>0 && height>0){
//1.计算bmi
bmi = weight/(height*height);
//2.根据bmi判断所属健康分类
if(bmi<18.5){
result = "偏瘦";
}else if(bmi<24){
result = "正常";
}else if(bmi<28){
result = "偏胖";
}else{
result = "肥胖";
}
}else{
return "Weight or height error!";
}
return result;
}
要求:
- 试利用直觉经验法及错误推测方法,设计BMI计算问题的测试用例。请给出测试用例的具体设计思路。
- 基于Junit,分别完成上述测试用例的测验工作,测试过程中应体现对固定片断(Fixture)方法、条件测试、异常处理方法、参数注入方法的应用。
实验报告
一、实验原理
1.1 搭建Junit单元测试环境
请自行完成JDK,java开发环境的搭建,推荐使用eclipse或者idea集成开发平台。完成Junit的安装与集成。
1.2 学习Junit常见用法。
1.2.1 固定片断方法
Fixture指的是测试方法执行前后需要进行的操作,通常包括setUp()和tearDown()方法,前者用于创建和准备测试环境,后者用于清理和销毁测试环境。Fixture的目的是确保测试方法的可重复性和独立性,减少测试代码的重复性,从而提高测试的准确性、可靠性和可维护性。
标记为@BeforeEach和@AfterEach的方法会在运行每个@Test方法前后自动运行,而标记为@BeforeAll和@AfterAll的方法在运行所有@Test前后运行。
1.2.2 异常处理
在编写程序时,我们无法预知所有可能出现的异常情况,因此需要使用异常处理方法来处理程序中的异常情况,以避免程序崩溃或产生错误结果。常见的异常处理方法包括try-catch语句、finally语句、throws关键字和自定义异常类等。在处理异常时,需要根据具体情况选择合适的异常处理方法,以确保程序的可靠性和稳定性。
1.2.3 条件测试
条件测试是软件测试中的一种测试方法,用于验证程序在不同条件下的行为是否符合预期。条件测试的目的是发现和修复程序中可能存在的逻辑错误和漏洞,从而提高程序的质量和可靠性。条件测试通常涉及到程序中的分支结构,例如if语句、switch语句等。在条件测试中,我们通常需要考虑以下几个方面:
- 边界条件:在测试条件分支时,需要测试各种边界情况,例如测试if语句中的等于、大于、小于等不同情况。
- 正常条件:需测试条件分支的正常情况,如测试if语句中的true分支和false分支。
- 异常条件:需测试条件分支的异常情况,如测试if语句中的null值、空字符串等情况。
- 多重嵌套条件:需测试多个条件分支嵌套时的情况,例如测试if - else if - else结构中各种不同情况。
1.2.4 参数注入方法
参数注入是指将对象所需的参数通过构造函数或属性注入到对象中的过程。在程序开发中,对象常常需要依赖其他对象或数据,而这些依赖关系通常通过构造函数或属性来传递。参数注入的目的是将对象所依赖的参数从对象的实现中解耦出来,使得对象具有更好的可测试性和可维护性,测试人员和开发人员可以更容易地控制和修改对象所依赖的参数。参数注入还可以提高代码的可重用性和可扩展性。
二、实验步骤
2.1 BMI计算问题
(1)试利用直觉经验法及错误推测方法,设计BMI计算问题的测试用例。请给出测试用例的具体设计思路。
BMI 计算问题:身体质量指数:BMI,Body mass index,用于衡量人体肥胖程序和是否健康。
计算公式:BMI = 体重/身高的平方(kg/m*m)
根据BMI的范围,进行不同的分类,分类如下:
分类 | 国内BMI值(kg/m*m) |
偏瘦 | (0,18.5) |
正常 | [18.5,24) |
偏胖 | [24,28) |
肥胖 | [28,++) |
2.1.1 测试用例
- 设计思路:首先每个分类区间都设计一个用例,然后在BMI值的边界(小于0)设计用例,接着编写Junit测试单元,对每个用例写一个测试方法进行测试。
- 设计测试用例:
身高 | 体重 | 实际输出 |
1.6 | 45 | 偏瘦 |
1.6 | 55 | 正常 |
1.6 | 68 | 偏胖 |
1.6 | 80 | 肥胖 |
0 | 45 | 无效 |
1.6 | 0 | 无效 |
-1.6 | 45 | 无效 |
1.6 | -45 | 无效 |
-1.6 | -45 |
|
- 直觉经验法是一种基于测试人员的经验和直觉进行测试的方法。
- 错误推测方法是一种基于推测和猜测进行测试的方法。
(2)基于Junit,分别完成上述测试用例的测验工作,测试过程中应体现对固定片断(Fixture)方法、条件测试、异常处理方法、参数注入方法的应用。
1、使用固定片断方法。具体代码见BMITest.java文件,运行结果如下图所示。
2、使用参数化运行器@Runwith(Parameterized.class)分别实现构造器注入和属性注入两种参数注入。具体代码见BMITestParam.java文件。运行结果如下图所示。
三、实验结果与分析
该实验学习到了Junit单元测试的一般方法,理解注释的作用,以及它们之间的运行前后顺序。学习到了更加方便的测试方法,比如使用参数化运行器,也更加直观的看到测试结果,加深了我对测试的理解,通过自己的动手实现,让我对Junit测试中的固定片断方法、条件测试、异常处理、参数注入方法更加熟练。
实验代码
1、BMI.java
package BMI;
public class BMI {
private double weight; //体重
private double height; //身高
//Getter and Setter
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
//一次性设置体重和身高
public void setParams(double w, double h) {
this.weight = w;
this.height = h;
}
//定义构造
public BMI(double w, double h) {
this.weight = w;
this.height = h;
}
//定义功能方法,计算BMI,并判断所属分类
public String getBMIType() {
String result = "";
double bmi = 0.0;
if (weight > 0 && height > 0) {
bmi = weight / (height * height);
if (bmi < 18.5) {
result = "偏瘦";
}else if (bmi < 24) {
result = "正常";
}else if (bmi < 28) {
result = "偏胖";
}else {
result = "肥胖";
}
}else {
result = "无效输入";
}
return result;
}
}
2、BMITest.java
package BMI;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class BMITest {
BMI testObj;//被测类
@Before
public void setUp() throws Exception {
testObj = new BMI(0, 0);
System.out.println("Run @Before method");
}
@After
public void tearDown() throws Exception {
testObj = null;
System.out.println("Run @After method");
}
@BeforeClass
public static void prepareEnvironment(){
System.out.println("Run @BeforeClass method");
}
@AfterClass
public static void RestoreEnvironment(){
System.out.println("Run @AfterClass method");
}
@Test
//测试偏瘦用例
public void testBMI_Thin() {
System.out.print("Run testBMI 偏瘦 --> ");
//创建被测对象
testObj.setParams(45.0,1.6);
//调用测试方法
String actual = testObj.getBMIType();
//校验测试结果
String expect = "偏瘦";
assertTrue(expect==actual);
System.out.println("测试通过");
}
@Test
//测试正常用例
public void testBMI_Normal(){
System.out.print("Run testBMI 正常 --> ");
testObj.setParams(55.0,1.6);
assertTrue(testObj.getBMIType()=="正常");
System.out.println("测试通过");
}
@Test
//测试偏胖用例
public void testBMI_SlightlyFat(){
System.out.print("Run testBMI 偏胖 --> ");
testObj.setParams(68.0,1.6);
assertTrue(testObj.getBMIType()=="偏胖");
System.out.println("测试通过");
}
@Test
//测试肥胖用例
public void testBMI_HighlyFat(){
System.out.print("Run testBMI 肥胖 --> ");
testObj.setParams(75.0, 1.6);
assertTrue(testObj.getBMIType()=="肥胖");
System.out.println("测试通过");
}
@Test
//测试无效用例
public void testBMI_Illegal(){
System.out.print("Run testBMI 无效输入 --> ");
testObj.setParams(75.0, -1.6);
assertTrue(testObj.getBMIType()=="无效输入");
System.out.println("测试通过");
}
}
3、BMITestParam.java
package BMI;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collection;
/*//构造器注入
//1.指定参数化运行器
@RunWith(Parameterized.class)
public class BMITestParam {
BMI testObj;//被测类
//1.定义属性,作为参数
private double weight;//体重
private double height;//身高
private String expected;//预期分类
//2.定义带参数的构造方法,传输数据
public BMITestParam(double w, double h, String exp){
this.weight = w;
this.height = h;
this.expected = exp;
}
//3.准备测试数据集
@Parameterized.Parameters(name="{index}:getBMIType[{0},{1}]=[{2}]")
public static Collection testDataset(){
return Arrays.asList(
new Object[][]{
{45.0,1.6,"偏瘦"},
{55.0,1.6,"正常"},
{68.0,1.6,"偏胖"},
{80.0,1.6,"肥胖"}
}
);
}
@Before
public void setUp() throws Exception {
testObj = new BMI(weight, height);
}
@After
public void tearDown() throws Exception {
testObj = null;
}
@Test
public void getBMIType() {
assertTrue(testObj.getBMIType()==expected);
}*/
//属性注入
@RunWith(Parameterized.class)
public class BMITestParam {
BMI testObj; //被测类
@Parameterized.Parameter(0)
public double weight; //体重
@Parameterized.Parameter(1)
public double height; //身高
@Parameterized.Parameter(2)
public String expected; //预期分类
@Parameterized.Parameters(name = "{index}:getBMIType[{0},{1}] = [{2}]")
public static Collection testDataset() {
return Arrays.asList(
new Object[][]{
{45.0, 1.6, "偏瘦"},
{55.0, 1.6, "正常"},
{68.0, 1.6, "偏胖"},
{80.0, 1.6, "肥胖"}
}
);
}
@Before
public void setUp() throws Exception {
testObj = new BMI(weight, height);
//System.out.println("Run @Before method");
}
@After
public void tearDown() throws Exception {
testObj = null;
//System.out.println("Run @After method");
}
@Test
public void getBMIType() {
assertTrue(testObj.getBMIType() == expected);
}
}