单元测试是开发人员需要自己完成的一个测试,可能有时候我们会觉得写测试会特别费时间,毕竟代码写下去并运行后我们还是可以保证它的正确性的。但是当项目被频繁的修改的时候就会有很多莫名奇妙的 bug 冒出来了,定位一个 bug 至少都需要经历重新编译一次程序然后再安装到手机上并重现 bug 的场景的流程,因此适当的写一些单元测试还是可以节省调试时间的。
什么是单元测试
- 跟普通的代码相比,它是验证代码正确性的代码。
- 它是由开发人员自己编写的测试代码。
- 单元测试可便于后期的重构和维护
- 可优化设计,单元测试能使开发人员的代码便于测试的方向优化,解除软件中的耦合。
- 单元测试也是一种特殊的文档,它可展示函数或则类如何使用。
Android Studio 中生成好的单元测试
我们在 AS 新建的工程都会默认含有存放测试文件的包
简单的看下 ExampleUnitTest 文件里的代码
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
从以上代码就可以猜出 assertEquals 方法的作用就是用来判断其所传入的两个参数是否相等的,运行只需右键点击 run ,就可以得到一个结果,而这些都是毫秒级别的操作。
如何编写单元测试
在 Android 中虽然有很多的测试优秀的测试框架来替代 Junit ,但是由于 Junit 的简单性以及基础性,所以还是得先了解它再去学别的好一些,接下来看一个简单的例子 。
/**
* 加法的接口
*/
public interface Adder {
public int add (int a, int b);
}
/**
* 加法实现类
*/
public class AdderImpl implements Adder {
@Override
public int add(int a, int b) {
return a + b;
}
}
选择对应的类,将光标停留在类名上,按下 ALT + ENTER ,在弹出的弹窗中选择Create Test 勾上图中的选项,就可生成一个文件。
我们在 setUp 函数初始化对象,在 tearDown 函数销毁对象,在 add 方法里测试该对象方法的正确性。
package cn.demon96.testandroidtest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class AdderImplTest {
Adder mAdder;
@Before
public void setUp() throws Exception {
mAdder = new AdderImpl();
}
@After
public void tearDown() throws Exception {
mAdder = null;
}
@Test
public void add() {
assertEquals(0, mAdder.add(0,0));
assertEquals(1, mAdder.add(-1,2));
assertEquals(Integer.MAX_VALUE + 1, mAdder.add(Integer.MAX_VALUE,1));
}
}
通过以上简单的操作,在一些重要的方法中适当的使用单元测试就可以在代码经过大量的修改的情况下只需要运行一下测试用例就可以在几秒中的时间里发现问题。
运行多个测试用例
当测试类多了的时候一个一个的运行反而会更浪费时间,这时候可以将测试类分组进行统一的运行,运行多个测试类用到的是 TestSuite
类,此类有两种用法。
- 用法一:使用
JUnit4TestAdapter
包装测试类
package cn.demon96.testandroidtest;
import junit.framework.JUnit4TestAdapter;
import junit.framework.Test;
import junit.framework.TestSuite;
public class MainTest {
public static Test suite() {
TestSuite suite = new TestSuite("cn.demon96.testandroidtest");
suite.addTest(new JUnit4TestAdapter(AdderImplTest.class));
suite.addTest(new JUnit4TestAdapter(ExampleUnitTest.class));
return suite;
}
}
- 用法二:使用注解
package cn.demon96.testandroidtest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
AdderImplTest.class,
ExampleUnitTest.class,
})
public class MainTest {
}
Junit 简介
Junit 是基于 java 语言的单元测试框架,已默认配置在安卓项目中。
testImplementation 'junit:junit:4.12'
- 使用时的注意事项
- 测试的方法应该是
public
的 - 可选用
setUp
进行初始化工作, 使用tearDown
进行收尾工作。 - 每个测试方法没有关联,执行的顺序也不一定是代码中的顺序,因此测试方法之间不要存在有依赖性。
- Junit 的断言和失败提示
是否相等 assertEquals
assertEquals(0, 0);
是否为真 assertTrue
assertTrue(true);
是否为空 assertNull
assertNull(null);
是否为同一个对象 assertSame
String s1 = "123";
String s2 = s1;
assertSame(s1, s2);
- 失败提示
assertNull("这个不是空的!", new Object());
更详细的用法可以看 Assert
类的源码。
测试哪些内容
- 边界条件
- 覆盖执行路径
参考
- 《Android 开发进阶 从小工到专家》何红辉