Download - 前端测试
![Page 1: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/1.jpg)
前端测试
![Page 2: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/2.jpg)
赵勇 / 淘宝 UED / 前端 / 遇春(花名)
个人介绍:
![Page 3: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/3.jpg)
前端测试
![Page 4: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/4.jpg)
前端 测试
Why
![Page 5: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/5.jpg)
找一个说服自己的理由
![Page 6: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/6.jpg)
• RIA
• Base on Browser
• Heavy Javascript
• Html 5
产品的变化
![Page 7: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/7.jpg)
Server Browser
Server Browser
开发量的变化
![Page 8: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/8.jpg)
前端质量
内部质量
可维护性性能设计模式开发效率
外部质量
功能
界面
前端关注点的变化
![Page 9: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/9.jpg)
前端团队的变化
游击队
正规军
![Page 10: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/10.jpg)
测试同学:
“ 前端的问题越来越多了”
![Page 11: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/11.jpg)
别再找理由了先搞起来再说
![Page 12: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/12.jpg)
前端 测试
How
![Page 13: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/13.jpg)
前端测试目标
• 产品界面
• 功能可用
• 性能高效稳定
• 代码可维护性强
![Page 14: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/14.jpg)
声音“ 前端不好测”“ 界面老是改,改完用例就没用了”“ 单元测试不好做,很难隔离,不好做mock”
“ 业内没有成熟的实践”“ 项目太紧,没时间”“ 前端测试性价比不高”
![Page 15: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/15.jpg)
前端的痛
Ajax
闭包
Dom
异步
匿名函数
浏览器
兼容性
面向过程
性能
![Page 16: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/16.jpg)
分而治之
Ajax
闭包Dom
异步
匿名函数
浏览器
兼容性
面向过程
性能
Dom 测试 单元测试功能测试 性能测试
![Page 17: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/17.jpg)
Dom 测试• 结构,布局• 兼容性
单元测试• 对象属性,方法• 过程函数
功能测试• 过程
性能测试• 动态执行响应
前端测试
![Page 18: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/18.jpg)
DOM 测试
![Page 19: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/19.jpg)
测试目标• DOM 结构完整
• 模块布局样式无错乱
• 浏览器兼容性
![Page 20: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/20.jpg)
谁动了我的 TAG
</div>
![Page 21: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/21.jpg)
• 加个样式, Ie6 乱掉了
• 开发 html 嵌套时,标签没闭合
• 某个元素的样式名写错了
• …
还有
![Page 23: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/23.jpg)
代码
describe('UI-logo',function(){
var logo = KISSY.get('#logo');
it('exist',function(){
expect(logo).toBeNode();
});
})
![Page 24: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/24.jpg)
代码describe('UI-logo',function(){
var logo = KISSY.one('#logo');
it('position is right',function(){
var oPos = (KISSY.DOM.viewportWidth() – 990)/2;
expect(logo.width()).toNear(177);
expect(logo.height()).toNear(48);
expect(logo.offset().left).toNear(oPos);
expect(logo.offset().top).toNear(47); });
})
![Page 25: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/25.jpg)
代码describe('UI- 新鲜货 ',function(){
var freshItem = KISSY.one('#J_FreshItems');
it('childNode is right',function(){
expect(freshItem.children().length).toBe(2);
});
})
![Page 26: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/26.jpg)
功能测试
![Page 27: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/27.jpg)
功能测试目标 • 功能可用
• 交互过程正确
![Page 29: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/29.jpg)
代码describe(' 功能 - 城市切换 ', function(){
var cityTrigger = KISSY.get('.J_CityPicker'),
cityPopup = KISSY.get('.more-city-bd');
it(' 打开地区浮出层 ', function(){
jasmine.simulate(cityTrigger, 'mouseover');
expect(cityPopup).toBeVisible();
});
})
![Page 30: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/30.jpg)
性能测试
![Page 31: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/31.jpg)
性能测试目标 • 同步执行耗时
• 异步响应耗时
![Page 33: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/33.jpg)
代码describe(' 功能 - 城市切换 ', function(){
var cityTrigger = KISSY.one('.J_CityPicker').getDOMNode(),
cityPopup = KISSY.one('.more-city-bd').getDOMNode();
it(' 打开速度 ', function(){
var start = +new Date();
jasmine.simulate(cityTrigger, 'mouseover');
var end = +new Date();
var runtime = end-start;
expect(cityPopup).toBeVisible();
expect(runtime).toBeLessThan(500);
});
})
![Page 34: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/34.jpg)
代码describe(' 搜索推荐 - 城市切换 ',function(){
var searchInput = KISSY.get('#J_TBSearchQuery');
it(' 自动搜索推荐 ', function(){
searchInput.value = 'nokia';
jasmine.simulate(searchInput,'keydown');
waits(1000);
runs(function(){
var suggestContainer = KISSY.get('.ks-suggest-container');
var suggestContent = KISSY.one('.ks-suggest-content').children().length;
expect(suggestContainer).toBeVisible();
expect(suggestContent).toBe(1);
}); });})
![Page 35: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/35.jpg)
单元测试
![Page 36: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/36.jpg)
单元测试目标• 函数
• 对象的属性和方法
• 业务逻辑
![Page 37: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/37.jpg)
代码可测试性问题
1.面向过程,过程嵌套
2.太多的 DOM 操作
3.展现逻辑和业务逻辑混淆
4.闭包
![Page 38: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/38.jpg)
语言特性
1.本地对象 & 宿主对象
2.静态作用域链
3.动态 & 弱类型
![Page 39: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/39.jpg)
提升可测试性
抽象
![Page 40: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/40.jpg)
绑定事件回调
更新 DOM
处理数据
从 UI 层获取数据
定义变量
定义常量
function(){
var CONSTANTS = 'constants value',ELEMENTID = 'J_EId';
var localVariable,result;
var element = KISSY.one(ELEMENTID);
localVariable = element.attr('data-need');
result = handle(localVariable);
update(element,result);
E.on(element, 'event', EventHandler);
}
过程式函数结构
![Page 41: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/41.jpg)
数据属性
DOM 相关属性
处理数据的方法
操作 DOM 的方法
功能或过程方法
Obj : {
attr-data:'value',
attr-ui:D.get('xid'),
method-data:function(){// deal attr-data...
},
method-ui:function(){// deal attr-ui...
},
process:function(){method-data();method-ui();
}}
对象结构
![Page 42: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/42.jpg)
1. 单一职责法则,更细颗粒的过程抽象
2. 避免使用匿名函数
3. 将数据处理和 DOM 操作完全分开
4. 分离业务逻辑和展现逻辑
5. 减少闭包,为闭包中待测函数提供全局命名空间
如何抽象
![Page 43: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/43.jpg)
过程抽象范例
//...calculate point
var level;if (point < 100){
level = ' 文艺青年 ';}else if (point >= 100 && point < 200){
level = ‘2B 青年’ ;}else{
level = ' 普通青年‘ ;}
//...use level
function getLevel(point){var level;if (point < 100){
level = ' 文艺青年 ';}else if (point >= 100 && point < 200){
level = '2B 青年‘ ;}else{
level = ' 普通青年‘ ;}return level;
}
//...var level = getLevel(point);//...
![Page 44: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/44.jpg)
闭包内函数暴露测试接口范例
(function(){var a = 1;function method1(m){
return a + m;}testTarget = window['testTarget‘] || {};testTarget.method1 = method1;
})();
![Page 45: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/45.jpg)
Event.on('#content','blur',function(){
if(this.value === ''){
alert(' 输入有误,不能为空 ')
}
})
逻辑分离范例
hasError(this.value)
showError()
Event.on('#content','blur',function(){if(hasError(this.value)){
showError();}
})function hasError(v){
return isBlank(v);}function isBlank(v){
var BLANK = '';return KISSY.trim(v) === BLANK;
}function showError(){
var errMsg = ' 输入有误,不能为空 ';alert(errMsg);
}
![Page 46: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/46.jpg)
提升可测试性
分层
![Page 47: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/47.jpg)
Javascript
1.构建 Js 本地对象
2.处理数据逻辑
3.与 Server 通信
4.添加事件回调
5.操作 DOM , BOM
![Page 48: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/48.jpg)
BOM
UI
Model
DOM
Javascript
Server
Control
![Page 49: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/49.jpg)
View Control
Model
obj
obj obj
objobj
obj
obj obj
obj instantiation
process
bindEvent
…
MVC 对象结构
![Page 50: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/50.jpg)
ViewObj
_Attr : value1
AttrEl : someEl
getUIData : function(){//…
}
setUI : function(){//…
}
1.获取 DOM , BOM 数
据
2.修改 DOM 和 BOM
3.处理展现层逻辑
![Page 51: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/51.jpg)
ModelObj
_Attr1 : value1
_Attr2 : value2
_Method : function(){//…
}
Method : function(){//…
}
1.建立业务数据模型
2.处理数据间的逻辑关系
3.提供数据访问器
4.预留数据事件接口
![Page 52: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/52.jpg)
ControlVar objUI = new View();Var obj = new Model();
Function Process1(){//…
}Function Process2(){
//…}
E.on(someEl,’event’,process1);
1.对象实例化
2.初始化
3.定义过程 , 实现
view 和 model 层对
接
4.事件绑定
![Page 53: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/53.jpg)
1. 可测试性提升
2. 各层关注分离,提升可扩展性
3. 业务逻辑和展现逻辑分离, UI 修改更安全
分层的好处
![Page 54: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/54.jpg)
1. 面向过程面向对象,推行成本较大
2. 对于简单的过程,反而增加可理解性
3. 对开发人员的抽象能力要求较高
分层的问题
![Page 56: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/56.jpg)
Dom 测试 单元测试
功能测试 性能测试
如何应用?
![Page 57: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/57.jpg)
单元测试
性能测试功能测试
DOM 测试
逻辑复杂型首页型
交互型
![Page 58: 前端测试](https://reader031.vdocuments.site/reader031/viewer/2022020105/5411e2657bef0ae6708b5539/html5/thumbnails/58.jpg)
3QA