如何编写脚本对项目代码进行分析(测试篇)

来源:互联网 发布:thinkphp商城源码 编辑:程序博客网 时间:2024/06/03 19:24

本篇将从一个测试的角度,对于在开发过程中,如何对代码进行完善的测试(包括功能以及性能的测试)。(内容属于杂谈,可能不够严谨,但希望能帮到看到这篇文章的各位)

前言

我想没有人会质疑测试的重要性,我们自己编写的代码,可能需要经过很多次的测试才能上线使用。有些bug可能是微不足道的,但是有些bug则可能是致命的。要想尽早的消灭这些bug,那么测试就成了非常重要的一环。

对于测试,有着非常多的资料,也有着非常成熟的理论体系。而且还有一种开发方式叫做“Test-Driven Development”,即“测试驱动开发”,通常也被简称为TDD。其大致思想是,在开发功能代码之前,先编写测试的代码,再编写功能代码,也就是所谓”测试先行”。

对于测试,也有着非常多的分类,下面是其常见的分类方式:
(1)按照是否需要执行软件,可以分为静态测试动态测试
(2)按照软件开发阶段,可以分为单元测试、集成测试、系统测试、验收测试、回归测试等
(3)按照测试方法来分,可以分为黑盒测试白盒测试灰盒测试等。

单元测试(unittest)

本篇主要介绍的是单元测试,它是离开发人员最近的测试,这种测试通常由开发人员来完成,而不是由测试人员来完成,它通常是由开发人员来判断自己的开发是否符合需求。

在单元测试中,如何去划分这些“单元”是非常重要的,一般我们都会按照类里面的方法为单位来划分各个单元,也就是类里面的一个方法就是一个单元,我们对它们进行逐个测试,也就是我们的单元测试。

在Python中,有数量众多的单元测试框架和工具,比如unittest、testtools、subunit、nose、pytest等等,由于它们都是用来做单元测试的,因此它们的使用方式都是非常相似的。

我个人比较倾向于使用nose,首先,我们都知道,unittest是python提供的用于单元测试的标准模块。而nose正是基于这个模块开发出的第三方框架,并且有着更好的易用性。

使用unittest编写测试脚本需要将其编写成为一个测试类,而nose不仅可以使用unittest的测试用例,并且可以支持使用函数进行测试。

至于具体如何使用nose,我就不赘述了,官方文档以及众多的博客资料肯定会比我写的更加详细。在这里,我想说明的是:

如何编写脚本对项目代码进行分析

想要更好的了解如何编写测试脚本,我们必须明确两点:

一、数据
测试中最麻烦的地方永远不在于测试脚本的编写,而在于对于数据的准备环节,这真的是一个累人的活_(:з)∠)_
准备的数据一般可以有两个来源:

1、来自于项目的真实数据,这类数据通常是比较可靠的(废话),但缺点是不够灵活。使用起来略显麻烦。

2、自己构造,根据函数预期的功能自定义数据。优点是方便且可控,缺点是可能cover不到一些边边角角的地方。

那么,我们需要准备那些数据呢?

一般来说,针对一个单元,一般是有若干个输入;而我们也是通过函数的输出来判断函数功能是否达到预期的要求。

理所应当的,我们需要准备数据应该包括预期的输入数据预期的输出数据
而且这个数据一旦准备好了,一般是不会轻易改变的(除非是函数的功能改变了),所以,从时间点上来看:

—————————————这是时间线—————————————
  ↑                           ↑
→预期输入A                     →预期输入A
预期输出B→                     预期输出B→

看,在这条时间线上,你所准备的数据始终是不变的(或者说不能变,因为这就是判断函数功能的依据)。随着版本的开发,函数内部可能被重构,但是输入和输出的变动将会是很小的(个人见解)。

二、脚本

数据准备好了,接下来改写脚本了,这里又牵扯到一个问题,你的单元测试脚本:
1、应该写在哪里?
2、data和脚本是否应该分开。
3、你所需要测试的函数是否适合进行单元测试(个人认为比较重要)?

ok,针对上面的问题一个一个的进行分析:

首先,针对前两个问题,亮出我的看法:你的测试脚本应该和项目源代码各自独立开来。并且不应该放到离你的被测代码太远的地方(方便查找),比如,你可以把你的测试代码用一个test package装起来~

理由有二:
1、方便管理,可以很方便的进行修改,而不用每次都在大段的代码里定位自己的测试函数。

2、显得有调理,一堆源代码里零零散散的穿插着测试代码,看着不揪心么_(:з)∠)_

而第3个问题,则是针对开发环节就应该注意的问题。即代码的耦合性问题。
举个例子:
当你要对使用某个框架(例如Django)开发的项目中的某个函数进行测试,你可能会遇到如下这些问题:
1、你的函数代码和框架的耦合性太高,直接导致你的测试脚本无法直接调用这个函数。结果就是,你为了把这个函数剥离出来而不得不对其进行重构以适应单元测试的需要。(但这无法从根本解决这个问题,当函数发生改变时,你不得不重新开始构造)

2、函数中存在着过多和此次测试无关的参数或者涉及到数据库的操作。在进行测试的环节,这些参数或者操作就是对你的阻碍。通常比较好的做法是:使用Mock,将这些无关紧要的东西用你准备好的数据屏蔽掉。从而把注意力放在你真正关心的事情上面。