一、思考:
是否会出现这种情况,代码写完,自己也测试几遍了,策划,测试同学都验收了,为啥线上总会出现一些显而易见的bug?
谁的锅?
肯定程序员啊,因为代码是我们写的。。。
根据我个人工作经验,策划都只是验收功能,能否跑通,有无明显问题,然后交给测试同学,游戏公司测试同学都是黑盒测试
不会去测试你代码内部方法是否有问题。那最终还是得靠自己啊。
虽然我们程序基本上会认真的逐行debug,但由于思维惯性,可能无法从另一个角度测出问题。那就需要写代码,写测试类了。
二、怎么测试?
1、直接在每个类里面测试
public class MessageUtil { private String message; public MessageUtil(){} public MessageUtil(String message) { this.message = message; } @Override public String toString() { return message; } public String printMessage(){ System.out.println("print message"); return message; } public int calculate(int a,int b){ return a * b; } public static void main(String[] args) { MessageUtil util = new MessageUtil(); int result = util.calculate(2,5); System.out.println(result); } }
但这样测试会出现几个问题:
(1)不能一起执行
(2)测试类多了,怎么去测试?
(3)大部分测试的结果都需要人为观察对与错;
2、使用Junit单元测试框架
(1)maven会自动引入这个包,没用maven就自己去下一个包就可以了。
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
(2)好处在哪儿?
多个测试同时运行;
测试结果直观显示,错就是,对就是对;
工程代码和测试代码分离,不耦合,方便后期维护;
三、Junit 基本使用
编写测试类,一般的命名都是在需要测试的类的后面加上Test,测试类的方法上面添加@Test就变成可执行程序
public class MessageUtilTest {
@Test public void testPrintMessage() {} }
1、assert 断言
assertNotNull(Object);// 为空检测
assertTrue(Boolean); // boolean 类型检测
assertTrue(String,Boolean);方法的重载 如果发生错误,在控制台直接打印出String;
assertEquals(Object expected, Object actual)//expected期待是是否与实际结果(actual)相等
assertThat(result,Matcher) result得出的结果,Matcher 匹配值
@Test public void testPrintMessage() { //是否为空 assertNotNull(message); assertEquals(message, messageUtil.printMessage()); assertEquals(10,messageUtil.calculate(2,5)); assertTrue(30 > 10); assertTrue("to small", 300 > 100); int b = 9; //assertThat("值",matcher) 前面的值是否与后面的matcher 相匹配 assertThat(b, is(9)); }
2、Mock:不是真实的对象,是模拟出来的一个虚拟对象,并可以设置对象行为
(1)//list List<Integer> list = mock(ArrayList.class); list.add(1);
(2)//创建 Iterator Iterator iterator = mock(Iterator.class); when(iterator.next()).thenReturn("hello").thenReturn("world"); String result = iterator.next() + " " + iterator.next() + " " + iterator.next(); assertEquals("hello world world", result);
复杂的对象:
@Data public class Player { private String pid; private Person person; }
@Data public class Person { private String name; private int age; private Map<Integer, Integer> desp; }
测试代码
@Test public void mockTest() { //创建自定义对象 Player player = mock(Player.class); when(player.getPid()).thenReturn("666"); Person person = new Person(); when(player.getPerson()).thenReturn(person); person.setAge(18); person.setName("999"); Map<Integer, Integer> p = new HashMap<Integer, Integer>(); p.put(11, 11); p.put(2, 23); person.setDesp(p); assertEquals("999", player.getPerson().getName()); assertEquals(Integer.valueOf(23), player.getPerson().getDesp().get(2)); }
3、annotation
Junit中使用了很多注解,其中典型的:
@BeforeClass // 类执行之前,所以所在的方法需要时static的
@AfterClass // 类执行之后,也需要static
@Before // 方法执行之前调用
@After // 方法执行之后调用
//execute before class @BeforeClass public static void beforeclass() { System.out.println("before"); } //execute after class @AfterClass public static void afterclass() { System.out.println("after"); } @Before public void before() { System.out.println("before method"); } @After public void after() { System.out.println("after method"); }
执行的结果:
before
before method
after method
after
4、测试结果 Error,failure
failure 测试失败
Error 表示你的程序出错;
以上就是Junit常规使用的APi ;
三、结论
虽然公司没做统一规定一定要写单元测试,但是为了程序的安全,少出bug, 在认真编写代码,逐行运行调试基础之上,添加一个
单元测试,个人认为还是很有必要的,最终达到的效果就是提高代码质量,少出bug