关于你提出的几点:1. 单元测试是一种测试,它不是代码的一部分;2. 单元测试是最低层级的测试,它只保证函数的可靠性,不保证其它;3. 单元测试应该能保证每一个函数的可靠性。
当今前端测试的问题在于仅仅对函数的输出进行验证并不能很好的确认其行为。因为js还需要对DOM进行操作,需要对CSS进行操作,IE,FF显示效果不一致等等。使得前端开发程序员不得不人肉进行测试,查看程序是否符合预期的显示效果。你们认为如何才能提高前端单元测试的有效性呢?
说实话这个问题是我刚刚接触单元测试的时候,也一直被困扰的一个问题,那就是,GUI界面如何单元测试?我记得在几年前,我还就这个问题特地咨询过gigix,当时他告诉我说“测试能测试的”。但是当时我对单元测试一知半解的时候,对于这个答案也是不甚了了。
今天我不敢说对这个问题已经理解得非常透彻了,但是我想把我的想法说出来,大家讨论一下。
在解释这个问题之前,我想重复一下我对单元测试的理解:单元测试是最底层的测试,它只保证函数的可靠性。
但是这里有一个重要的概念,我们需要进一步的说两句:什么叫“函数”?
从语法而言,函数就是语言概念上的一个语句块,这个语句块接收0个至多个输入,产生0个至多个输出。但是,所有的语言都没有规定函数需要有怎样的“语义”。于是,我们也不能在解释器或编译器层面阻止一个“坏函数”的诞生。例如,下面这两个函数,如何测试?
x = 1;
function a()
{
global x = x+1;
if (x < 10)
setTimer(100, b);
}
function b()
{
feed = time.now();
diff = random(feed).getInteger(10);
global x = x - diff;
}
函数a严重依赖于函数b,以及平台相关的定时器和一个状态未知的全局变量x。而函数b也依赖于平台相关的函数time和一个状态未知的全局变量x。这样两个函数要进行测试,难度是非常高的。简单的说,a几乎可以认为是无法测试的,因为它并不是一个我们所谓的“输入-处理-输出”函数,而是依赖于定时器这样的平台相关操作,定时器这种东西是很难模拟的,就算模拟出来意义也不大,因为真实的定时器几乎可以肯定不会跟模拟的定时器有相同的表现——而这个表现,正是我们编写这个函数的目的。函数b倒是可以测试,但你必须事先为它模拟好一个时间函数(类),一个随机数函数(类),和一个确定状态的全局变量x——这些工作在一些语言里可以做到但要付出很大的代价,在另一些语言里几乎可以说是不可能的任务。
那么,接下来的工作倒也变得很简单了:我们就要做一个价值上的衡量,我花很多时间精力去实现这些测试基础框架(对了,这些基础框架也需要测试),跟我整个系统的测试工作本身相比到底值不值?
其实在大部分时候,这个答案是“不值”。如果为了一个系统的单元测试要做如此多的工作,其难度不亚于开发一个新系统,那我们当然会选择不测试。
上面的例子说明了两点:1、函数并不是天然可测试的;2、不是所有的“函数”都是需要测试的。
文章来源于领测软件测试网 https://www.ltesting.net/