本地化单元测试
本地化的意思就是你要测试的代码和Android框架的API没有任何的关系,只需要开启Java虚拟机就能运行起来的测试:
打开test下的ExampleUnitTest文件,默认的代码是这个样子的:
import org.junit.Test; import static org.junit.Assert.*; /** * Example local unit test, which will execute on the development machine (host). * * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> */ public class ExampleUnitTest { @Test public void addition_isCorrect() throws Exception { assertEquals(4, 2 + 2); } } |
这是Google给我们提供的一个单元测试的例子,就是断言两个参数是否相等。可以把光标放在函数名称上,然后按下Ctrl+Shift+F10来运行这个测试:
运行单元测试demo
可以很快看到下方的控制台窗口打印出了绿条,因为这个过程并不需要Android API的支持,它只是开启了一个Java虚拟机来运行这段函数,并给出结果,所以速度是相当快的,比build整个项目不知要快到哪里去了。同时控制台的打印结果也证明这个函数经过测试是符合我们的的预期的,因为2+2显然等于4。
相反的,如果测试没有成功,就会打印红条,这时候就需要查找失败的原因。
仿照Google给出的例子我们也可以在这里测试自己的函数:
import org.junit.Test; import java.util.ArrayList; import java.util.List; import static org.junit.Assert.*; /** * Example local unit test, which will execute on the development machine (host). * * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> */ public class ExampleUnitTest//类名可以随便取,不过最好是有实际意义的名称 { @Test//所有的测试都必须加上@Test注解(非常重要!!),这样测试框架才能识别你的代码,并把它当作单元测试进行处理 public void addition_isCorrect() throws Exception { assertEquals(4, 2 + 2); } //测试无参无返回值的函数 @Test public void printText() { System.out.println("Hello test!"); } //测试带参数和返回值的函数 @Test public void printTextWithArgs() { System.out.println(text("Hello test with args!")); } //被测试的函数 private String text(String text) { return text; } @Test public void complexFun() { List<String> list = calculateLevel(111); System.out.print(list); } //复杂函数的测试 private List<String> calculateLevel(int level) { List<String> list = new ArrayList<>(); int sunNum = level / (5 * 5); int moonNum = (level - (5 * 5) * sunNum) / 5; int starNum = level - sunNum * (5 * 5) - moonNum * 5; //根据不同图标的个数添加不同的元素 for (int i = 0; i < sunNum; i++) { list.add("日"); } for (int i = 0; i < moonNum; i++) { list.add("月"); } for (int i = 0; i < starNum; i++) { list.add("星"); } return list; } |
我们看一下复杂函数的测试结果:
复杂函数的测试.png
需要注意的点:
1、在test目录下的单元测试,只能测试和Android API无关的函数,例如你要在这里打印log,通常来说就使用Java的System.out.print()函数打印,如果你用Android的Log类去打印,肯定会报错的。
2、所有的测试函数都必须加上@Test注解,只有加了注解,该函数才能被测试框架识别并处理,还有就是带@Test注解的函数一般都是public并且无参无返回的函数,如果你要测试带有参数和返回值的函数,就需要写一个不带@Test注解的函数然后在测试函数里面调用你的被测试函数。
3、运行单个测试函数需要把光标放在测试函数的函数名称上,按Ctrl+shift+F10或者右键选择运行。如果要运行该测试类中的所有测试函数,就把光标放在除了函数名称的任意位置或者直接在导航栏里选中该测试类即可,运行方法和上面单个函数的方法一样。
图形化测试
图形化测试就是要测试的代码必须运行在搭载Android系统的硬件设备或者虚拟机上。
我们先来看下Google给的例子:
import android.content.Context; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.*; /** * Instrumentation test, which will execute on an Android device. * * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> */ @RunWith(AndroidJUnit4.class) public class ExampleInstrumentedTest { @Test public void useAppContext() throws Exception { // Context of the app under test. Context appContext = InstrumentationRegistry.getTargetContext(); assertEquals("com.mewlxy.qqlevelbar", appContext.getPackageName()); } } |
从这个例子中我们可以看出在Android单元测试中,Google给出了一系列API方便开发者进行Android设备相关的单元测试,例如可以利用
Context appContext = InstrumentationRegistry.getTargetContext();
获取Context变量,有了它,我们就能做好多和Android API相关的测试了。
@Test//Android log打印 public void logTest() { Log.d("android", "Hello, android test!"); } |
相对于本地测试,UI相关测试的API要稍微复杂一点,我平时用的比较多的也是本地测试。想深入了解UI测试的小伙伴可以戳这里(需科学上网):
https://developer.android.com/topic/libraries/testing-support-library/index.html?hl=zh-cn#espresso-matching
总结
本篇文章的主要目的就是想让大家了解下Android的单元测试,并学会编写单元测试。在今后的开发过程中利用单元测试来提高自己的开发效率。当然单元测试这块的内容也比较多,我也只是了解了一点皮毛,今后还要继续学习。
源码