刚开始使用Protractor进行E2E测试,我在测试用例结构方面遇到了一些麻烦。
不确定我是否可以将测试划分为单独的规范,然后从另一个规范中调用它们,或者我如何制作好的辅助函数来处理它。
我正在通过转发器找到元素,然后我想对转发器中每个元素的每个操作进行测试。有点像这样:
describe('tasty', function () {
'use strict';
var ptor;
beforeEach(function () {
ptor = protractor.getInstance();
ptor.get('http://localhost:8000/');
});
it('Should sample three tasty fruits of every kind on my shopping list.', function () {
ptor.findElement(protractor.By.className('fruitstore')).click();
var fruitshelves = ptor.findElements(protractor.By.repeater('fruit in fruits').column('header'));
fruitshelves.then(function(arr) {
for (var i=0;i<arr.length; i++) {
// Pick up three fruits of this kind from the shelf and put in shopping cart
// Should be listed on my shopping list
// Open the wallet
// Should have money
// Pay for the fruits and put it in your shopping bag
// Should be able to complete the transaction
// For each one of the fruits in your shopping bag
// Take a bite
// Should be tasty
}
});
});
});
答案 0 :(得分:11)
我来到这个问题寻找一种在Protractor中的spec文件之间共享辅助函数的方法。如果其他人正在寻找相同的东西,那么因为Protractor刚刚在Node中运行,所以你需要做的只是var helpers = require('./your-helper-file')
。
答案 1 :(得分:7)
如果您需要共享设置以及函数之前/之后以及辅助方法,一种解决方案是要求您的规范帮助程序进行测试,而不是要求测试中的规范帮助程序。
<强> conf.js 强>
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['e2e/spec.js']
}
<强> E2E / spec.js 强>
var chai = require('chai'),
homepage = require('./homepage.js'),
signin = require('./signin.js');
chai.should()
browser.baseUrl = 'http://localhost:3000'
homepage.test()
signin.test()
<强> E2E / homepage.js 强>
exports.test = function() {
describe('homepage', function() {
it('should have the right title', function() {
browser.get('/')
browser.getTitle().then(function(title){
title.should.eq('Home')
})
});
});
}
<强> E2E / signin.js 强>
exports.test = function() {
describe('signin', function() {
it('should have the right title', function() {
browser.get('/signin')
browser.getTitle().then(function(title){
title.should.eq('Sign in')
})
});
});
}
答案 2 :(得分:2)
我自己也在看同样的事情,在某种程度上我希望你能在这个问题上找到答案。 : - )
话虽如此,看来量角器是新的,没有人真正知道答案,我想这使我的答案和下一个人一样好。
首先,我正在使用量角器入门页面上描述的页面对象表示法,在底部:https://github.com/angular/protractor/blob/master/docs/getting-started.md
这提供了一个模块化元素,我的观点是我最终得到一组类,每页一个,抽象出一些细节。因此,例如,我可能有一个“foo”类,其中包括“foo.get”和“foo.validate(id,name,otherData)”等抽象。这将是一种拉出重复代码的方法。
我没有解决的问题是如何创建模块库,然后将它们组装成一组场景。我有几点想法:
我还没有说这是一个好主意,只是表面看起来它可以起作用,并且会产生预期的结果。我主要担心的是它感觉很脆弱 - 因此随着测试套件的大小增加,它可能变得非常难以维护。也许另一种方法是,不是对场景进行编号,而是将它们定义为依赖项,并且有一些东西可以确保任何给定的脚本在它声明自己依赖的任何脚本之后运行。这也许允许对脚本进行子集化 - 所以你可以说“运行吧脚本”,框架会知道条形脚本需要先运行foo脚本,也许还需要登录脚本。但是可以将所有其他脚本保留下来。
编辑:我认为astrolabe在这里可能是一个很好的答案,看起来它明确允许你模块化你的测试。 https://github.com/stuplum/astrolabe。我刚刚完成了它的概念验证,它似乎做了我可能希望的一切。它的代码最终结果如下:
clubs.part.scenario.js:
/**
* Partial for the page objects associated with clubs
*/
var Page = require('astrolabe').Page;
module.exports = Page.create({
url: { value: 'UI/index.html#clubs' },
title: { get: function() { return this.findElement(this.by.id('title')); } },
description: { get: function() { return this.findElement(this.by.id('description')); } },
clubTableElement: { value: function(rowNum, columnBinding) {
return this.findElement(this.by.repeater('club in clubs').row(rowNum).column(columnBinding)); } }
}
);
clubs.scenario.js:
/**
* End to end tests for the club functionality
*/
var homePage = require('../home/home.part.scenario.js');
var clubsPage = require('./clubs.part.scenario.js');
describe( 'Navigate to club list page', function() {
it ( 'should allow navigation to the club list page', function() {
homePage.go();
expect(homePage.clubsLink.getText()).toEqual('Clubs');
homePage.clubsLink.click();
expect(clubsPage.title.getText()).toEqual('Club functions');
expect(clubsPage.description.getText()).toEqual('Soon this will show a list of all the clubs, based on information from the server');
expect(clubsPage.clubTableElement(0, 'name').getText()).toEqual('First club');
expect(clubsPage.clubTableElement(0, 'contact_officer').getText()).toEqual('A Person');
expect(clubsPage.clubTableElement(1, 'name').getText()).toEqual('Second club');
expect(clubsPage.clubTableElement(1, 'contact_officer').getText()).toEqual('J Jones');
});
it ( 'should allow us to go directly to the club list page', function() {
clubsPage.go();
expect(clubsPage.title.getText()).toEqual('Club functions');
expect(clubsPage.description.getText()).toEqual('Soon this will show a list of all the clubs, based on information from the server');
expect(clubsPage.clubTableElement(0, 'name').getText()).toEqual('First club');
expect(clubsPage.clubTableElement(0, 'contact_officer').getText()).toEqual('A Person');
expect(clubsPage.clubTableElement(1, 'name').getText()).toEqual('Second club');
expect(clubsPage.clubTableElement(1, 'contact_officer').getText()).toEqual('J Jones');
});
});
我对这种结构感到非常满意,它不会做任何事情,但它会做大多数事情。我提供的示例代码来自我已经使用angularjs进行了一段时间的教程,我正在更新e2e测试和Rails 4,如果你想要上下文:{ {3}}