前戏
- 面向模型编程;
- 测试驱动开发;
- 先保障交互逻辑,再调整细节。---by 雪狼。
为什么要自动化测试?
1,提高产出质量。
2,减少重构时的痛。反正我最近重构多了,痛苦经历多了。
3,便于新人接手。
angular自动化测试主要分:端到端测试和单元测试,很明显两者都要熟练掌握。
端到端测试是从用户的角度出发,认为整个系统是个黑盒,只会有ui暴露给用户,主要是模仿人工操作测试。
单元测试认为整个系统是白盒,可以用来测试服务,控制器,过滤器还有基础函数等。
端到端测试使用protractor,今天就扯这个。
为什么使用protractor,也就是说protractor有什么好处,有没有替代品?
1,不需要基于id,css选择器,xpath等查询元素,你可以基于绑定,模型,迭代器等等进行测试。
2,避免回调地狱。对比下面的代码就知道了。
//没有protractor
driver.gettitle().then(function(title){
expect(title).tobe('baidu');
});
//使用protractor
expect(browser.gettitle()).toequal('baidu');
替代品:capybara-angular等。
正文
前戏做完了,开始办正事吧。
第一步当然是配置protractor,别人写好了,我就不累赘了,送上传送门:
第二步,掌握最简单的测试(高手可以绕过)
describe('hello world', function() {
it('标题是hello world', function() {
browser.get('测试地址自己搞一个咯');
expect(browser.gettitle()).toequal('hello world');
});
});
说白了就是希望指定的链接的标题是"hello world"
第三步,了解下大体编写流程。

首先我们必须跳转到指定的页面,跳转页面有两种方法。
1,browser.get,跳转到指定的页面,还会重新刷新整个页面。
2,browser.setlocation,更确切的说,是跳转路由,修改#后面部分。
“等待某个元素出现”而不是“等待页面加载完毕”,如果页面加载完毕之后,马上去获取某个元素,很可能改元素不存在,然后直接报错退出。
点击某个按钮之后,弹窗,弹窗有渐进动画,具体弹窗内的元素什么时候出现不确定,那么必须“等待某个元素出现”。怎么实现?
//等待ng-model="password"的出现,最多等待20秒
browser.wait(function(){
return browser.iselementpresent(by.model("password"));
},20000);
封装页面对象,英文叫pageobject,我也不知道怎么翻译,说白了就是封装组件或者页面的选择器。
为什么要有这一步?
先看一段代码:
describe('angularjs homepage', function() {
it('should greet the named user', function() {
browser.get('http://www.51sjk.com/Upload/Articles/1/0/286/286813_20210712000659041.org');
element(by.model('yourname')).sendkeys('julie');
var greeting = element(by.binding('yourname'));
expect(greeting.gettext()).toequal('hello julie!');
});
describe('todo list', function() {
var todolist;
beforeeach(function() {
browser.get('http://www.51sjk.com/Upload/Articles/1/0/286/286813_20210712000659041.org');
todolist = element.all(by.repeater('todo in todos'));
});
it('should list todos', function() {
expect(todolist.count()).toequal(2);
expect(todolist.get(1).gettext()).toequal('build an angular app');
});
it('should add a todo', function() {
var addtodo = element(by.model('todotext'));
var addbutton = element(by.css('[value="add"]'));
addtodo.sendkeys('write a protractor test');
addbutton.click();
expect(todolist.count()).toequal(3);
expect(todolist.get(2).gettext()).toequal('write a protractor test');
});
这是没封装的情况。
1,语义化很差,根本很难看明白在做神马。
2,重复代码多。browser.get('http://www.51sjk.com/Upload/Articles/1/0/286/286813_20210712000659041.org');就不止出现了一次。
3,耦合严重。如果标签结构改动,代码很多地方都要改。
4,难以维护,随着项目的增长和时间的推移,没有人会乐意在这上面添加其它测试功能。
问题已经暴露出来了,怎么封装?
封装之前,建议过一遍官方的教程和api接口,常用的不多,难度不大。。
举个栗子,很简单的。现在有个滚动条。示意图有点丑,别笑。

封装出来应该如下,这样即使滚动条的代码结构改了什么的,只要改下面的代码,而具体测试逻辑不用动。
function scrollbarselector(model){
object.defineproperty(this,"target",{
get:function(){
return typeof model == "string" ? element(by.model(model)) : model;
}
})
object.defineproperty(this,"pre",{
get:function(){
return this.target.$(".pre");
}
})
object.defineproperty(this,"next",{
get:function(){
return this.target.$(".next");
}
})
object.defineproperty(this,"scrollbutton",{
get:function(){
return this.target.$(".scrollbutton");
}
})
object.defineproperty(this,"value",{
get:function(){
return this.target.$("input").getattribute("value");
} })
}
测试逻辑,基本上就是,
点击某个按钮:scrollbar.next.click()
希望某个输入框的内容为:expect(scrollbar.value).tobe("xx");
最后,还是附上登录的测试和路由跳转,google上面很多人都在问。很多人问的问题是,登录完了,跳转页面,怎么知道页面跳转了。
spec.js
!function(){
require(".loginaction.js");
require(".logoutaction.js");
require(".scrollbaraction.js");
describe("自动登录",function(){
new loginaction().execute("getlishu","123456");
})
describe('testscrollbar', function () {
new scrollbaraction().execute();
});
describe("退出登录",function(){
new logoutaction().execute();
});
}();
loginaction.js
!function(){
function loginaction(){
}
var prop = loginaction.prototype;
prop.execute = function(username,password){
beforeeach(function () {
//先跳转到登录页面
browser.get("登录页面");
//等待输入框出来
browser.wait(function(){
return browser.iselementpresent(by.model("username"));
},20000);
})
//输入账号密码然后点击登录
it('自动登录', function () {
element(by.model("username")).sendkeys(username);
element(by.model("password")).sendkeys(password);
element(by.css(".login-input-btn")).click();
});
}
module.exports = loginaction;
}();
scrollbaraction.js
!function(){
beforeeach(function () {
browser.setlocation("/app/common/stepper");
})
it('测试滚动条', function () {
var scrollbar = new scrollbarselector("vm.scroll");
//等待滚动条出来,最多等待20秒,滚动条出来了,马上处理测试代码
browser.wait(function(){
return browser.iselementpresent(numberdefault.mius);
},20000);
//这里省略很多行测试代码
});
}();
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
歆颢美菱格