Protractor - Protractor 风格指南
本章,我们将详细学习 Protractor 的风格指南。
简介
该风格指南由两位软件工程师创建:ING 的前端工程师 **Carmen Popoviciu** 和 Google 的软件工程师 **Andres Dominguez**。因此,此风格指南也称为 Carmen Popoviciu 和 Google 的 Protractor 风格指南。
此风格指南可分为以下五个要点:
- 通用规则
- 项目结构
- 定位策略
- 页面对象
- 测试套件
通用规则
以下是使用 Protractor 进行测试时必须注意的一些通用规则:
不要对已经进行单元测试的内容进行端到端测试
这是 Carmen 和 Andres 给出的第一个通用规则。他们建议我们不要对已经进行单元测试的代码执行 e2e 测试。其主要原因是单元测试比 e2e 测试快得多。另一个原因是,为了节省时间,我们必须避免重复测试(不要同时进行单元测试和 e2e 测试)。
只使用一个配置文件
另一个重要的建议是,我们必须只使用一个配置文件。不要为每个测试环境创建配置文件。您可以使用 **grunt-protractor-coverage** 来设置不同的环境。
避免在测试中使用逻辑
我们必须避免在测试用例中使用 IF 语句或 FOR 循环,因为如果这样做,测试可能会在没有进行任何测试的情况下通过,或者运行速度非常慢。
使测试在文件级别独立
启用共享时,Protractor 可以并行运行测试。然后,这些文件将在不同的浏览器中按可用情况执行。Carmen 和 Andres 建议至少在文件级别使测试独立,因为 Protractor 运行它们的顺序是不确定的,而且单独运行测试非常容易。
项目结构
关于 Protractor 风格指南的另一个重要要点是项目的结构。以下是关于项目结构的建议:
以合理的结构分组 e2e 测试
Carmen 和 Andres 建议我们必须以对项目结构有意义的结构来分组我们的 e2e 测试。此建议背后的原因是查找文件会变得容易,并且文件夹结构更易于阅读。此步骤还将 e2e 测试与单元测试分开。他们建议应避免以下类型的结构:
|-- project-folder |-- app |-- css |-- img |-- partials home.html profile.html contacts.html |-- js |-- controllers |-- directives |-- services app.js ... index.html |-- test |-- unit |-- e2e home-page.js home-spec.js profile-page.js profile-spec.js contacts-page.js contacts-spec.js
另一方面,他们推荐以下类型的结构:
|-- project-folder |-- app |-- css |-- img |-- partials home.html profile.html contacts.html |-- js |-- controllers |-- directives |-- services app.js ... index.html |-- test |-- unit |-- e2e |-- page-objects home-page.js profile-page.js contacts-page.js home-spec.js profile-spec.js contacts-spec.js
定位策略
以下是使用 Protractor 进行测试时必须注意的一些定位策略:
永远不要使用 XPATH
这是 Protractor 风格指南中推荐的第一个定位策略。其背后的原因是 XPath 需要大量的维护,因为标记很容易发生变化。此外,XPath 表达式速度最慢,并且很难调试。
始终优先使用 Protractor 特定的定位器,例如 by.model 和 by.binding
Protractor 特定的定位器(例如 by.model 和 by.binding)简短、具体且易于阅读。借助它们,编写定位器也变得非常容易。
示例
视图
<ul class = "red"> <li>{{color.name}}</li> <li>{{color.shade}}</li> <li>{{color.code}}</li> </ul> <div class = "details"> <div class = "personal"> <input ng-model = "person.name"> </div> </div>
对于以上代码,建议避免以下内容:
var nameElement = element.all(by.css('.red li')).get(0); var personName = element(by.css('.details .personal input'));
另一方面,建议使用以下内容:
var nameElement = element.all(by.css('.red li')).get(0); var personName = element(by.css('.details .personal input'));
var nameElement = element(by.binding('color.name')); var personName = element(by.model('person.name'));
当没有可用的 Protractor 定位器时,建议优先使用 by.id 和 by.css。
始终避免对频繁更改的文本使用文本定位器
我们必须避免使用基于文本的定位器,例如 by.linkText、by.buttonText 和 by.cssContainingText,因为按钮、链接和标签的文本会随着时间的推移而频繁更改。
页面对象
如前所述,页面对象封装了关于应用程序页面上元素的信息,因此帮助我们编写更简洁的测试用例。页面对象的一个非常有用的优点是它们可以在多个测试中重复使用,如果我们的应用程序模板发生了更改,我们只需要更新页面对象即可。以下是使用 Protractor 进行测试时必须注意的一些页面对象建议:
要与被测页面交互,请使用页面对象
建议使用页面对象与被测页面交互,因为它们可以封装关于被测页面上元素的信息,并且也可以重复使用。
始终为每个文件声明一个页面对象
我们应该在它自己的文件中定义每个页面对象,因为它可以保持代码简洁,并且查找内容变得容易。
在页面对象文件的末尾始终使用单个 module.exports
建议每个页面对象都应该声明一个类,以便我们只需要导出一个类。例如,应避免以下对象文件的用法:
var UserProfilePage = function() {}; var UserSettingsPage = function() {}; module.exports = UserPropertiesPage; module.exports = UserSettingsPage;
但另一方面,建议使用以下内容:
/** @constructor */ var UserPropertiesPage = function() {}; module.exports = UserPropertiesPage;
在顶部声明所有必需的模块
我们应该在页面对象的顶部声明所有必需的模块,因为它使模块依赖关系清晰易于查找。
在测试套件的开头实例化所有页面对象
建议在测试套件的开头实例化所有页面对象,因为这将使依赖关系与测试代码分开,并使依赖关系可用于套件的所有规范。
不要在页面对象中使用 expect()
我们不应该在页面对象中使用 expect(),即我们不应该在页面对象中进行任何断言,因为所有断言都必须在测试用例中完成。
另一个原因是,测试的阅读者应该能够仅通过阅读测试用例来理解应用程序的行为。