Protractor - 对象

本章详细讨论了 Protractor 中的对象。

什么是页面对象?

页面对象是一种设计模式,它已成为编写 e2e 测试的流行模式,旨在增强测试维护并减少代码重复。它可以定义为一个面向对象的类,用作 AUT(被测应用程序)页面的接口。但是,在深入研究页面对象之前,我们必须了解自动化 UI 测试的挑战及其处理方法。

自动化 UI 测试的挑战

以下是自动化 UI 测试的一些常见挑战 −

UI 更改

进行 UI 测试时最常见的问题是 UI 中发生更改。例如,大多数情况下,按钮或文本框等通常会发生变化,从而给 UI 测试带来问题。

缺乏 DSL(领域特定语言)支持

UI 测试的另一个问题是缺乏 DSL 支持。由于这个问题,很难理解正在测试的内容。

大量重复/代码重复

UI 测试中的下一个常见问题是存在大量重复或代码重复。可以借助以下代码行 − 来理解它

element(by.model('event.name')).sendKeys('An Event');
element(by.model('event.name')).sendKeys('Module 3');
element(by.model('event.name'));

维护困难

由于上述挑战,维护变得令人头痛。这是因为我们必须找到所有实例,用新名称、选择器和其他代码替换。我们还需要花费大量时间来使测试与重构保持一致。

破坏的测试

UI 测试中的另一个挑战是测试中出现大量失败。

应对挑战的方法

我们已经看到了 UI 测试的一些常见挑战。处理此类挑战的一些方法如下 −

手动更新引用

处理上述挑战的第一个选项是手动更新引用。此选项的问题在于我们必须在代码和测试中进行手动更改。如果您有一两个测试文件,则可以这样做,但如果项目中有数百个测试文件怎么办?

使用页面对象

处理上述挑战的另一种选择是使用页面对象。页面对象基本上是一个封装 Angular 模板属性的纯 JavaScript。例如,以下规范文件是在没有页面对象和有页面对象的情况下编写的,以了解差异 −

没有页面对象

describe('angularjs homepage', function() {
   it('should greet the named user', function() {
      browser.get('http://www.angularjs.org');
      element(by.model('yourName')).sendKeys('Julie');
      var greeting = element(by.binding('yourName'));
      expect(greeting.getText()).toEqual('Hello Julie!');
   });
});

使用页面对象

要使用页面对象编写代码,我们需要做的第一件事就是创建一个页面对象。因此,上述示例的页面对象可能如下所示−

var AngularHomepage = function() {
   var nameInput = element(by.model('yourName'));
   var greeting = element(by.binding('yourName'));

   this.get = function() {
      browser.get('http://www.angularjs.org');
   };

   this.setName = function(name) {
      nameInput.sendKeys(name);
   };
   
   this.getGreetingText = function() {
      return greeting.getText();
   };
};
module.exports = new AngularHomepage();

使用页面对象组织测试

我们已经在上面的示例中看到了使用页面对象来处理 UI 测试的挑战。接下来,我们将讨论如何使用它们来组织测试。为此,我们需要修改测试脚本而不修改测试脚本的功能。

示例

为了理解这个概念,我们将使用上面的带有页面对象的配置文件。我们需要按如下方式修改测试脚本 −

var angularHomepage = require('./AngularHomepage');
describe('angularjs homepage', function() {
   it('should greet the named user', function() {
      angularHomepage.get();

      angularHomepage.setName('Julie');
   
      expect(angularHomepage.getGreetingText()).toEqual
      ('Hello Julie!');
   });
});

此处请注意,页面对象的路径将与您的规范相关。

同样,我们还可以将测试套件分成多个测试套件。然后可以按如下方式更改配置文件

exports.config = {
    // 正在运行的 selenium 服务器的地址。
    seleniumAddress: 'http://localhost:4444/wd/hub',
    
    // 要传递给 webdriver 实例的功能。
    capabilities: {
    'browserName': 'chrome'
    },
    // Spec 模式与 spec 文件的位置相关。它们可能
    // 包括 glob 模式。
    suites: {
    homepage: 'tests/e2e/homepage/**/*Spec.js',
    search: ['tests/e2e/contact_search/**/*Spec.js',
    'tests/e2e/venue_search/**/*Spec.js']
    },
    
    // 要传递给 Jasmine-node 的选项。
    jasmineNodeOpts: {
    showColors: true, // 在命令行报告中使用颜色。
    }
};

现在,我们可以轻松地在运行一个或另一个测试套件之间切换。以下命令将仅运行测试的主页部分 −

protractor protractor.conf.js --suite homepage

同样,我们可以使用以下命令运行特定的测试套件 −

protractor protractor.conf.js --suite homepage,search