优化Web应用程序以进行测试自动化:开发人员的最佳实践

2024-12-13   出处: medium  作/译者:Sritaj Patel/ 溜的一比

引言

随着Web应用程序日益复杂并成为用户体验的核心,有效的测试自动化需求也从未如此重要。然而,许多开发人员在确保其应用程序易于测试方面遇到了重大挑战,往往是由于定位器定义不清晰以及开发阶段对自动化考虑不足。

在本文中,我们将探讨一些帮助开发人员创建稳定且有意义的定位器的策略,例如利用唯一标识符和ARIA属性,以及如何在测试自动化中利用它们。

定位器

在Web开发和测试自动化的背景下,定位器是用于查找和与网页元素交互的标识符。在使用诸如Playwright、Selenium或Cypress等工具编写自动化测试时,定位器对于识别特定网页元素(如按钮、文本框、链接)至关重要,以执行诸如点击、输入文本或验证其属性等操作。

为什么定位器很重要?

定位器之所以重要,是因为它们允许测试脚本:

  • 查找页面上的特定元素。
  • 与这些元素交互(例如,点击按钮,填写表单)。
  • 验证元素的行为和状态(例如,检查按钮是否启用或禁用)。
  • 确保测试可靠和稳健,即使网页的结构发生变化。

定位器的类型

定位网页元素有多种方法:

  • id:使用唯一的id属性定位元素。 示例:

html <button id="submit-button">Submit</button>

Playwright/Selenium中的定位器:

javascript page.locator('#submit-button'); * class:基于CSS类名定位元素。虽然类名通常不是唯一的,但可以与其他定位器结合使用。 示例:

```html

```

定位器:

javascript page.locator('.login-form'); * name:使用name属性定位表单元素,通常在一个表单中是唯一的。 示例:

html <input type="text" name="username" />

定位器:

javascript page.locator('[name="username"]'); * CSS选择器:使用CSS语法定位基于样式、类、属性或结构的元素。 示例:

```html

Submit

```

定位器:

javascript page.locator('.container .submit-btn'); * XPath:一种基于路径的语言,通过导航HTML文档结构来定位元素。 示例:

```html

Submit

```

定位器:

javascript page.locator('//*[@id="submit"]'); * 文本内容:根据可见文本定位元素。 示例:

html <button>Submit</button>

定位器:

javascript page.locator('text=Submit'); * aria-label和aria-labelledby:基于无障碍属性(如aria-label或aria-labelledby)定位元素,常用于屏幕阅读器和辅助技术。 示例:

html <button aria-label="submit form">✔</button>

定位器:

javascript page.locator('[aria-label="submit form"]'); * data- 属性*:可以为测试目的将自定义的data-*属性添加到HTML元素中。 示例:

html <button data-testid="submit-btn">Submit</button>

定位器:

javascript page.locator('[data-testid="submit-btn"]');

好的定位器的特征

  • 唯一性:一个好的定位器应该只指向页面上的一个元素,避免歧义。
  • 稳定性:定位器应该保持一致,即使页面的结构或样式发生变化。
  • 可读性:易于开发人员和测试人员理解和维护。

对于测试自动化而言,唯一定位器的重要性

  • 提高测试准确性和稳定性
    唯一定位器可以确保自动化工具与网页上的正确元素进行交互。如果定位器不是唯一的,测试可能会针对多个元素或错误的元素,从而导致假阳性(测试通过但实际上应该失败)或假阴性(测试失败但实际上应该通过)。这会导致不稳定的测试,降低对测试套件的信心。
    示例
    想象一下页面上有两个具有相同类的按钮,但用途不同。如果没有唯一标识符(如id或data-*),你的测试可能会错误地点击错误的按钮。
  • 防止测试因DOM变化而中断
    唯一定位器通常对页面结构(DOM)的变化不太敏感。例如,与类名或复杂的XPath表达式相比,id或data-*属性在UI更新过程中更不容易更改。
    示例
    一个使用XPath(如//div/button[2]​)的测试可能会在添加新按钮后中断,而使用id="submit-btn"​则确保无论其他元素如何变化,始终定位正确的按钮。
  • 减少测试维护
    当使用唯一定位器时,测试更加稳定,不易失败,从而减少了对测试脚本的持续更新需求。这对于UI频繁更改的大型应用程序尤其重要,如果定位器选择不当,会导致高昂的维护负担。
    示例
    使用诸如id="user-name-input"​的唯一标识符可以确保测试始终能找到正确的输入框,即使表单结构或样式发生了变化。
  • 提高可读性和调试性
    清晰且唯一的定位器可以提高测试脚本的可读性,使开发人员和测试人员更容易理解目标元素。在调试过程中,唯一定位器使得跟踪与元素交互相关的问题变得简单,因为不用担心测试试图与哪个元素交互。
    示例
    一个定位器如page.locator('#submit-button')​比page.locator('div>button:nth-child(3)')​更加直观且易于调试。
  • 支持稳健的测试框架
    诸如Playwright、Selenium和Cypress之类的测试框架非常依赖定位器来与元素交互。使用唯一定位器可以增强这些框架执行端到端测试的能力,确保用户流程(如登录、填写表单、点击按钮)得以正确验证,这对于CI/CD管道和回归测试至关重要。
  • 提高测试执行性能
    唯一定位器通常更容易定位,这可以减少自动化工具查找元素所需的时间,从而加快测试执行速度。非唯一或复杂的定位器,如依赖于深度DOM遍历的定位器,可能会因自动化工具需要在更多元素中查找匹配项而减慢测试速度。
    示例
    id="search-box"​比较长的XPath查询如//div[@class="form"]/input[1]​更快定位。

开发人员如何在开发阶段确保定位器的正确使用

为了使测试自动化更顺畅和可靠,开发人员在开发阶段应积极遵循最佳实践来分配定位器。确保应用程序的元素可以被Playwright、Selenium或Cypress等自动化工具轻松识别需要开发人员与测试人员之间的合作,以及采用正确的技术。

早期采用定位器策略

  • 原因:从一开始就明确分配定位器的计划(例如,使用唯一的id、data-*或aria-*属性)应作为开发指南的一部分。
  • 可操作步骤:在设计和实施阶段,与QA和自动化团队达成定位器策略的一致意见。为id、class和data-*属性制定命名约定,以确保代码库中的一致性。
  • 示例:确保UI中的每个重要元素(如表单字段、按钮或链接)都有一个唯一标识符(如id="username-input"​,data-testid="submit-btn"​)。

使用有意义且描述性的定位器

  • 原因:描述性定位器使得开发人员和测试人员更容易理解元素的用途,并在DOM中找到它。
  • 可操作步骤:为id、data-*或aria-*属性使用自解释名称,这些名称能清楚地反映元素的用途。避免使用通用名称或自动生成的ID。
  • 示例
    代替:

html <input id="input-12345" />

使用:

html <input id="email-input" />

为测试添加自定义data-*属性

  • 原因:使用data-*属性可以灵活地为测试目的定义自定义定位器,而不影响应用程序的视觉设计或功能。
  • 可操作步骤:开发人员应在开发过程中为重要元素添加诸如data-testid​、data-qa​或data-test​之类的data-*属性,以确保测试人员拥有稳定且一致的定位器。
  • 示例

html <button data-testid="register-btn">Register</button>

自动化定位器:

javascript page.locator('[data-testid="register-btn"]');

通过ARIA属性确保可访问性

  • 原因:ARIA属性(如aria-label​或aria-labelledby​)提高了残障用户的可访问性,并为测试自动化提供了一种可靠的方法来定位元素。
  • 可操作步骤:在必要时实施ARIA属性,尤其是对于可能缺少可见文本的图标或按钮元素。这使应用程序更加易于访问,并确保自动化工具可以轻松识别这些元素。
  • 示例

html <button aria-label="Search">🔍</button>

自动化定位器:

javascript page.locator('[aria-label="Search"]');

保持定位器稳定,避免动态生成的ID

  • 原因:动态生成的ID可能经常变化,导致测试脚本中断,因为自动化工具可能难以始终如一地识别相同的元素。
  • 可操作步骤:避免为定位器使用动态生成的值(如随机或基于会话的ID)。相反,使用在不同会话中不会更改的稳定ID或data-*属性。
  • 示例: 避免:

```html

...

```

使用:

```html

...

```

使用类进行分组,而不是识别

  • 原因:类通常用于样式目的,多个元素可能共享相同的类,这使它们作为自动化中的唯一标识符不可靠。
  • 可操作步骤:使用类来样式或分组元素,但避免在测试中将其用作唯一定位器。必要时,将类与其他选择器或属性结合以增加特异性。
  • 示例: 代替:

html <button class="btn submit">Submit</button>

使用:

html <button class="btn" id="submit-button">Submit</button>

确保定位器在变更中保持一致

  • 原因:随着UI的演变,定位器频繁更改会中断自动化测试。维护更新中的一致性定位器可减少测试维护的工作量。
  • 可操作步骤:在修改UI时,开发人员应尽量保留现有的id、data-*和ARIA属性,除非绝对必要更改它们。这有助于在重构时减少对测试自动化团队的负担。
  • 示例:如果更新表单的CSS或布局,请保留定位器:

html <input id="user-email" />

与QA团队合作

  • 原因:开发人员与QA团队之间的合作可确保定位器满足测试自动化工具的需求,减少不稳定的测试出现的可能性。
  • 可操作步骤:在功能开发过程中,与QA或测试自动化团队密切合作,识别需要稳定定位器的关键元素。就哪些元素需要data-*​属性或ARIA标签达成一致,以增强可测试性。
  • 示例:测试人员可能会请求:

html <button data-qa="login-btn">Login</button>

在开发过程中编写自动化测试

  • 原因:在开发过程中(或之后不久)编写自动化测试可确保立即验证定位器,并确保它们对于自动化目的有效。
  • 可操作步骤:采用如测试驱动开发(TDD)或行为驱动开发(BDD)等实践,确保在功能开发的同时测试和验证定位器。这可以及早发现定位器问题。
  • 示例:编写测试以确保登录按钮容易识别:

javascript await page.locator('[data-qa="login-btn"]').click();

利用工具识别定位器问题

  • 原因:有时,似乎稳定的定位器在不同环境或浏览器中仍然可能出现问题。
  • 可操作步骤:使用浏览器开发工具或自动化测试框架(如Playwright Inspector、Selenium IDE或Cypress Test Runner)在开发过程中验证和优化定位器。这有助于及早发现潜在问题。
  • 示例:使用Playwright Inspector确保你选择的定位器可靠:

shell npx playwright test --ui

什么是ARIA属性?

Web可访问性对于确保所有用户(包括有残障的用户)能够无障碍地与您的应用程序进行交互至关重要。实现可访问性的关键工具之一是ARIA(Accessible Rich Internet Applications)属性。ARIA属性使您的应用程序对依赖辅助技术(如屏幕阅读器)的用户更友好。除了可访问性,ARIA属性在使Web元素更容易在测试自动化中识别和交互方面也起着重要作用。

为什么ARIA属性对可访问性有好处?

  • 让内容对所有人可访问
    ARIA属性为网页元素提供了额外的上下文,这些元素的用途可能不容易从HTML结构中推断出来。它们帮助辅助技术(如屏幕阅读器)理解交互元素的用途,使残障用户能够更好地导航和与您的应用程序进行交互。
    示例

  • aria-label​可以为元素提供一个可访问的名称,即使它没有可见的文本。

  • aria-labelledby​可以引用另一个元素,该元素为当前元素提供上下文。
  • 增强语义含义
    在现代Web应用程序中,诸如按钮、滑块和菜单等动态交互元素通常依赖于复杂的JavaScript,这些JavaScript并非固有地具有可访问性。ARIA属性为开发人员提供了工具,能够明确定义这些元素的角色、状态和属性,使得应用程序对屏幕阅读器和其他辅助技术更加易于理解和使用。
    示例

html <button aria-label="Search" type="button">🔍</button>

该按钮虽然通过图标呈现,但对于屏幕阅读器用户来说,现在被明确标记为“Search”。 * 符合可访问性标准
集成ARIA属性有助于确保您的应用程序符合Web内容无障碍指南(WCAG)等可访问性标准。这不仅改善了残障用户的体验,还帮助避免与可访问性要求相关的潜在法律问题。

ARIA属性如何帮助测试自动化?

  • 一致且稳定的定位器
    测试自动化工具(如Playwright、Selenium和Cypress)依赖定位器来识别和与DOM中的元素交互。ARIA属性(如aria-label​和aria-labelledby​)提供了一种稳定且描述性的方法来定位元素。这些属性通常在UI更改时保持不变,使得自动化测试更加稳健,减少了更新期间中断的可能性。
    示例
    与依赖于可能变化的类名或动态ID相比,您可以使用aria-label​来创建稳定的定位器:

javascript page.locator('[aria-label="Search"]');

这种方法确保您的测试对布局或视觉更改具有抗性。 * 提高测试的可读性
ARIA属性本身具有描述性,这使得测试脚本更加可读和易于理解。当自动化脚本使用aria-label​或aria-labelledby​时,清楚地显示测试目标,而不是使用可能无法传达元素用途的任意类或id属性。
示例

javascript const searchButton = page.locator('[aria-label="Search"]');

测试清楚显示它在与搜索按钮交互,使脚本对开发人员和测试人员更直观。 * 支持可访问性测试的自动化
集成ARIA属性可以使自动化工具验证应用程序的可访问性。许多现代测试自动化框架(如Cypress或Playwright)提供插件或集成,可以检查元素是否具有适当的ARIA属性以确保可访问性。
示例
Playwright具有访问树检查功能:

javascript await page.accessibility.snapshot();

这有助于确保所有交互元素都被正确标记并暴露给辅助技术。

使用ARIA属性进行可访问性和测试自动化的最佳实践

  • 为非文本元素添加ARIA属性
    没有可见文本的非文本元素(如图标、按钮和输入字段)应具有诸如aria-label​之类的ARIA属性,以描述它们的功能。
    示例

html <button aria-label="Add to Cart">🛒</button>

这个按钮只通过图标呈现,但对于屏幕阅读器和自动化脚本来说是可识别的。 * 使用aria-labelledby为描述性标签
当需要更具描述性的标签时,使用aria-labelledby​引用现有的标签或文本元素。这对于具有可见标签的表单元素特别有用。
示例

html <label id="name-label">Full Name</label> <input type="text" aria-labelledby="name-label" />

这确保屏幕阅读器知道输入字段对应“Full Name”。 * 避免过度使用ARIA属性
尽管ARIA属性可以增强可访问性,但应谨慎和适当使用。ARIA属性的滥用可能导致错误信息传递给辅助技术,从而导致混淆。 * 将ARIA与其他稳定属性结合使用
对于经常交互的元素,将ARIA属性与其他属性(如id或data-*)结合使用,以提高定位器的稳定性。
示例

html <button id="confirm-btn" aria-label="Confirm Purchase">Confirm</button>

在自动化框架中选择测试定位器的“可以”和“不可以”

在测试自动化中选择正确的定位器对于创建稳健、可维护和可靠的测试至关重要。合适的定位器策略可以显著减少测试的不稳定性和维护开销。以下是选择自动化框架中的测试定位器时的一些“可以”和“不可以”实践:

可以做的:选择定位器的最佳实践

  • 使用唯一标识符(ID属性)
    始终优先选择唯一且稳定的id属性来定位元素。ID在页面中是唯一的,使其成为强大且稳定的定位器选择。
    示例

javascript page.locator('#submit-button'); * 使用aria-label或aria-labelledby进行描述性标签
使用ARIA属性(如aria-label​和aria-labelledby​)定位具有有意义描述的元素。对于按钮、图标和其他非文本元素,这种方式特别有用,提供了稳定且可访问的定位器。
示例

javascript page.locator('[aria-label="Search"]'); * *使用data-属性作为自定义定位器
实现特定用于测试目的的data-*属性。这些属性不对用户公开,可以专门为测试自动化量身定制。它们不受视觉或布局更改的影响。
示例

javascript page.locator('[data-test="login-button"]'); * 为复杂元素层次结构使用CSS选择器
如果没有唯一的标识符,可使用CSS选择器来定位基于其结构的元素。结合类、标签和层次结构以唯一地识别元素。
示例

javascript page.locator('div.header > nav > a[href="/login"]'); * 必要时使用XPath
虽然通常更推荐使用CSS选择器,但在处理复杂的DOM结构或难以用CSS选择器选择的元素时,XPath可以发挥作用。
示例

javascript page.locator('//div[@class="header"]//a[text()="Login"]'); * 使用文本定位静态文本元素
对于包含静态文本的元素(如按钮或链接),使用匹配文本内容的定位器。
示例

javascript page.locator('text="Sign In"');

不可以做的:选择定位器时需要避免的做法

  • 避免使用动态ID
    不要依赖于动态生成或在不同会话或构建之间经常变化的ID。动态ID可能会导致测试中断,因为它们可能不一致。
    示例

javascript // 如果ID是动态的,请避免使用它 page.locator('#user_12345'); * 避免使用自动生成或通用类名
不要使用通用类名或前端框架自动生成的类(如Bootstrap、Material UI)。这些类名经常会随着更新而变化,或者无法提供唯一的标识。
示例

javascript page.locator('.btn'); * 避免单纯依赖位置进行元素选择
不要依赖于仅通过元素在DOM层次中的位置来选择它们(例如,第一个子元素,第n个元素)。这会使测试变得脆弱,在页面结构变化时容易中断。
示例

javascript page.locator('div > button:nth-child(3)'); * 避免使用过于复杂或冗长的XPath表达式
不要使用嵌套太深或过于复杂的XPath表达式。这些定位器难以维护和理解,且DOM的细微变化可能会使它们中断。
示例

javascript // 避免使用过于复杂的XPath page.locator('//div[2]/section[1]/div[4]/table/tbody/tr[1]/td[2]/button'); * 避免依赖元素的视觉外观(CSS样式)
不要依赖样式(如颜色、字体大小或显示样式)来定位元素。样式可以在不影响功能的情况下频繁更改,导致测试不必要地失败。
示例

javascript page.locator('button[style="color: red"]');

结论

在当今快节奏的开发环境中,优化Web应用程序以进行测试自动化对于确保质量和高效交付至关重要。通过采用最佳实践(如使用唯一标识符、ARIA属性和data-*属性),开发人员可以创建增强测试自动化和可访问性的稳定定位器。这种双重关注不仅简化了测试过程,还对更具可维护性的代码库做出了贡献。避免使用脆弱的定位器(如动态ID和过于复杂的XPath表达式),可以确保测试在应用程序更改过程中保持可靠性。最终,将开发实践与测试自动化的需求相结合,可以促进协作,减少技术债务,并支持高质量产品的成功交付。


声明:本文为本站编辑转载,文章版权归原作者所有。文章内容为作者个人观点,本站只提供转载参考(依行业惯例严格标明出处和作译者),目的在于传递更多专业信息,普惠测试相关从业者,开源分享,推动行业交流和进步。 如涉及作品内容、版权和其它问题,请原作者及时与本站联系(QQ:1017718740),我们将第一时间进行处理。本站拥有对此声明的最终解释权!欢迎大家通过新浪微博(@测试窝)或微信公众号(测试窝)关注我们,与我们的编辑和其他窝友交流。
21° /210 人阅读/0 条评论 发表评论

登录 后发表评论
最新文章