selenium-webdriver - 是否应该在页面对象之外提供元素?

标签 selenium-webdriver protractor webdriver automated-tests pageobjects

这是一个我无法找到确切来源的问题,我希望根据用户以前的经验得到一些答案,主要是解释为什么要采用某种方法 没有 锻炼。

我正在通过 Protractor 使用 webdriver 进行自动化,并且正在就是否应该在页面对象本身之外提供页面元素进行辩论。经过研究,人们似乎采取了几种不同的方法,我无法完全掌握每种方法的长期影响。

我已经看到了页面对象模型的以下不同实现:

定位器在页面对象中声明并导出

这是我最不喜欢的方法,因为这意味着元素实际上在测试中被识别。这似乎是一个不好的标准,因为它可能鼓励自动化程序直接在应用程序中使用新的定位器,而不是来自页面对象。
此外,任何需要任何动态信息的都不能在 PO 初始化时直接设置,需要进一步编辑。

pageobject.js

export default class HomePage {
    constructor() {
        this.passwordField = '#password';
        this.usernameField = '#user';
    }
}

test.js
const homePage = new HomePage();
$(homePage.usernameField ).sendKeys('admin');
$(homePage.passwordField ).sendKeys('password');

在页面对象中声明并导出的元素,定位器不是

pageobject.js
export default class HomePage {
    constructor() {
        this.passwordField = $('#password');
        this.usernameField = $('#user');
    }
}

test.js
const homePage = new HomePage();
homePage.usernameField.sendKeys('admin);
homePage.passwordField.sendKeys('password);

在页面对象中声明且仅在页面对象中直接使用的元素,仅导出方法

这是我过去使用的方法,我们最终得到了很多很多功能。例如,我们有 setUsename(), getCurrentUsername(), getUsernameAttibute(), verifyUsernameExists()password 相同元素和许多其他元素。我们的页面对象变得很大,所以我觉得这不再是最好的方法了。
然而,优点之一是我们的测试看起来非常干净并且非常易读。

pageobject.js
export default class HomePage {
    constructor() {
        var passwordField= $('#password');
        var usernameField = $('#user');
    }

    setUserName(name){
       username.sendKeys(name);
    };

    setPassword(password){
       passwordField.sendKeys(password);
    };
}

test.js
const homePage = new HomePage();
homePage.setUsername('admin');
homePage.setPassword('123');

我很想得到一些反馈,所以希望你能花时间阅读。

最佳答案

我更喜欢并相信最后一种方法是最好的。

撇开我们谈论自动化这一事实不谈,任何好的/伟大的软件都具有以下特征。

  • 组成单个模块/件/组件
  • 每个单独的模块/部件/组件是有凝聚力的就数据/信息(选择器,自动化情况下的 webdriver API 调用)而言,特定于其 API/与数据交互的方法。

  • 最后一种方法提供了您指出的测试清洁度的额外好处。

    然而,大多数时候,无论出于何种原因,我们都倾向于忽略模块化,使现有的 PO 变得臃肿。这是我见过的并且是其中的一部分。因此,在某种程度上,PO 变得臃肿不是因为方法,而是自动化人员/测试人员/开发人员有意识地保持 PO 模块化、组合和更简单的方式。无论是关于 PO 还是关于应用程序功能代码都是如此

    划船订单:

    具体到PO臃肿的问题,看看能不能把PO的共同元素分离出来。例如。页眉,页脚,左导航,右导航等在页面中很常见。它们可以分开,采购订单可以是组成这些单独的部分/部分。

    即使在主要内容中,如果其合乎逻辑并且可以跨页面重用,则将公共(public)内容(如果它跨两个或多个页面,如果不是全部)分离到它们自己的组件 API 中。

    自动化规范对 ex 执行广泛的回归是正常的。一个元素是一个密码字段,文本框的长度是这样等等。在这种情况下,为每个规范用例(或期望)添加方法是没有意义的。好消息是,这里的共性也占据了中心位置。基本上,提供跨规范使用的 API,而不是在一个规范中使用的 API。

    举个例子。密码字段应该被屏蔽。您不太可能想在多个规范文件中进行测试。在这里,我们可以在 LoginPO 中为它添加一个方法喜欢 isPasswordMasked() 我们可以让 LoginPO 访问密码字段并且规范对密码类型字段进行实际检查。通过这样做,我们仍然让 LoginPO控制与其他 API 相关的密码字段信息(login()logout() 等),即只有 PO 知道如何以及在何处获取该密码元素。具有将规范测试推送到规范文件的额外优势。

    expect 的采购订单/assert

    在任何时候,它的不是一个好主意使任何测试(或 expect)成为 PO API 的一部分。原因:
  • PO 及其 API 可跨套件重用,任何人都应该易于查看和理解。他们的主要职责是提供通用 API。
  • 它们应该尽可能瘦(以防止膨胀)
  • 更重要的是,浏览器自动化本身就比较慢。如果我们将测试逻辑添加到 PO 及其 API 方法中,我们只会让它变慢。

  • FWIW,我没有遇到任何网页 授权 臃肿的 API。

    公开采购订单中的元素:

    这取决于我相信的用例。可能是仅在一个规范中使用的元素,也可能是要公开的基本情况。也就是说,一般来说,这个想法是规范应该对测试人员/开发人员以及稍后查看它们的人来说是可读的。无论是使用有意义的元素变量名还是方法名,充其量只是一种偏好。另一方面,如果一个元素需要进行一些交互(例如悬停打开菜单链接),那么它绝对是仅通过 API 公开的候选对象。

    希望增加一些澄清!

    关于selenium-webdriver - 是否应该在页面对象之外提供元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57251094/

    相关文章:

    python - 无法创建着色器缓存条目 - 在通过其 Css 选择器定位元素时出错

    angularjs - 有 Angular 和无 Angular 的 Protractor

    javascript - 在级联promise中修改it block 中本地定义的变量时如何修改

    protractor - 将目标移出边界 : Failed to read the 'localStorage' property from 'Window' : Access is denied for this document. build

    selenium - 由于向后兼容性已被删除,如何使用 ChromeDriver 73 和 Chrome 版本 74 执行现有的 selenium 脚本?

    java - Angular 元素定位

    c# - Selenium 测试失败时捕获错误消息

    java - 一个 Selenium 测试自动化项目在少数环境中运行

    javascript - 无法从下拉列表中选择值

    python - selenium.common.exceptions.WebDriverException : Message: invalid session id using Selenium with ChromeDriver and Chrome through Python