实验五 单元测试
一、实验目的
1)掌握单元测试的方法
2)学习XUnit测试原理及框架;
3)掌握使用测试框架进行单元测试的方法和过程。
二、实验内容
1、了解单元测试的原理与框架
2、结对编程的小组采用测试框架 对自己“结对编程”实验的程序模块(类)进行单元测试,提交单元测试报告
测试报告包括以下内容:
1)源码
2)测试用例设计 (结合单元测试的内容和模块功能设计测试用例)
3)选择的测试框架介绍、安装过程
4 )测试代码
5)测试结果与分析
3、push测试报告和测试代码到各自的github仓库
4、提交博客报告
实验内容
1)源码
Map.java
package LifeGame; import java.util.Random; public class Map { final static public int x=16;//设置地图初始大小 final static public int y=16; public static Cell [][]initial() { Cell [][]cell=new Cell[x][y]; for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { cell[i][j]=new Cell(); Random random=new Random(); cell[i][j].setStatus(random.nextInt(2)); //随机初始化设置细胞状态 } } return cell; } public static void getLiving(Cell [][]cell){ for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { int living=0; if(i>0&&j>0) living+=cell[i-1][j-1].getStatus(); if(j>0) living+=cell[i][j-1].getStatus(); if(i<x-1&&j>0) living+=cell[i+1][j-1].getStatus(); if(i>0) living+=cell[i-1][j].getStatus(); if(i<x-1) living+=cell[i+1][j].getStatus(); if(i>0&&j<x-1) living+=cell[i-1][j+1].getStatus(); if(j<x-1) living+=cell[i][j+1].getStatus(); if(i<x-1&&j<x-1) living+=cell[i+1][j+1].getStatus(); cell[i][j].setLiving(living);//计算细胞周围八个格子的活细胞数目,特殊位置边界只计算地图内活细胞数目,地图外默认为死细胞 } } } public static int update(Cell [][]cell){ int count=0; for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { int status=cell[i][j].getStatus(); cell[i][j].UpdateStatus(); if(status==cell[i][j].getStatus()) count++;//计算细胞达到演化平衡时的轮数 } } return count; } public static void printMap(Cell [][]cell) { for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { System.out.print(cell[i][j].getStatus()+" ");//打印细胞地图 } System.out.println(); } } }
Cell.java
package LifeGame; public class Cell { private int Status; //0-死亡 1-存活 private int Living; //周围活细胞数目 Cell(){ Status=0; Living=0; } Cell(int m_Status,int m_Living){ Status=m_Status; Living=m_Living; } public int getStatus() { return Status;//获取状态 } public void setStatus(int m_Status) { Status=m_Status;//设置状态 } public int getLiving() { return Living;//获取当前周围活细胞数目 } public void setLiving(int m_Living) { Living=m_Living;//设置当前周围活细胞数目 } public void UpdateStatus() { if(this.getLiving()>3||this.getLiving()<2) this.setStatus(0); else if(this.getLiving()==3) this.setStatus(1); else this.setStatus(this.Status); } }
2)测试用例设计
a.生命游戏需求分析:
每个细胞的状态由该细胞及周围 8 个细胞上一次的状态所决定;
如果一个细胞周围有 3 个细胞为生,则该细胞为生,即该细胞若原先为死则转为生,若原先为生则保持不变;
如果一个细胞周围有 2 个细胞为生,则该细胞的生死状态保持不变;
在其它情况下,该细胞为死,即该细胞若原先为生则转为死,若原先为死则保持不变。
b.测试用例编写:
①测试数据:无细胞
②测试数据:代码错误
3)测试框架介绍及安装过程
框架介绍:
JUnit是一个开发源代码的Java测试框架,用于编写和运行可重复的测试。他是用于单元测试框架体系xUnit的一个实例(用于java语言).
安装过程:
a.将 JUnit4 单元测试包引入这个项目:在该项目上点右键Properties→Java Build Path→Library→Add Library→JUnit,,如下图所示:
选择JUnit4
b.将JUnit4单元测试包导入项目
点击ok,进行名称创建等操作
选择我们所要测试内容
之后在新生成的Test里添加修改即可。
4)测试代码
CellTest
package LifeGame; import static org.junit.Assert.*; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; public class CellTest { private static Cell cell=new Cell(); @BeforeClass public static void setUpBeforeClass() throws Exception { ; } @AfterClass public static void tearDownAfterClass() throws Exception { ; } @Test public void testUpdateStatus() { cell.setLiving(1); cell.UpdateStatus(); assertEquals(0,cell.getStatus()); cell.setLiving(3); cell.UpdateStatus(); assertEquals(1,cell.getStatus()); cell.setLiving(4); cell.UpdateStatus(); assertEquals(0,cell.getStatus()); cell.setStatus(1); cell.setLiving(2); cell.UpdateStatus(); assertEquals(1,cell.getStatus()); cell.setStatus(0); cell.setLiving(2); cell.UpdateStatus(); assertEquals(0,cell.getStatus()); } }
MapTest
package LifeGame; import static org.junit.Assert.*; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; public class MapTest { private static Map map=new Map(); private static Cell [][]cell=new Cell[16][16]; @BeforeClass public static void setUpBeforeClass() throws Exception { cell=map.initial(); } @AfterClass public static void tearDownAfterClass() throws Exception { ; } @Test public void testGetLiving() { for(int i=0;i<16;i++) { for(int j=0;j<16;j++) { cell[i][j].setStatus(1); } } map.getLiving(cell); for(int i=0;i<16;i++) { for(int j=0;j<16;j++) { if(i>0&&i<15&&j>0&&j<15) assertEquals(8,cell[i][j].getLiving()); else if((i==0||i==15)&&(j>0&&j<15)||(j==0||j==15)&&(i>0&&i<15)) assertEquals(5,cell[i][j].getLiving()); else assertEquals(3,cell[i][j].getLiving()); } } for(int i=0;i<16;i++) { for(int j=0;j<16;j++) { cell[i][j].setStatus(0); } } map.getLiving(cell); for(int i=0;i<16;i++) { for(int j=0;j<16;j++) { assertEquals(0,cell[i][j].getLiving()); } } } }
5)测试结果与分析
MapTest
修改值,报错
CellTest
修改值,报错
2.push测试代码带Github仓库
实验小结
此次实验是代码的单元测试实验,我们小组的是生命游戏程序,但是由于我们之前是用c语言来进行编写的,要使用MiniUnit来进行测试,但是找这个资源实在是太少了,难以寻找。所以更换了一份Java代码。在课下会继续尝试使用其他工具来进行测试。
思考题
比较以下二个工匠的做法,你认为哪种好?结合编码和单元测试,谈谈你的认识。
答:工匠一的做法相当于边写代码边进行测试,这也是 不同于传统的测试方法,这也是方法的转变,可能在这种情况下创作团队的设计思路等会发生改变,有好有坏;工匠二的做法是严格按照流程来,可能会节省一部分时间,但是若期间有更好的想法可能会较难改变。