你或许已经发现了关键字的实现代码里引入了更多的语法和特殊字符。这不用多虑,通过把细节抽象成关键字, 我们的测试脚本看起来整洁多了,可读性大大增强,现在我把更新过的测试脚本贴上如表3所示,更直观展示了修改后的效果。
表3 更新过的测试脚本
虽然某些程度上增加了关键字这一部分的代码,但获得了整个测试用例脚本的干净清爽,这一做法是值得尝试的。
重复
上面我们已经学会通过提炼可复用的关键字改进了测试脚本,但还存在其他问题。一个问题是我们之前提到的,即每隔一个测试步骤就包含用户名fred。另一个更大的问题是重复,从表3修改过的测试来看,每一对关键字(Create Account和Status Should Be)组成一步验证测试,每一步都要提交一个不同的密码并与比较系统返回的状态值和期望值,我们看到,除了输入的密码和期望状态值不同之外,其他部分基本都是一样的。
重复的代码将毁掉可维护性。现在假设我们的用户交互分析师指出产品系统的其他部分并不要求用户创建账号(Create)而是要求他们注册(Register),这就在同一个系统里出现了用户交互接口和使用术语的不一致,而用户交互分析师坚持整个系统应该杜绝这种不一致性,于是我们决定把Create命令变成Register。
这样一来,对测试会产生的影响有多大?我们封装了关键字Create Account来创建用户,现在看样子只需要把关键字的实现部分中调用Create命令的地方改成Register就可以了,但这样一来的又一个问题就在于我们的测试的关键字和被测的功能也出现了不一致的叫法,这会使人困惑。或许以后我们每次验收测试跑完之后,都需要向这些测试报告的经理或者市场人员解释这些关键词。
为了保持术语一致性,最好的做法是修改我们的测试用例。上面的测试用例中,至少有八个用到Create Account关键字的地方可能都要改成Register。还有两个关键字也都用到了Create Account。而现实会更残酷,可能有成千上万的测试步骤都调用了那个关键字。由此,我们得出结论:重复绝对会增加维护成本。
重复往往预示了潜藏在测试中的某一重要概念。当这样的重复不是发生在个别测试步骤而是一系列的步骤的时候,情况更是这样。
思考一下表3中的测试脚本,看看前面两行究竟说明什么。没错,它们核实创建用户命令是否拒绝1234!@$^这一密码。那再来看看第9~10两行。这两行来证实创建用户命令接受!C2456这一密码,再进行一次抽象概括,我们惊奇地发现,原来这两行测试的本质便是接受(Accept)和拒绝(Reject)。但遗憾的是在表3的测试中,这一本质却被埋没了。接下来我们利用两个新的关键字来使概念明朗化,如表4所示:
表4 用两个新的关键字来使概念明朗化
这两个新的关键字不仅将重写我们的测试脚本,同时也给接受密码和拒绝密码下了定义:接受密码即调用被测系统的Create命令,系统报告用户创建成功;拒绝密码即调用Create命令,系统报告密码无效。