android代码自测

TDD

https://www.raywenderlich.com/7109-test-driven-development-tutorial-for-android-getting-started

Android应用功能测试

https://developer.android.com/training/testing/

编写自测代码的好处

Testing also provides you with the following advantages:

  • Rapid feedback on failures.–解放双手,提升测试效率

  • Early failure detection in the development cycle. –开发提前发现错误

  • Safer code refactoring, letting you optimize code without worrying about regressions. –保证重构不影响功能,很关键

  • Stable development velocity, helping you minimize technical debt. –提前发现错误漏洞,提前纠正不合理的设计


测试驱动开发概念,迭代开发工作流

When developing a feature iteratively, you start by either writing a new test or by adding cases and assertions to an existing unit test. The test fails at first because the feature isn’t implemented yet.

It’s important to consider the units of responsibility that emerge as you design the new feature. For each unit, you write a corresponding unit test. Your unit tests should nearly exhaust all possible interactions with the unit, including standard interactions, invalid inputs, and cases where resources aren’t available.

image

Figure 1. The two cycles associated with iterative, test-driven development

The full workflow, as shown in Figure 1, contains a series of nested, iterative cycles where a long, slow, UI-driven cycle tests the integration of code units. You test the units themselves using shorter, faster development cycles. This set of cycles continues until your app satisfies every use case.


如何编写具有可测试性的代码

https://www.cnblogs.com/wenpeng/p/8266472.html

很多人在开发过程中都强调测试驱动开发,单元测试,代码测试覆盖率。那么为什么大家要强调这些?这些工作非做不可么? 其实并非绝对。不论是驱动测试开发,还是代码测试覆盖率,本质上都只是方法,而不是目的。人们的真正的目的,是编写出优秀的,高质量的具有可维护性的,能够很好扩展的代码。

什么是具有可测试的代码?

  所谓具有可测试的代码,是指能够很轻松的执行各种测试的代码。

  具有可测试性的代码有什么特点?

  1.   控制性–输入参数或插桩数据。

    控制性是指测试者给在被测试的软件提供固定的输入数据的方便程度。换句话说就是软件本身接受定义明确的参数,并且这些参数可由测试者灵活的传入,软件在接受到这些参数后通过一系列运算返回固定的结果。任何软件都应该清楚的表明自己需要什么参数,以及将会生成什么返回值。此外任何软件都应该应该抽象它的依赖,譬如参数或底层模块,并为外部调用者提供随意注入的方式。当然软件代码本身应该清晰,整洁,目标明确。      2.   可见性–返回或回调。

    可见性是指测试者观察正在测试的软件的当前状态以及它所产生的任何输出的能力。换句话说就是软件应该将内部运算的状态(一般是指错误状态)和输出结果清晰明确的告知测试者。可见性一般都是通过方法执行后验证后置条件完成。      3.   简约性。

    一般而言,简约性对任何系统在任何情况下都是一个正面的属性,测试毫无疑问也不例外。简单和极其内聚的组件非常适合测试,因为他们暴露出来的方法少,需要的测试也就少,而需要的测试越少,就越能做得可靠,快速。

如何得到编写具有可测试性的代码和程序呢?

  1. 坚持面向对象编码原则:
  • 单一责任原则
  • 开放/封闭原则
  • 里氏代换原则
  • 接口分离原则
  • 依赖反转原则
  1. 坚持编码建议
  2. 使用设计模式

        编写了测试,我们仅仅完成了测试驱动开发的一部分。测试仅仅是基础工程,我们后期可以依托测试,进行持续的重构,而丝毫不用担心破坏了原有的代码逻辑和返回结果。重构,才是坚持测试驱动开发的核心部分。而持续的重构,最终我们得到的就是设计良好的代码,还附带一堆高代码覆盖率的测试作为奖励。

功能测试类型

Unit test – 单元测试

  • build unit tests that run on your local machine.
  • Build Instrumented Unit Tests — build unit tests that run on an Android device or emulator.

Integrate test – 集成测试

  • junit + Mockito
  • AndroidJunitRunner

UI test – UI自动化

  • Test UI for a single app —Espresso testing framework.
  • Test UI for multiple apps — UI Automator testing framework.

Mockito

https://site.mockito.org/

https://static.javadoc.io/org.mockito/mockito-core/2.23.4/org/mockito/Mockito.html#do_family_methods_stubs

Mockito关键api

方法名 方法描述
thenReturn(T value) 设置要返回的值
thenThrow(Throwable… throwables) 设置要抛出的异常
thenAnswer(Answer<?> answer) 对结果进行拦截
doReturn(Object toBeReturned) 提前设置要返回的值
doThrow(Throwable… toBeThrown) 提前设置要抛出的异常
doAnswer(Answer answer) 提前对结果进行拦截
doCallRealMethod() 调用某一个方法的真实实现
doNothing() 设置void方法什么也不做
graph LR
Ax1(测试输入数据x1)--> B(测试单个功能或方法代码x)
Ax2(测试输入数据x2)--> B
Ax3(测试流程插桩数据x3)--> B
Ax4(测试流程插桩数据x4)--> B
B--> C(单个可测试功能代码x)

封装思路:

左边的数据,封装成一个model/bean,传递给测试方法,可以动态新增字段来支持新的功能

输入数据和插桩数据会有多个,每个是为了测试方法内部的不同分支流程,达到更高的覆盖率

robolectric

http://robolectric.org/

https://github.com/robolectric/robolectric

@VisibleForTesting

可以把这个注解标注到类、方法或者字段上,以便在测试的时候可以使用。 这个Annotation只是一个指示作用,告诉其他开发者该函数为什么有这么大的可见程度(为了测试单元或者其他类对其测试使用)

因此经常用来修饰public和protected,用其修饰private不会报错,但是意义很小。它不能改变任何权限。

Guava has a @VisibleForTesting annotation, but it’s only for documentation purpose.

A simple annotation that tells you why a particular property access restriction has been relaxed.A common trick to use in testing is to relax access restrictions to default for a particular property, so that you can use it in a unit test, which resides in the same package (though in different catalog). Whether you thing it’s good or bad, remember to give a hint about that to the developer.

该注解用来说明,为什么该变量或者函数私有访问权限被释放成“公有”或者“package可见”。 单元测试是有访问权限的。所以加上@VisibleForTesting是说明,为什么你定义其他类似函数需要用private,这里这个test123函数需要释放私有访问权限呢?哦,原来是需要对测试单元可见(private函数 测试类是访问不了的)。

类似的,该注解经常和public一起使用,告诉大家为什么这个函数我现在设计成public的,是为了给其他测试的类使用的。总的来说@VisibleForTesting就是一个标记(Marker)。

VisibleForTesting并不能改变权限,在单元测试以及其他package中,访问权限加不加该注解没有任何改变。 @VisibleForTesting没有那么强大,它只是一个很基本的注解。

This annotation is better than nothing in such a case because it at least makes it clear to others using the construct that there is a reason for its otherwise surprisingly relaxed visibility.