武汉轻工大学软件测试实验报告实验一单元测试工具JUNIT姓名:李娅娅学号: 1505110015班级:软工1503指导老师:丁月华1. 实验目的了解自动化测试工具JUnit的架构、功能,学习如何下载、安装JUnit,掌握使用JUnit对Java程序进行单元测试的方法。
2. 实验步骤2.1 导入jar包右击项目名,单击Build Path中的Add Libraries..选择User Libariry。
新建一个存放Junit的包的库将junit-4.7.jar导入Jar包导入完成。
2.2 编写第一个Junit测试类2.2.1 Calculator类编写被测试类Calculator:(拷贝)private static int result; // 静态变量,用于存储运行结果public void add(int n){result = result + n;}public void substract(int n){result = result - 1; //Bug: 正确的应该是 result=result-n}public void multiply(int n){} // 此方法尚未写好public void divide(int n){result = result / n;}public void square(int n){result = n * n;}public void squareRoot(int n){for (; ;) ; //Bug : 死循环}public void clear(){ // 将结果清零result = 0;}public int getResult(){return result;}}2.2.2 CalculatorTest类编写CalculatorTest类,用于测试Calculator类:(拷贝)public class CalculatorTest {private static Calculator calculator = new Calculator();@Beforepublic void setUp() throws Exception{calculator.clear();}@Testpublic void testAdd(){calculator.add(2);calculator.add(3);assertEquals(5, calculator.getResult());}@Testpublic void testSubstract(){calculator.add(10);calculator.substract(2);assertEquals(8, calculator.getResult());}@Ignore("Multiply() Not yet implemented")@Testpublic void testMultiply(){}@Testpublic void testDivide(){calculator.add(8);calculator.divide(2);assertEquals(4, calculator.getResult());}}2.2.3 运行测试在类名上右击,选择Run As Junit Test得到Junit面板,并显示了哪些测试是成功的,哪些是失败的以及哪些是未执行(直接跳过了):2.3 使用JUnit对Money类进行单元测试2.3.1 Money类(拷贝)public class Money {private int fAmount; //货币余额private String fCurrency; //货币类型public Money(int amount, String currency){ fAmount=amount;fCurrency=currency;}public int amount(){return fAmount;}public String currency(){return fCurrency;}public Money add(Money m){//add方法把两个Money对象相加,合成一个Money对象return new Money(amount()+m.amount(),currency());}public boolean equals(Object anObject){//equals方法判断两个Money对象是否相等if(anObject instanceof Money){Money aMoney=(Money)anObject;returnaMoney.currency().equals(currency())&&amount()==aMoney.am ount();}return false;}}现在要对Money类的add方法进行测试,步骤如下:2.3.2 MoneyTest类(1) 创建对象定义几个Money类的对象Money result;Money m12CHF=new Money(12,"CHF");Money m14CHF=new Money(14,"CHF");Money expected=new Money(26,"CHF"); //预期的运行结果(2) addTest()在MoneyTest类中编写testAdd方法,对Money类中的add()方法进行测试:@Testpublic void testAdd(){result=m12CHF.add(m14CHF);assertTrue(expected.equals(result));//判断运行结果是否与预期值相同}(3) testEquals()@Testpublic void testEquals(){assertTrue(!m12CHF.equals(null));assertTrue(!m12CHF.equals(m14CHF));assertEquals(m12CHF,m12CHF);assertEquals(m12CHF,new Money(12,"CHF"));}2.3.3 运行测试测试通过2.4 Fixture和几个标签Fixture的含义就是“在某些阶段必然被调用的代码”。
比如我们上面的测试,由于只声明了一个Calculator对象,他的初始值是0,但是测试完加法操作后,他的值就不是0了;接下来测试减法操作,就必然要考虑上次加法操作的结果。
这绝对是一个很糟糕的设计!我们非常希望每一个测试都是独立的,相互之间没有任何耦合度。
因此,我们就很有必要在执行每一个测试之前,对Calculator对象进行一个“复原”操作,以消除其他测试造成的影响。
因此,“在任何一个测试执行之前必须执行的代码”就是一个Fixture,我们用@Before来标注它,如前面例子中的setUp()方法所示:这里不在需要@Test标注,因为这不是一个test,而是一个Fixture。
同理,如果“在任何测试执行之后需要进行的收尾工作”也是一个Fixture,使用@After来标注。
2.4.1 代码测试public class TTest {@BeforeClasspublic static void beforeClass() {System.out.println("beforeClass");}@AfterClasspublic static void afterClass() {System.out.println("afterClass");}@Beforepublic void before() {System.out.println("before");}@Testpublic void testAdd() {int z = new T().add(5, 3);assertThat(z, is(8));assertThat(z, allOf(greaterThan(5), lessThan(10)));}@Test(expected = ng.ArithmeticException.class, timeout = 100)public void tDivide() {int z = new T().divide(8, 0);}@Afterpublic void after() {System.out.println("after");}}2.4.2 运行结果在控制台中得到运行结果:在Junit选型卡中得到:(1) 结果分析在Junit选项卡中由于代码找不到T类,而使方法运行错误。
在控制台中输出两次before和两次after,是因为在类中test了两个方法,每运行一个方法,@before和@after下的方法就是默认执行。
2.4.3 标签学习(1) @Test测试方法(2) @Before使用了该元数据的方法在每个测试方法执行之前都要执行一次,一般做初始化方法。
(3) @After使用了该元数据的方法在每个测试方法执行之后要执行一次,一般用于释放资源。
(4) @ignore该元数据标记的测试方法在测试中会被忽略。
你可以为该标签传递一个String的参数,来表明为什么会忽略这个测试方法。
比如:@lgnore(“该方法还没有实现”),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。
(5) @BeforeClass所有测试开始之前运行,一个测试类只能有一个,并且必须声明为public static。
该方法在内存中只存在一份实例,比较适合加载配置文件。
(6) @AfterClass:所有测试结束之后运行,一个测试类只能有一个,并且必须声明为public static。
通常用来对资源进行清理,比如关闭数据库的连接。
(备注:为什么需要@BeforeClass 和@AfterClass ,我们来看看他们是否适合完成如下功能:有一个类是负责对大文件(超过500 兆)进行读写,他的每一个方法都是对文件进行操作。
换句话说,在调用每一个方法之前,我们都要打开一个大文件并读入文件内容,这绝对是一个非常耗费时间的操作。
如果我们使用@Before 和@After ,那么每次测试都要读取一次文件,效率及其低下。
这里我们所希望的是在所有测试一开始读一次文件,所有测试结束之后释放文件,而不是每次测试都读文件。
JUnit 的作者显然也考虑到了这个问题,它给出了@BeforeClass 和@AfterClass 两个Fixture 来帮我们实现这个功能。