单元测试系列之一开篇

1,111 阅读4分钟

最近一直在搞单元测试,对一些测试工具进行了封装,提供aar包,方便其他人引用。做的差不多了,过来总结一下,分享下自己封装的框架。

单元测试概念

单元测试是为了测试某一个代码单元而写的测试代码。一个代码单元,可以是一个模块,一个类,也可以是一个方法。在OOP领域,一个代码单元指的是一个类的一个方法。所以,这里说的单元测试就是为了测试某一个类的某一个方法而写的测试代码。

例子:

现有的类:

public class Calculator {
   public int add(int num1, int num2){
       return (num1 + num2);
  }
}

测试类:

public class CalculatorTest {
   Calculator calculator;
​
   @Before
   public void setUp() throws Exception {
       System.out.println("测试准备工作");
       calculator = new Calculator();
  }
​
   @Test
   public void testAdd() {
       System.out.println("测试方法 testAdd()");
       int sum = calculator.add(23);
       Assert.assertEquals(5, sum);
  }
​
   @After
   public void tearDown() throws Exception {
       System.out.println("测试结束");
  }
}

由示例代码也可以看出,测试主要分为三个部分:

  1. 准备工作setUp() 用来做一些初始化的工作,需要使用@Before作注解。

  2. 测试方法test**() 一般命名规则是test+需要测试的方法名,并且使用@Test作为注解。在此处调用需要测试的方法,获得运行结果,然后验证运行结果与预期是否一致。

  3. 结束测试tearDown() 在测试结束后,有时需要释放一些资源,测试可以在该方法中统一释放。需要使用@After作注解。

其中,setUp()tearDown()非必需,视情况而定。一般来说,写单元测试都需要用到一些测试框架,本文介绍的是JUnit4。上面示例代码中的Assert.assertEquals()就是JUnit中用来验证结果的方法,另外还有assertEquals,assertTrue, assertNotNull等等。

单元测试的好处

  1. 提升代码质量 降低crash率、减少bug,也可以更早点发现bug

  2. 提升代码设计 当你为自己的代码写单元测试的时候,尤其是采用TDD的方式,你会把每个类写的比较小,功能单一,这是软件设计里面很重要的单一职责原则。此外,你能把每个功能职责分配的很清楚,而不是把一堆代码都塞到一个类里面(比如Activity)。当你TDD的时候,你是从一开始,就从一个代码的使用者,或者说维护者的角度,去写你的代码。这样写出来的代码,自然会有更好的设计。

  3. 给你自信

有单元测试来保证你的代码是对的,这对于你写代码、发布代码、重构都提供了信心保证,没有那么多的担心。

学习成本

* JUnit
* Mockito
* PowerMock
* Robolectric
* Espresso
* UI Automator
* DI
* 。。。

时间成本

在一个没有单元测试的项目里添加单元测试,刚开始肯定会花费大量时间。因为你需要花时间去调整各个部分的代码,让他们变得容易测试。

在刚开始写单元测试时,可能会很花时间,但一旦你习惯了这种开发模式后,单元测试是可以为你节省时间的。因为等你熟悉了如何写单元测试以后,要对一个类、一个方法写单元测试,是很容易的一件事情。如果你发现一个类不好测,往往是因为这个类的设计是有问题的。除此之外,在写单元测试的过程中,你可以慢慢的搭建自己的一套测试框架,简化一些常用的繁琐的写法,让写单元测试变得更简便快捷。

总体来说,写单元测试刚开始可能会花一点时间,但从长远来看,这个时间的付出是值得,而且单元测试是可以节约时间的。

技术选择

根据需求,要包括Android UI测试和Java层测试,所以会用到这些东西:junit + mockito + powermock + espresso。另外为了使测试报告美观,使用extentreport进行报告美化。除了这些测试框架自带的功能,还封装了一些其他的东西,比如CPU使用率、内存使用情况等。对这些第三方的工具封装之后,用户只需要引入3个aar包就可以进行测试。

在使用时,首先将三个aar包复制到app/libs/目录下,

截屏2021-10-11 上午9.52.33.png

并在build.gradle中添加如下代码:

  testImplementation files('./libs/UnitTestSDKJava-1.0.0.aar')   
  androidTestImplementation files('./libs/UnitTestSDKAndroid-1.0.0.aar')
  testImplementation files('./libs/UnitTestSDKReport-1.0.0.aar')
  androidTestImplementation files('./libs/UnitTestSDKReport-1.0.0.aar')

其中UnitTestSDKJava-1.0.0.aar是Java层面的测试,不需要启动模拟器或者连接真实的Android设备,而且与业务代码无关,所以使用testImplementation引入依赖;UnitTestSDKAndroid-1.0.0.aar是Android UI层的测试,一般使用androidTestImplementation引入依赖,但如果需要进行异步更新UI的测试,就需要在业务代码中插入测试相关代码,这个时候就需要使用implementation引入依赖。

注意:在使用Android studio创建项目时,会自动引入一些单元测试相关的包,为避免依赖冲突,请删除自动引入的单元测试依赖包。

到这里,你就可以使用本框架写单元测试啦。