单元测试在我国工程界,一直有一些争论的声音。反对者认为,业务繁忙无暇去做这些繁琐的测试。
支持者的理由则围绕工程上的维护性,迭代和代码共享这些点去说。
现在稍微流行一点的开源项目,都有比较可靠的单元测试用例集。
中国有一段互联网疯狂扩张的时间,很多项目在技术上尽管很烂,但因为业务方向走对了路,踩准了时机,因此最终也获得成功,对于单元测试这种表面上非常拖慢研发进度的东西,很多做业务的老大自然很是不屑。
但是随着时间的推移,产品的迭代积累的技术债务越来越高,业务增长到了瓶颈,甚至出现领先一个维度的竞品,这时候终于开始反思——什么是好的研发模式。
好了不扯这些。本文的重点是谈谈自动化测试应当遵守的一些约定。
之所以扯到单元测试,是因为我认为单元测试是最容易做的自动化测试。
在《单元测试的艺术》这本书中,作者提到他认为的“优秀的”单元测试应该是什么样的?
作者列出
- 它应该是自动化的,可以重复执行
- 它应该很容易实现
- 它应该第二天还有意义
- 任何人都应该能一键运行它
- 它速度应该很快
- 它的结果应该是稳定的(如果运行之间没有修改的话,多次运行一个测试应该总是返回相同的结果)
- 它应该能完全控制测试的单元
- 它应该是完全隔离的
- 如果它失败了,我们应该很容发现什么是期待的结果,进而定位问题所在
- 它应该是隔离的,独立于其它测试的运行
并定义单元测试
一个单元测试是一段自动化的代码,这段代码调用被测试的工
作单元,之后对这个单元的单个最终结果的某些假设进行检验。单元测试几乎都是用单
元测试框架编写的。单元测试容易编写,能快速运行。单元测试可靠、可读,并且可维
护。只要产品代码不发生变化,单元测试的结果是稳定的。
实践中,很多单元测试,一开始确实是为需要写出的,测往往是为了测试一个链路——这已经不是单元测试了,而是集成测试——只需要在另一个开发者的电脑下载代码,很可能这样的测试就无法运行了,这违反了上述重复运行的原则
有的单元测试不好维护,很脆弱,一旦代码修改,所有用例都会失败,但往往又不是代码存在问题——这种情形存在晦涩之处——从TDD的理念出发,可能是因为软件一开始并未定义清楚,也有可能确实是单元测试的断言校验写的过于细致。
将单元测试延伸到接口测试和集成测试,我们仍然可以借鉴上述的“审美” 视角,给出一些公共的约定。当然,高级别的测试有别于单元测试的“小而快”的特点,我们再效率上不那么追求的话,可以着重考虑可维护性和稳定性。
国内的一些自动化测试项目实践往往会遇到一些共性问题
- 用例复杂,难于维护——比如某企业的框架qtxx生产的用例,一个集成用例往往上千行
- 移植困难,一旦要把用例挪一个环境运行,有如抬动一座山;粘性大,用例写就之后,没有任何回头的余地,假如要移交到另个一个团队,只能是让接手的人也顺应你的框架,要么他们重新写——这一点是不是好事?我认为不是,用例的共享和可移植性(可转换性)对于自动化工程极为重要,否则,每当听到“我们要试试某某框架”都会惊出一身冷汗
- 稳定性。这一点几乎是所有自动化工程团队都会碰到的问题,项目早期都有消灭“点工”的宏愿,随着项目深入,写就框架和平台的“高手”脱离一线,开始“布道”,升职,讲方法论的时候,留下你在那堆经常运行失败又发现不是bug的日常维护工作的泥淖中无法自拔,有时候甚至导致对自动化本身的怀疑。业界有许多对 UI 自动化深恶痛绝的工程师,大概都遭受过这些摧残。
造成这些问题的原因可能有许多。其中一点,就是不注重用例的审美。
写用例和写代码有些共同之处,对于自动化用例,本身也是代码——如果只是完成一条当天可以运行通过的用例——用这样的目标去生产用例,那么用例不稳定不可维护是迟早的事情。
写用例的一开始,就需要抱持一种目标
它们是要长期多次运行的
一旦失败,意味着发现了系统的问题,或者流程上的问题
很多团队做自动化,KPI或者OKR是本月完成多少条case ,并且做的很神圣很有那么一回事,雇一个前端做一些表盘,每个人的进度可视化,很漂亮,然而这本质都是形象工程,上级走过来一看,哦,很漂亮。但是自动化工程本身要解决的问题没有得到解决,甚至恶化情况,本来大家点的好好的,现在除了继续点,还得额外护养一堆研发人员早就不关心的用例。
什么是好的自动化用例
——从单测版中摘出几条认为是适用的
- 它应该是自动化的,可以重复执行
- 它应该很容易实现 **尽管集成用例更加负责,但是用例的视线应该还是以简单为主,最好不要太多的控制流转语句, 纷繁复杂的if else 嵌套最好消失;不要放太多花哨的特性,简单朴素为主 **
- 它应该第二天还有意义——这一条对集成测试仍然是有意义的
- 任何人都应该能一键运行它
- 它速度应该比较快,集成测试不追求单元测试的速度,但是速度仍然是一个考虑的因素,我们不希望,一个用例运行半个小时,十几分钟
- 它的结果应该是稳定的(如果运行之间没有修改的话,多次运行一个测试应该总是返回相同的结果)结果稳定是个比较容易犯的错误
- 如果它失败了,我们应该很容发现什么是期待的结果,进而定位问题所在
- 它应该是隔离的,独立于其它测试的运行
网友评论