<img src=”https://evernotepic-1253152250.cos.ap-shanghai.myqcloud.com//20191023155334.png” width=450px>
你是否注意到过你的自动回归测试不稳定并且经常失败? 你和你团队的其他成员是否不再信任自动回归测试的结果? 当你的修改App后,你是否很难更换测试?
我们从实践经验里总结了了5个关键技巧,来进行更灵活的测试,让我们开始吧!
使用测试专用的Selector
大部分自动测试失效的原因都是由于你或者团队中的其它人重新编辑了用于自动测试的元素(element)。
解决这个问题的方法是在 HTML 和自动化测试中使用测试专用的标识符。当这个标识符添加到代码中后,测试便可以不再依赖和使用原代码中已经存在的id
或者class
,从而避免了未来可能发生的测试冲突。
为了让这个方法起作用,你还需要在团队成员间对使用什么样的测试标识符达成共识。
例如,在HTML中,你已经向所有人清楚标识了自动化测试将会使用该元素。其中qaid
代表该标识符是用于测试用途:
let testDOM = document.querySelector('a[data-qaid="shop-ankle-boots"]');
使用
data-*
作为标识符能够保证该属性的内容不会显示在页面中(会被页面解析器忽略)或者在 JS 中被意外引用。因此这里建议所有的测试属性都使用data-
前缀,关于这个 H5 的新属性更多的可以点击使用数据属性了解。
独立地自动化单个流程
我们都知道,应当保证每个自动化测试不依赖于先前测试的输出或先前测试中创建的数据,使每个测试之间彼此独立有助于确保测试的结果无论在怎样的执行顺序下都是相同的。
这种独立性带来的另一个好处是保证了测试在单独运行和共同运行时的结果一致。从而使你能够更轻松的将测试组合到不同的套件中,以促进测试的重用。关于测试隔离原则可以查看单元测试的 F.I.R.S.T.原则。
DRY 原则(Don’t Repeat Yourself)
当编写自动化测试时发现要在三个以上的地方重复同一组步骤时,那就是时候开始考虑最大程度地减少编写重复代码的方法了。 例如,如果你经常在代码中使用重复的步骤组合,而这些步骤却不属于测试框架 API,那么可以创建包含这些步骤的函数来实现可重用性,并将其导入到测试文件中;如果有语句多次重复的,则应考虑将重复的代码放入可重用的函数中。除了提高可读性之外,这还有助于代码的整体可维护性。
但你在写代码过程中可以不必过分担心写出不够 DRY 的代码,可以在提交代码之前再考虑将其重写为 DRY 的代码。
以下面的代码段为例:
printAccountBalance(account);
{
if (account.fees < 0) {
console.log(`Fees: -$${account.fees}`);
} else {
console.log(`Fees: $${account.fees}`);
}
if (account.balance < 0) {
console.log(`Balance: -$${account.balance}`);
} else {
console.log(`Balance: ${account.balance}`);
}
}
以上代码主要是调整了货币格式并输出,因此我们如果为货币格式转换这一功能创建一个可重用的函数,则代码段会变得更加易读:
// 货币格式转换
formatAmount(dollarAmount);
{
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
return formatter.format(dollarAmount);
}
printAccountBalance(account);
{
console.log("Debits", formatAmount(account.debits));
console.log("Fees", formatAmount(account.debits));
}
如你所见,我们删除了所有的if
语句,使代码的整体可读性和可维护性都变好了。
DRY概念在软件领域非常的常见,如果时间允许我们甚至可以谈几个小时,但如果你对这个概念有兴趣,可以点击更多了解。
消除无意义的等待(wait)
在构建异步的自动化程序时,有时候需要延时一段时间以等待某些操作完成。在多次的自动化测试经验中,我们发现,数量繁多的延时语句将使代码变得杂乱。有时是因为目标对象没有在预设时间内出现导致报错,有时是因为操作在设置的超时时间前完成了但仍然继续等待着。这些情况导致的结果就是程序白白浪费了大量的等待时间。
// 等待固定时间
await setSignIn(userName, password);
const waitTime = 10000;
await webdriver.wait(waitTime);
await webdriver.click(provinceDropDownList.withText(provinceCode));
// 等待目标元素加载完成 || 超过超时时间
await setSignIn(userName, password);
const waitTime = 60000;
await webdriver.expect(isSignedInConfirmation.exists).ok({ timeout: waitTime });
await webdriver.click(provinceDropDownList.withText(provinceCode));
如果需要在多个地方延时等待任意时间,可以创建一种合适的轮询方法来检查任意目标元素,以便在这些地方通过快速复用方法来实现。
waitForSelector(selector, number = 1000)
{
await webdriver.expect(selector.exists).ok({ timeout: waitTime });
}
组织你的代码
以一种能够让别人快速定位被测项目与对应的代码位置的方式来组织你的代码。文件、变量、函数的命名应当清晰明了,使读者能够快速理解它们的目的(而不是用大量的注释去解释你糟糕的命名)。
恰当的命名非常重要,它可以帮助每个人理解你试图执行的操作,而无需深入了解任何业务。在为函数命名时,选择一个特定的动词和统一的命名规范来描述同一类动作。例如:用于获取对象值的方法,使用get
前缀;用于更新对象值的方法,使用set
前缀。
setNewUserName(oldUsername,newUsername) { }
changeUserLocation(oldUsername,newUsername) { }
如果代码中没有一致的命名模式,将会很难维护,并且维护者将无法一目了然地看到代码的修改内容。
setNewUserName(oldUsername,newUsername) { }
setUserLocation(oldUsername,newUsername) { }
对于如何更好的组织和构建自己的代码,可以参考这本书——《代码大全》。
优先在一种浏览器中实现自动化
从一开始就专注于一种浏览器,这将使你能够着重编写第一版的测试。在引入更多不同的浏览器以致复杂性提高前,先确保基础业务逻辑能够在一种浏览器上能够正常、可靠地运行。 对于能够在一个浏览器中正常运行的大部分功能而言,其在其它浏览器中也能顺利的运行。因此你只要首先保证自己编写的测试能够在一个浏览器上跑通,接着再去考虑其它浏览器上的兼容性问题。
如果你的应用程序需要进行浏览器兼容性测试,请尽可能选择执行那些可能在不同浏览器上出现不同运行结果的测试操作组合,并仅在所有浏览器上运行这些测试。这将有助于减少测试的运行时间,从而更快地获得结果。
总结
这些技巧有助于提高自动化回归测试中的代码的健壮性,并且帮助测试更加有效的部署到其它地方。采用这些技巧将有助于提高可靠性,以便增强团队对于自动化回归测试结果的信任。