1 / 58

前 端 测试

前 端 测试. 个人介绍:. 赵勇 / 淘宝 UED / 前端 / 遇春(花名). 前端测试. 找一个 说服自己的理由. 产品的变化. RIA Base on Browser H eavy J avascript H tml 5. 开 发量的 变化. Server. Browser. Server. Browser. 前 端关注点的 变化. 外部质量 功 能 界面. 内 部质量 可 维 护 性 性 能 设计模式 开发效率. 前端 质量. 前 端团队的 变化. 游击队. 正规军. 测 试同学: “前端的问题越来越多了”.

Download Presentation

前 端 测试

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 前端测试

  2. 个人介绍: 赵勇/ 淘宝UED / 前端 / 遇春(花名)

  3. 前端测试

  4. 找一个 说服自己的理由

  5. 产品的变化 • RIA • Base on Browser • Heavy Javascript • Html 5

  6. 开发量的变化 Server Browser Server Browser

  7. 前端关注点的变化 外部质量 功能 界面 内部质量 可维护性 性能 设计模式 开发效率 前端质量

  8. 前端团队的变化 游击队 正规军

  9. 测试同学: “前端的问题越来越多了”

  10. 别再找理由了 先搞起来再说

  11. 产品界面 • 功能可用 • 性能高效稳定 • 代码可维护性强 前端测试目标

  12. 声音 “前端不好测” “界面老是改,改完用例就没用了” “单元测试不好做,很难隔离,不好做mock” “业内没有成熟的实践” “项目太紧,没时间” “前端测试性价比不高”

  13. 前端的痛 Dom 兼容性 匿名函数 Ajax 面向过程 闭包 异步 浏览器 性能

  14. 分而治之 匿名函数 浏览器 兼容性 Ajax 闭包 Dom 单元测试 Dom测试 性能测试 功能测试 面向过程 性能 异步

  15. 单元测试 • 对象属性,方法 • 过程函数 • Dom测试 • 结构,布局 • 兼容性 前端测试 • 功能测试 • 过程 • 性能测试 • 动态执行响应

  16. DOM测试

  17. DOM结构完整 • 模块布局样式无错乱 • 浏览器兼容性 测试目标

  18. 谁动了我的Tag </div>

  19. 还有 • 加个样式,Ie6乱掉了 • 开发html嵌套时,标签没闭合 • 某个元素的样式名写错了 • …

  20. Demo http://www.labs.com/sample/ershou.html#testOn

  21. 代码 describe('UI-logo',function(){ varlogo = KISSY.get('#logo'); it('exist',function(){ expect(logo).toBeNode(); }); })

  22. 代码 describe('UI-logo',function(){ varlogo = KISSY.one('#logo'); it('position is right',function(){ varoPos = (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); }); })

  23. 代码 describe('UI-新鲜货',function(){ varfreshItem = KISSY.one('#J_FreshItems'); it('childNode is right',function(){ expect(freshItem.children().length).toBe(2); }); })

  24. 功能测试

  25. 功能可用 • 交互过程正确 功能测试目标

  26. Demo http://www.labs.com/sample/ershou.html#testOn

  27. 代码 describe('功能-城市切换', function(){ varcityTrigger = KISSY.get('.J_CityPicker'), cityPopup= KISSY.get('.more-city-bd'); it('打开地区浮出层', function(){ jasmine.simulate(cityTrigger, 'mouseover'); expect(cityPopup).toBeVisible(); }); })

  28. 性能测试

  29. 同步执行耗时 • 异步响应耗时 性能测试目标

  30. Demo http://www.labs.com/sample/ershou.html#testOn

  31. 代码 describe('功能-城市切换', function(){ varcityTrigger = 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); }); })

  32. 代码 describe('搜索推荐-城市切换',function(){ varsearchInput = KISSY.get('#J_TBSearchQuery'); it('自动搜索推荐', function(){ searchInput.value= 'nokia'; jasmine.simulate(searchInput,'keydown'); waits(1000); runs(function(){ varsuggestContainer = KISSY.get('.ks-suggest-container'); varsuggestContent = KISSY.one('.ks-suggest-content').children().length; expect(suggestContainer).toBeVisible(); expect(suggestContent).toBe(1); }); }); })

  33. 单元测试

  34. 函数 • 对象的属性和方法 • 业务逻辑 单元测试目标

  35. 代码可测试性问题 面向过程,过程嵌套 太多的DOM操作 展现逻辑和业务逻辑混淆 闭包

  36. 语言特性 本地对象 & 宿主对象 静态作用域链 动态 & 弱类型

  37. 提升可测试性 抽象

  38. 过程式函数结构 function(){ var CONSTANTS = 'constants value', ELEMENTID = 'J_EId'; varlocalVariable, result; var element = KISSY.one(ELEMENTID); localVariable = element.attr('data-need'); result = handle(localVariable); update(element,result); E.on(element, 'event', EventHandler); } 定义常量 定义变量 从UI层获取数据 处理数据 更新DOM 绑定事件回调

  39. 对象结构 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(); } } 数据属性 DOM相关属性 处理数据的方法 操作DOM的方法 功能或过程方法

  40. 如何抽象 单一职责法则,更细颗粒的过程抽象 避免使用匿名函数 将数据处理和DOM操作完全分开 分离业务逻辑和展现逻辑 减少闭包,为闭包中待测函数提供全局命名空间

  41. 过程抽象范例 //...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); //...

  42. 闭包内函数暴露测试接口范例 (function(){ var a = 1; function method1(m){ return a + m; } testTarget = window['testTarget‘] || {}; testTarget.method1 = method1; })();

  43. 逻辑分离范例 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(){ varerrMsg = '输入有误,不能为空'; alert(errMsg); } Event.on('#content','blur',function(){ if(this.value=== ''){ alert('输入有误,不能为空') } }) hasError(this.value) showError()

  44. 提升可测试性 分层

  45. 构建Js本地对象 处理数据逻辑 与 Server 通信 添加事件回调 操作DOM,BOM Javascript

  46. DOM BOM Javascript Control UI Model Server

  47. MVC对象结构 View Control obj obj obj instantiation obj obj process bindEvent … Model obj obj obj obj

  48. ViewObj 获取DOM,BOM数据 修改DOM和BOM 处理展现层逻辑 _Attr:value1 AttrEl:someEl getUIData:function(){ //… } setUI:function(){ //… }

More Related