如果单元测试很费劲的话,说明你的程序的可测试性程度较低。
一段代码可以从很多个维度来评估,一般来说初学者会比较关注功能覆盖和容错性,再高级一点会关注可读性和可维护性,但是如果真的去参与到一个大型项目中,你会发现可测试性也是极为重要的。
提高可测试性的方法有很多,可以从需求、开发框架等方面入手。
像你所说的:
不过我还是习惯于直接看效果,看UI上的显示和print出来的结果
这说明你的程序设计上有缺陷使得可测试性较低。
首先我们认为UI交互的测试是非常难的,所以我们应当尽可能避免对UI和交互进行测试,而尽可能的测试其最接近的逻辑。vczh说的选一个合适的MVVM框架,就可以很大程度上避免对最终UI和交互进行测试,而是针对VM进行测试,而VM与UI交互之间的一致性,则由MVVM框架保证。
如果没有MVVM框架,那么可以自己动手做一个,将项目的结构划分成MVVM的形式,然后在VM上进行单元测试,则远比针对UI进行单元测试简单得多。
其次是依赖于print,依赖于print意味着程序有较少的检查点和异常检测机制,一个健壮的程序应当在运行中自动侦测系统的异常情况并作为异常抛出。例如所有方法的入口检查,检查所有参数是否符合预期,或者使用断言来对数据进行一些约束,若不能满足这些约束便直接抛出异常。
针对很大可能会影响程序正常运行的数据异常,应立即抛出异常。而针对正常情况下不可能出现的一些问题,则使用仅仅在Debug模式才会执行的断言代码来标识,这样一来,只要在Debug模式下单元测试能通过,说明这些断言通过了,如果这些断言没通过,单元测试就会爆出来,多简单。
其次就是程序结构设计上始终要遵循高内聚松耦合的原则,如果只能针对UI进行测试,说明UI和逻辑不能进行有效地解耦,如果必须要print才能测试,则说明程序的内聚度不够,而无法对外界呈现出职责单一、测试简单的接口。
最后,如果程序可以通过一些简单地print语句暴露出来一些问题,那么也可以选择一个合适的单元测试框架对程序内部的检查点(print)来进行测试,即针对指定的输入,断言内部的检查点会输出什么信息。话说,偶正打算弄这么个工具,针对日志进行单元测试。