让UI测试不再可怕😱
测试开发。
引擎盖下
让测试变得更好……对修复 bug 的人来说更是如此。
何时应该实现 UI 测试自动化?
优点和缺点?
蛋糕是真的吗?
鸣谢
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
问题不在于测试用例本身有问题,而在于我们用于 UI 测试的工具非常糟糕。
UI测试真让人头疼。真的。
如果您还不熟悉端到端测试的自动化,那么目前有一些知名的免费开源框架可供选择,按 GitHub 星标数排序如下:NightmareJS (16K)、Selenium (12K)、WebDriverIO (4K)、CodeceptJS (1K)。
测试通常看起来都差不多是这样——花点时间弄清楚 NightmareJS 中的这个“Hello World”示例的作用🤔:
const Nightmare = require('nightmare')
const nightmare = Nightmare({ show: true })
nightmare
.goto('https://duckduckgo.com')
.type('#search_form_input_homepage', 'github nightmare')
.click('#search_button_homepage')
.wait('#r1-0 a.result__a')
.evaluate(() => document.querySelector('#r1-0 a.result__a').href)
.end()
.then(console.log)
.catch(error => {
console.error('Search failed:', error)
})
你弄明白了吗?
这样做的方法是访问 DuckDuckGo,在搜索框中输入“github nightmare”,按下搜索按钮,等待第一个结果出现,然后打印第一个结果的链接地址。
拜托各位,我们不是都知道硬编码和使用魔法等待是绝对不行的吗?测试代码也是代码,而且这代码简直臭气熏天。这不仅让代码难以阅读,也让维护更加困难。万一产品改了设计,或者前端突然想做个大扫除怎么办?糟糕,测试又失败了。谁有时间去修复那一百零一个该死的 CSS 选择器啊!
而且,我们到底想测试什么?
是用户旅程,还是HTML代码?
这样编写测试怎么样?
I.goTo("https://duckduckgo.com")
I.fill("Search", "Github nightmare")
I.pressEnter()
I.see("Github - segmentio/nightmare")
I.click("Github - segmentio/nightmare")
简洁、易读、易于维护,
并且与前端技术无关。VueJS、ReactJS、Angular……这重要吗?
我和@picocreator从 jQuery 出现之前就开始开发 Web 应用了,我们俩都经历过无数次凌晨两点的噩梦:为了确保测试按时完成并发布,我们绞尽脑汁,结果却因为在生产环境中测试而惨遭失败💣💣💣😱😱😱。每年万圣节,我们都会把这些恐怖故事讲给年轻的开发人员听。好吧,我好像有点跑题了……
我们在软件架构方面有很多分歧,也经常争论可维护代码应该是什么样的,但我们一致认为问题不在于测试用例本身存在缺陷,而在于我们现有的 UI 测试工具非常糟糕。必须有人来修复它。而这正是我们过去两年一直致力于解决的问题:
小菜一碟。
但这个测试太简单了。你可能会想,嗯,这不错,但如果情况变得更复杂呢?比如有 50 个“添加到购物车”按钮,或者都是图标按钮?
咱们玩得开心点儿吧? 😎
哦,等等,在我们开始之前,先说明一下,这绝对不是一个由人工智能驱动的黑箱算法,但稍后会详细介绍。
测试开发。
让我们从基础开始,确保最关键的功能之一——搜索功能——能够正常运行。
I.goTo("https://dev.to/")
I.fill("Search", "dev.to")
I.pressEnter()
I.click("thepracticaldev")
I.see("The hardworking team behind dev.to ") // mmhm, very hardworking indeed.
将测试与 UI 实现解耦的好处在于,我们可以轻松地复用同一个测试来测试响应式设计。让我们看看搜索功能在桌面端和移动端是否都能正常工作。
现在,我们来试试点击 DEV.to 的 logo 返回首页。UI-licious 会扫描辅助功能属性和工具提示,title以及其他一些常用框架使用的类似属性。我们的首页 logo 里有我们可以利用的信息吗?
<a href="/" class="logo-link" id="logo-link" aria-label="DEV Home"><svg ... /></a>
瞧,这就是 DEV.to 的 logo 在后台的样子。太棒了!aria-label我们点击“开发者主页”。
I.click("DEV Home") // We love aria-labels
I.amAt("https://dev.to/")
好了:
好,咱们发挥创意,去开发者商店逛逛。我打算买一百个贴纸包和开发者手提袋。
I.click("DEV Shop")
I.amAt("https://shop.dev.to/")
let shopping_list = [
"Dev tote",
"Sticker Pack"
]
shopping_list.forEach((item) => {
I.click("The DEV shop")
I.click(item)
I.fill("Quantity", 100) // lets' get a hundred of each
I.click("Add to cart")
})
好了……快完成了。等等,我们再拿几个购物袋。嗯……购物车里有好几排商品,我们需要选择正确的数量框来更新。没问题,我只需要稍微具体一点,I.see在更新数量之前告诉 UI-licious 要输入什么。
I.amAt("/cart")
I.see("Dev tote")
I.fill("Quantity", 120) // UI-licious will pick the quantity box for "Dev Tote" to fill
I.pressEnter()
最后,我们再进行一些测试,以确保 UI-licious 本身能够正常工作。
是啊宝贝,小菜一碟。😎
引擎盖下
不,它并非由人工智能驱动。至少不是现代意义上的人工智能。
警告:前方高能,观点至上!测试应该是确定性的,也就是说,在相同的输入下,它应该始终产生相同的结果。随机且不可预测的行为在测试中并不理想,而修复人工智能驱动的测试引擎中的缺陷,实际上就是……向它输入更多“正确”的样本数据,以提高其准确性。
UI-licious 的工作原理是通过逆向工程来理解用户的意图(即你I.click("Sign in")HTML 代码中的含义)以及之前的步骤。它在可访问性强的网站上效果最佳。你的代码不必完美无缺才能进行测试,但使用语义化的 HTML 和 ARIA 属性肯定会有所帮助。
(顺便一提,这款界面精美的 IDE 完全是用 VueJS 构建的。\o/)
让测试变得更好……对修复 bug 的人来说更是如此。
我觉得收到错误报告最烦人的地方在于报告不完整,我需要追着报告者要重现错误的步骤。但说实话,我也遇到过一些敷衍了事的报告。所以我们努力让错误复现报告尽可能完整、实用(而且美观!)。👇
何时应该实现 UI 测试自动化?
一个好的指导原则是:当你第 n 次测试该用户角色的登录流程时。
还有👇
应该先自动化单元测试、集成测试还是端到端测试?这并不重要,重要的是从某个地方开始。我通常建议,对于任何需要复杂条件语句和数学运算的功能,都应该先进行单元测试;而对于关键用户流程,则应该先进行端到端测试,因为这些测试也有助于在下游发现错误。
优点和缺点?
优点:起价 0 美元。而且,运维人员少了一件需要操心的事。
缺点:目前还不是开源的。(……除非天上掉馅饼)
蛋糕是真的吗?
是的,我没撒谎,我们无论去哪儿都会带蛋糕。
万圣节快乐!
👻👻👻
鸣谢
我们有一个规模很小但非常敬业的高级和初级开发人员团队 -> @picocreator、@jmtiong、@sopnopriyo、Wesley Chang 和我。
封面照片由 NeONBRAND 拍摄,来自 Unsplash
文章来源:https://dev.to/uilicious/take-the-horror-out-of-ui-testing--1fi6

