做一个项目势必要进行单元测试以保证程序的健壮性,以便保证版本迭代时功能正常。但是如果一个程序(如CMS等)本身就是依赖于数据库的,应该如何在保证不会破坏数据库的情况下进行单元测试呢?
举例:
访问?id=1的页面,先查询
sql
SELECT * FROM `data` WHERE `ID` = 1
,然后将其赋值给$data->ID
、$data->Title
这些属性;要保证这些属性的值正常。
然后,根据一些信息算出$data->Hash
,如$data->Hash = md5($data->ID)
,这些计算的值也要正常。
接着,删除id=1
的文章,要
sql
DELETE FROM `data` WHERE `ID` = 1
,必须保证ID所在行被删除。
再其次,后台发布一篇文章,必须使得数据库内多出ID=2
,内容为设定值的文章。但是HTML代码内容不一定要相同,可以允许诸如多余的空格、换行。
还需要模拟XML-RPC协议发表一篇文章。
像以上的内容,应该如何进行单元测试呢?
首先,请先想清楚你要作的是单元测试还是功能测试。
如果你的目的是验证这两个页面是否正常工作,你想做的是功能测试。这种情况下,可以先配置好测试数据,用selenium之类工具进行测试。
如果要作单元测试,那么你要测的是哪个单元?
也许从代码来看一个显示ID和title的页面已经非常简单了,但它并非一个单元。
事实上它处理了http请求,绑定了URL参数,用参数查询了数据库,从数据库返回结果中读取了需要的数据,做了业务逻辑需要的处理,根据处理结果绑定了一些数据到页面模版中,把模版渲染成为html页面,发送页面给客户端,如果页面上有js之类的脚本的话,还需要在客户端浏览器中执行这些脚本。之后用户才真正看到了页面。
上面任何一步出错,都会导致这个页面工作不正常。
很少有程序单元能不依赖于环境独立完成功能,它能做的是根据环境提供的输入,给出正确的输出。相应的,单元测试无法保证整个功能正常工作,只能验证这个单元接受特定的输入后,给出的是预期的输出。
所幸的是,大部分的依赖都是成熟的第三方代码。一般来说,只要给出了正确的输入数据,它们就会产生正确的输出(行为)。因而可以假设我们测试的关注点,在于确保我们自己写的代码,在从依赖环境中获得了正确输入后,向其它依赖正确的输出。
比如说,当你测试时,一般不会怀疑输入了?id=1后你的代码却从参数中读出id=0,因为那是你的代码信赖的第三方,你只要确认给它的输入是正确的。同样的,如果你确认了delete的SQL语句是正确的,一般来说也没有必要去怀疑数据库是否正确的执行这条语句。
从你的问题来看,你大部分的问题关注的是功能测试而非单元,所以可能单元测试并不是你真正需要的。如果要作的话,可能主要要测md5相关的那一部分。
另一个关于单元测试但是超出测试的问题,从你的描述来看似乎你的程序里并没有单元,这可能也会对单元测试造成一些困难。