阅读更多
测试是完善的研发体系中不可或缺的一环,但是在前端开发的项目中做单一测试的相对较少。为让大家了解前端测试给项目带来的好处,七牛资深前端工程师马逸清结合技术开发团队在前端测试方面的积极探索,特别撰文分享了七牛在前端测试的实践经验。

理想中的代码结构,每个模块都应该比较简单,且每个模块之间的关系也应该非常清晰。但事实上,在做Web开发的过程中,随着功能和迭代次数越来越多,就会产生一些问题。最初,七牛的Web开发并没有写测试,在开发的过程中常遇到代码稍作修改便会产生Bug的情况。而在做一些新功能开发时又很难察觉到它会对旧功能产生影响,到上报之后才发现有问题。另外,代码放久了,也不敢重构。因此,七牛开始考虑做前端测试。

七牛前端测试的早期尝试

七牛最早的尝试是使用 Selenium + Phantom,通过模拟用户操作来进行测试。比如,登录过程的代码大致如下:



测试过程就是打开某个页面之后,输入用户名、密码,点击这个按钮模拟用户的操作过程。这部分的工作其实是在做端到端的测试,而实际项目中,业务逻辑相对复杂,编写端到端测试工作量比较大,测试代码也会很复杂。因此,这样的做法没有很好地发扬起来。

既然做完整测试比较麻烦,七牛前端团队决定做一些更小粒度的测试,对一些基础函数编写单元测试。他们会抽取一些基本函数和组件放在统一的模块中,编写单元测试去验证函数是否符合预期。测试粒度变小以后,相比端到端测试,写测试变得更加容易,但对于 DOM 依赖比较强的部分,就会难以测试。

举个例子,设置七牛开发者平台顶部导航和侧边栏导航选中状态的功能是通过 jQuery 扩展的方式实现的,主要通过匹配URL和导航栏 A标签中href 属性来判断是否应该选中。这里的各种子页面 URL设计比较杂乱,非常容易出错,所以在编写测试的时候,需要把 DOM 结构写进测试脚本。由于一些历史遗留问题,七牛的导航栏有着两种结构,因此,这一部分的测试变得非常痛苦,DOM 结构发生一些微小的变化,整个测试脚本都要跟着改。所以对于依赖 DOM 结构的功能测试还比较少,并没有做到完全覆盖。

在实际开发中要尽量避免逻辑和 DOM 的耦合,分离之后才能更加方便地去验证业务逻辑。使用 MVC 框架是一个比较好的方式,关注度分离,让 DOM 和业务逻辑解耦。

七牛新的项目选择了 AngularJS,AngularJS对测试很友好,不允许在 Controller 里操作 DOM和依赖注入都让测试工作更加方便。换了AngularJS之后,测试的部分主要分为三类:一是Utils,包括一些格式化的函数、验证的函数;二是 Service 里的 Model 状态;三是 View 状态,这些和具体展现以及业务逻辑都有关,是比较复杂的部分。

Utils的测试



以上是对于Utils测试的代码,在代码里注入相关模块就可以进行测试(网上有很多相关的教程,对于 Utils 的测试比较简单)。接下来是做Service的测试,在这个过程中需要做一下设置。如下图所示:



Service封装了很多HTTP请求,这样会依赖于API服务,为此,我们使用AngularJS自带的Mock模块将HTTP这一层处理掉,使用Mock模块在测试时不会发出HTTP请求。同时也可以通过这个模块验证发出的请求以及请求的参数等。再接下来是Controller的测试,主要测一些外围的函数和变量的状态。如以下代码:






在实际的测试过程中,团队会遇到一些依赖不好处理的情况,比如依赖当前时间或者随机字符串,使用 Stub 就可以比较好的处理这种情况。如用户登录后会记录登录的时间,每次请求都会先用当前时间和登录时间进行比较,判断登录是否过期,这里就会依赖当前时间,由于每次运行测试脚本的时间不确定,因此需要替换掉当前时间。七牛使用的是sinon.js,把某个对象当中的某个方法替换掉,一旦每次调用当前时间,它就变成一个固定的值,后面的测试就跟以前的基本方式一样。具体方法如下:



在做测试的时候,某些逻辑代码依赖的是外部的返回值,这时用Stub最合适。因为Stub在Sinon库里可以选择每一次调用的返回值,或者某个参数的返回值,这样能满足绝大部分需求。

Mock除了关注外部依赖的返回值外,还关注外部调用的值。因此,在存/写一些状态的时候,没有返回值就不知道存/写是否成功,只能测试是否调用到了外部依赖的某个方法,传进去的参数是否是预期的。使用Mock的方式,最开始调用时要验证某个Mock对象的某个行为,最后再由Mock对象去验证它的行为是否正确。手工写一个Mock的对象会很麻烦,一般会使用通用的一些函数库来减少工作量。

在测试过程中,大部分情况下用Stub就足够了。如果一些测试依赖某些返回值,但又没有返回值,该怎么办?这里可以用Spy对象去验证一些函数是否被调用、调用时的参数等,Spy就是带有行为验证的Stub。

有了MVC框架和Stub,基本上单元测试中的问题就都能解决了,但是实践中还存在对于Mock Data处理的小问题。七牛团队最初的做法是直接在测试里硬编码了Mock数据,但测试脚本多了以后难以维护,后来便更换了方式,使用了Karma-fixture插件。由于前后端的同时进行,开发时后端API往往没有准备好,所以这里会先构造一些Mock数据,以Json文件的形式放在Mock目录下,再运行一个静态Server专门提供这些Mock数据。使用这样的插件,在测试代码里面便可以把这些Mock数据加载进来直接使用。这样做的好处在于,大家在开发调试和写单元测试时,使用的是同样一套Mock数据。将来如果结构发生一些小的调整(比如加字段),也只需要做简单的修改。

目前用到的工具:Karma+PhantomJS

在七牛早期项目中,测试工具主要使用Selenium,但Selenium配置比较复杂。因此,七牛在新项目开始使用Karma+PhantomJS,Karma比Selenium更加轻量,更适合运行单元测试。而脚本运行的浏览器环境选择PhantomJS,可以直接在命令行里看到结果,不会每次运行测试时弹出界面。测试框架官方推荐Jasmine(包括Stub、Spy的功能),虽然Jasmine的断言以及 Stub功能不如Mocha+Chai+Sinon强大,但对于实际项目已经足够。此外,测试还会依赖一些Karma插件,如测试覆盖率Karma-coverage工具、Karman-fixture工具及Karma-coffee处理工具。此外,前端社区里提供里比较丰富的插件,常见的测试需求都能涵盖到。






工具的配置可按照以上两图的代码先把Karma的文件配置好,然后再配置到自己的gulpfile里。配置gulp如下:



GULP主要配置了两个地方,一是只跑一次测试的testOnce,二是测试代码的testAndWatch。每次进行修改、保存,它都能自动的再跑,这样可以一边开发一边跑测试,从而查看对当前的代码有没有影响。

有了这部分的测试环境,可以把它配置到持续集成的环境当中。由于现有的工具已经非常成熟,这里可以导出覆盖率报告进行分析,之后还可以改进mockData。如果将来业务变得更加复杂,可以考虑加入UI的自动化测试。

前端测试带来的益处

首先,写测试代码和写业务代码时思考方式不一样,写测试代码的时候会考虑业务逻辑的边际条件是什么,这样就能提前找到开发时不太容易找到的Bug。当思路还在功能上时,去修改这个Bug会相对比较轻松,如果后面发现再去修改,就会花更多的工夫。

另一个好处是在写业务代码的时候,理解会更深刻。写测试时会发现代码不好测,输入输出不合理的情况。写测试可以帮助你找到更合理的代码结构。另外,如果很多人共同维护一份代码又需要对公共组件做一些小修改的时候,有了测试改起来会非常安心,测试覆盖比较好的情况下,会减少修改代码的心理负担。

前端的框架非常多,大家可以自由选择适合自己业务的框架。现阶段,前端MVC框架发展非常迅猛,它把DOM的结构和业务累计分离开来,使得测试比以前更好做。此外,Node.js的发展对于后端的测试非常重要,它有一些完善的工具链,在测试方面不会遇到阻碍,因为搭建一个测试环境已经变得非常简单。有了以上的测试环境,在写测试的过程中,更多的便是一个理想和现实之间的平衡。

关于前端测试的建议

对于一些规模较小、人手不足的公司,开发人员写测试的总会遇到一些影响因素,如:
  • 迭代速度快;
  • 业务需求不稳定,有时手里的代码还未写完,又需要修改功能;
  • 人手不足,把功能代码写完已经需要加班,但还需要写测试代码;
大部分的实际情况比解决方案要复杂。在测试的时候,可能要模拟多种实际情况,而业务代码则有可能就是实际的解决方案。对于比较大型的产品,测试代码比业务代码更多,项目紧张或者功能需求不稳定的情况下,过度测试不不可取。

目前七牛的做法是有选择性的写测试。首先,七牛会测试比较重要的部分,评估一些风险。比如数据统计、计费等和用户密切相关的内容。其次是测试比较稳定的部分,即跟业务不相关的部分函数。再次是测试依赖比较少的部分,这里只需要关注它整个逻辑本身。

在人手不足、时间有限的情况下,可能无法很快加上测试环节,这时一定要养成验证的习惯。随着公司业务发展,项目逐渐变大的时候,为了保持代码的可维护性,进行测试变得非常有必要,特别是在开发过程中,它能帮助你找到一些不容易察觉的小Bug。一些开发人员可能认为写测试会耗费额外的时间,但是对于大型软件项目,合适的测试方案能够大大减少今后的维护成本,从长远来看,写测试所花的时间是非常值得的。(责编:陈秋歌)

作者:马逸清,七牛云存储资深前端工程师,上海谷歌开发者社区组织者。关注各种前端技术,也对代码设计和质量维护相关的话题感兴趣,喜爱参加技术分享活动。
  • 大小: 135 KB
  • 大小: 136.9 KB
  • 大小: 158.8 KB
  • 大小: 96.2 KB
  • 大小: 144.8 KB
  • 大小: 143.5 KB
  • 大小: 116.4 KB
  • 大小: 161 KB
  • 大小: 93.5 KB
1
1
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • 工作中使用到的单词(软件开发)

    【Spring中这两个核心思想」都是一种设计模式(工厂,代理) 代理 51. AOP术语总结 ■2022/01/06 至 2022/01/30之间整理 (纯单词) ■2022/02/01以降 ■2022/02/23 以降整理 spring 学习 官网链接 Spring组件注册...

  • 工作中使用到的单词(软件开发)_2023_0316备份

    【Spring中这两个核心思想」都是一种设计模式(工厂,代理) 代理 51. AOP术语总结 ■2022/01/06 至 2022/01/30之间整理 (纯单词) ■2022/02/01以降 ■2022/02/23 以降整理 spring 学习 官网链接 Spring组件注册...

  • 面试题:面试题归类 已看1

    一、Java基础 1. String类为什么是final的。 答:主要是为了“效率”和“安全性”的缘故。若String允许被继承,由于它的高度被使用率,可能会降低程序的性能,所以String被定义成final。 2. HashMap的源码,实现...

  • CSDN Blog 2005年08月08日 帖子列表:

    http://blog.csdn.net/Article/D/200508/20050808/index.html CSDN Blog 2005年08月08日 帖子列表:成为技术传播者(一):写在前面CommunityServer研究(一) 安装什么是爱情 CSDN 即兴言论(FengYuanMSFT (袁峰 ...

  • webmagic采集CSDN的Java_WebDevelop页面

    项目中使用到了webmagic,采集论坛一类的页面时需要一些特殊的配置。在此记录一下 先来看看我要采集的页面 点击第2页可以看到它的url是http://bbs.csdn.net/forums/Java_WebDevelop?page=2 ...

  • 程序员常用英语大集合 http://bbs.itheima.com/thread-118950-1-1.html (出处: 黑马程序员IT技术论坛)

    干程序员这行实在是离不开英语,干程序员是一项很...首先编程本身就依赖于英语,虽然现在技术的发展,可以使得某些开发工具在变量名和字段名中支持中文,但还未发现能够完全使用中文的编程语句。   这并不代表我们

  • 尚学堂Java面试题整理

    1. super()与this()的区别? - 6 - 2. 作用域public,protected,private,以及不写时的区别?...5. 在JAVA中,如何跳出当前的多重嵌套循环? - 6 - 6. 什么是java序列化,如何实现java序列化?(写一个实例) - 6 - 7...

  • JAVA项目面试常谈问题以及个人开场介绍模板

    JAVA 人力面试常谈问题 汇总(98个) 1. 请你自我介绍一下 回答提示:一般人回答这个问题...企业很重视一个人的礼貌,求职者要尊重考官,在回答每个问题之后都说一句谢谢.。企业喜欢有礼貌的求职者。 2. 你觉得你个性上

  • 栋的月结 | 第二回合(定期更新、动态、架构、云技术、算法、后端、前端、收听/收看、英文、书籍、影视、好歌、新奇)[含泪总结.. 憋泪分享!]

    应用的基础架构:中央处理器+存储+一系列的输入输出设备;可编程性(计算类、I/O类、指令跳转类);开放设计的外部设备支持(电脑的 CPU 非常简洁,只读入和写出数据并对其进行计算。直接用机器指令太累,没人看懂...

  • 鸟哥的LInux私房菜 基础学习篇 第四版 学习笔记

    (3) 利用 ls -l 显示的文件属性中,第一个字段是文件的权限,共有十个位,第一个位是文件类型, 接下来三个为一组共三组,为使用者、群组、其他人的权限,权限有 r,w,x 三种; (4)如果档名之前多一个『. 』,则...

  • 面试题整理 !=!=未看 *****面试题整理最全 有用

    当向HashSet集合中存入一个元素时,HashSet会调用该对象的 hashCode()方法来得到该对象的hashCode值,然后根据该HashCode值决定该对象在HashSet中的存储位置。 值得主要的是,HashSet集合判断两个元素相等的标准是两...

  • java面试题目整理

    目录Java面试题整理... - 6 -Java面向对象... - 6 -1. super()与this()的区别?... - 6 -2. 作用域public,protected,private,以及不写时的区别?... - 6 -3.......... 在JAVA中,如何跳出当前的多重...

  • 高负载高并发网站架构分析

    由于自己正在做一个高性能大用户量的论坛程序,对高性能高并发服务器架构比较感兴趣,于是在网上收集了不少这方面的资料和大家分享。希望能和大家交流 msn: defender_ios@hotmail.com ————————————...

  • 2020-09-05

    一、Java 基础部分 二、Java 代码查错 三、算法与编程 四、html&JavaScript&ajax 部分 五、Java web 部分 六、数据库部分 七、XML 部分 八、流行的框架与新技术 九、软件工程与设计模式 十、j2ee ...

  • 栋的周评 | 第六回合(定期更新、动态、架构、云技术、算法、后端、前端、收听/收看、英文、书籍、影视、好歌、新奇)

    信封加密:通过数据密钥加密的纯文本数据、使用密钥加密密钥(KEK)来对数据密钥加密、KEK 可被另一个 KEK 加密,但最终会有一个主的密钥(特指 KMS CMK)以加密一个或多个密钥;KMS API 行为:加密、解密。 评分 ...

  • 基于物联网智能化平台的智慧园区解决方案PPT(28页).pptx

    智慧园区,作为现代城市发展的新形态,旨在通过高度集成的信息化系统,实现园区的智能化管理与服务。该方案提出,利用智能手环、定制APP、园区管理系统及物联网技术,将园区的各类设施与设备紧密相连,形成一个高效、便捷、安全的智能网络。从智慧社区到智慧酒店,从智慧景区到智慧康养,再到智慧生态,五大应用板块覆盖了园区的每一个角落,为居民、游客及工作人员提供了全方位、个性化的服务体验。例如,智能手环不仅能实现定位、支付、求助等功能,还能监测用户健康状况,让科技真正服务于生活。而智慧景区的建设,更是通过大数据分析、智能票务、电子围栏等先进技术,提升了游客的游玩体验,确保了景区的安全有序。 尤为值得一提的是,方案中的智慧康养服务,展现了科技对人文关怀的深刻体现。通过智慧手环与传感器,自动感知老人身体状态,及时通知家属或医疗机构,有效解决了“空巢老人”的照护难题。同时,智慧生态管理系统的应用,实现了对大气、水、植被等环境要素的实时监测与智能调控,为园区的绿色发展提供了有力保障。此外,方案还提出了建立全域旅游营销平台,整合区域旅游资源,推动旅游业与其他产业的深度融合,为区域经济的转型升级注入了新的活力。 总而言之,这份智慧园区建设方案以其前瞻性的理念、创新性的技术和人性化的服务设计,为我们展示了一个充满智慧与活力的未来园区图景。它不仅提升了园区的运营效率和服务质量,更让科技真正融入了人们的生活,带来了前所未有的便捷与舒适。对于正在规划或实施智慧园区建设的决策者而言,这份方案无疑提供了一份宝贵的参考与启示,激发了他们对于未来智慧生活的无限遐想与憧憬。

  • MES制造企业生产过程执行系统:全方位协同管理,提升生产效率与质量的信息化管理平台,MES制造企业生产过程执行系统:全面协同管理,提升生产效率与质量管理水平,mes制造企业生产过程执行系统,是一套面向

    MES制造企业生产过程执行系统:全方位协同管理,提升生产效率与质量的信息化管理平台,MES制造企业生产过程执行系统:全面协同管理,提升生产效率与质量管理水平,mes制造企业生产过程执行系统,是一套面向制造企业车间执行层的生产信息化管理系统。 MES 可以为企业提供包括制造数据管理、计划排产管理、生产调度管理、库存管理、质量管理、人力资源管理、工作中心 设备管理、工具工装管理、采购管理、成本管理、项目看板管理、生产过程控制、底层数据集成分析、上层数据集成分解等管理模块,为企业打造一个扎实、可靠、全面、可行的制造协同管理平台 ,MES制造企业生产过程执行系统;生产信息化管理;制造数据管理;计划排产管理;生产调度管理;库存管理;质量管理;人力资源管理;设备管理;数据集成分析,MES制造企业生产执行系统:全面协同管理平台助力制造企业高效运营

  • C++指针与内存管理详解:避免常见错误及最佳实践

    内容概要:本文介绍了C++编程中常见指针错误及其解决方案,并涵盖了模板元编程的基础知识和发展趋势,强调了高效流操作的最新进展——std::spanstream。文章通过一系列典型错误解释了指针的安全使用原则,强调指针初始化、内存管理和引用安全的重要性。随后介绍了模板元编程的核心特性,展示了编译期计算、类型萃取等高级编程技巧的应用场景。最后,阐述了C++23中引入的新特性std::spanstream的优势,对比传统流处理方法展现了更高的效率和灵活性。此外,还给出了针对求职者的C++技术栈学习建议,涵盖了语言基础、数据结构与算法及计算机科学基础领域内的多项学习资源与实战练习。 适合人群:正在学习C++编程的学生、从事C++开发的技术人员以及其他想要深入了解C++语言高级特性的开发者。 使用场景及目标:帮助读者掌握C++中的指针规则,预防潜在陷阱;介绍模板元编程的相关技术和优化方法;使读者理解新引入的标准库组件,提高程序性能;引导C++学习者按照有效的路径规划自己的技术栈发展路线。 阅读建议:对于指针部分的内容,应当结合实际代码样例反复实践,以便加深理解和记忆;在研究模板元编程时,要从简单的例子出发逐步建立复杂模型的理解能力,培养解决抽象问题的能力;而对于C++23带来的变化,则可以通过阅读官方文档并尝试最新标准特性来加深印象;针对求职准备,应结合个人兴趣和技术发展方向制定合理的学习计划,并注重积累高质量的实际项目经验。

  • VSC下垂控制策略仿真模型:基于MATLAB 2014a及更高版本的全面支持与应用实践,VSC下垂控制策略仿真模型MATLAB版本支持及功能解析,VSC下垂控制策略仿真模型,支持MATLAB2014a

    VSC下垂控制策略仿真模型:基于MATLAB 2014a及更高版本的全面支持与应用实践,VSC下垂控制策略仿真模型MATLAB版本支持及功能解析,VSC下垂控制策略仿真模型,支持MATLAB2014a及以上版本 ,VSC下垂控制策略; 仿真模型; MATLAB 2014a及以上版本; 核心关键词,MATLAB 2014a及以上版VSC下垂控制策略仿真模型研究

  • 信息技术知识赛系统设计与实现(代码+数据库+LW)

    摘  要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装信息技术知识赛系统软件来发挥其高效地信息处理的作用,可以规范信息管理流程,让管理工作可以系统化和程序化,同时,信息技术知识赛系统的有效运用可以帮助管理人员准确快速地处理信息。 信息技术知识赛系统在对开发工具的选择上也很慎重,为了便于开发实现,选择的开发工具为Eclipse,选择的数据库工具为Mysql。以此搭建开发环境实现信息技术知识赛系统的功能。其中管理员管理用户,新闻公告。 信息技术知识赛系统是一款运用软件开发技术设计实现的应用系统,在信息处理上可以达到快速的目的,不管是针对数据添加,数据维护和统计,以及数据查询等处理要求,信息技术知识赛系统都可以轻松应对。 关键词:信息技术知识赛系统;SpringBoot框架,系统分析,数据库设计

Global site tag (gtag.js) - Google Analytics