大话js代码静态检查-阿里云开发者社区

开发者社区> 玄学酱> 正文

大话js代码静态检查

简介:
+关注继续查看

1、背景

  首先必须承认,静态代码检查不能解决所有问题!比如说,QA不能指望着靠静态代码检查来发现rd的代码逻辑的bug。而对于javascript,可能就是代码某处少了个分号,或者是某些编码的bad –practice。这些问题可能很小很小,但是对用户体验足以造成巨大影响。因此,如果这种检查真的能发现问题,那么还是很有必要的。

  之后的一个问题是成本:为了发现一个潜在的问题,我们要付出多少精力?静态检查给我们的印象是:飞速的扫描一遍代码然后返回一大堆信息——就像一个可能蕴藏金子的沙堆,我们必须有耐心才能在这个沙堆中找到有价值的信息。显然这一过程的成本由以下两部分组成:代码扫描+判别有效性。第一个过程往往十分迅速,秒级而已。而第二个过程往往需要人工的介入,这是成本消耗的关键点。试想,如果静态检查返回过多无用信息,导致人工检查耗时过长,则这种检查的收益就得不偿失了。

  综上所述,静态代码检查面临的挑战是:准确性和低成本。

  2、初识静态检查规则与工具

  静态检查工具jslint&jshint

  为了应对QA前端js知识储备不足的短板,我们除了加强自身的学习之外,一个有效的方法就是“站在巨人的肩膀上”。

  1)jslint

  前端领域的大牛Douglas Crockford编写了JsLint,将他认为的那些重要的js编程实践作为静态检查项,他提出的某些编程实践也确实被人们所接受,因为这确实是容易引起问题的关键点(例如,在应该使用===的地方不要使用==等)。不过JsLint也存在一些问题,如它的某些检查过于严苛;遇到for-in语句后会停止检测;且非开源。。这些问题都使得人们对JSLint“敬而远之”。

  2)jshint

  为解决jslint现存的问题,有了JSHint这个项目,此开源项目作为JSLint的一个分支,允许用户自定义检查项,使用起来更加轻量级。有了JSHint,程序员就可以根据自己的编程习惯来定制个性化的检查策略。文献[1] 讲述了JSHint与JSLint的区别。

  JsHint本质上是一个js库(jshint.js)。笔者也曾膜拜此文件的代码,发现它实际上是一个js的词法分析器,里面定义了各种规则,然后对输入的代码字符串做切词和匹配,每发现一个“错误”(或是坏的编程实践)就放到结果数组中保存起来。因此,如果你会写js代码的话,完全可以在js文件中引用jshint.js。例如,你可以使用JSHINT函数来进行代码检查,如下所示:

  var result = JSHINT(source, options);

  其中JSHINT是一个全局函数,第一个参数source : 必选项。表示需要检查的代码,js或者json,可以传一个字符串或者一个数组。如果传字符串,需要用’\r’或者’\n’来分隔一行一行的代码;如果传数组,则每一个数组元素表示一行的代码。第二个参数option : 可选项。表示代码检查的配置项,具体的配置项含义参见文献[2],使用key/value字典表示,key就是要检查的配置项名称,value是bool类型。返回值:如果代码没有问题,JSHINT会返回一个true;否则返回false。当返回值是false的时候可以使用JSHINT.errors获取出错的原因,JSHINT.data包含了本次检查更详细的信息。另外,使用JSHINT.report可以生成错误信息的html报告。

  认识检查规则

prop description
bitwise 如果是true,则禁止使用位运算符
curly 如果是true,则要求在if/while的模块时使用TAB结构
debug 如果是true,则允许使用debugger的语句
eqeqeq 如果是true,则要求在所有的比较时使用===和!==
evil 如果是true,则允许使用eval方法
forin 如果是true,则不允许for in在没有hasOwnProperty时使用
maxerr 默认是50。 表示多少错误时,jsLint停止分析代码
newcap 如果是true,则构造函数必须大写
nopram 如果是true,则不允许使用arguments.caller和arguments.callee
nomen 如果是true,则不允许在名称首部和尾部加下划线
onevar 如果是true,则在一个函数中只能出现一次var
passfail 如果是true,则在遇到第一个错误的时候就终止
plusplus 如果是true,则不允许使用++或者- -的操作
regexp 如果是true,则正则中不允许使用.或者[^…]
undef 如果是ture,则所有的局部变量必须先声明之后才能使用
sub 如果是true,则允许使用各种写法获取属性(一般使用.来获取一个对象的属性值)
strict 如果是true,则需要使用strict的用法,
详见http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
white 如果是true,则需要严格使用空格用法。

  不足

  牛人的东西很好,但实际使用起来发现有如下的问题:

  (1)静态代码检查规则配置需要修改Jshint的Js源代码,修改代价较高,且容易出错;

  (2)检查结果误报较多,且可读性差,找到真正是问题的结果需要排查几K的报错信息,效率较低。

  3、jshunter:一款基于jshint的静态代码检查工具

  为解决Jshint以上2个突出问题以及扩展更多的特性满足ECOM WEB类产品JS静态代码检查的准确性、有效性,基于Jshint和Rhino开发了Jshunter这一款工具用于js代码语法类错误检查。

  Jshunter提供的解决方案如下:

  (1)检查规则灵活配置。Jshunter支持将所有检查项放到一个配置文件中,用户可以通过true或false来自定义个性化的检查项,而不必修改Jshint源代码;

  (2)清晰醒目的结果报表。Jshunter从繁杂的检查结果字符串中提出关键信息,以Html文件的形式展现,对扫描结果严重程度给出LEVEL标识。非常适用于持续集成的开发模式,作为Hudson上的一个报表呈现;示意图如下:

  (3)支持Html内嵌js代码的检查,提高检查准确性。业界的Jshint不支持Html内嵌Js代码检查,存在漏检、漏测的风险。Jshunter解决了这个问题,不但能检查Js文件,还能检查Html中内嵌的文件;

  (4)扫描结果过滤,减少冗余信息,提高结果分析效率。通过黑名单过滤和错误级别设定,Jshunter支持用户设定结果提醒级别,目前支持warning,error和ignore,其中被设定ignore的错误不会在报表中呈现,减少冗余信息的查看与分析。

  具体说来,之前困扰的根源就在于我们解析jshint.js的环境是浏览器,受限于浏览器的环境,我们不能进行外部文件读写。如果需要将jshint命令行化我们需要找到这样一个环境:既能解析js代码,又能进行文件读写。因此我们找到了rhino——一个能解析js代码的java环境[4]。利用java环境,我们读取外部文件提取待检查的js代码,之后利用rhino运行大牛写的jshint.js。

  此工具依赖python环境,无需安装。使用也极其简单,只需要进入jshunter的主目录下运行:./hint.py /rest/file/path /path/to/check/*.js就可以了。这里hint.py是主程序的代码,/rest/file/path是该工具生成的报表文件名,/path/to/check/*.js是待检查的文件(支持单个文件和多个文件的代码检查)。程序运行后会根据主目录中的check.cfg配置文件进行检查,该文件各个检查项的具体含义见注释的描述。另外,如果不希望看到某些提示信息,可以将这些信息放到ignore.list黑名单文件中。也就是说,通过check.cfg和ignore.list,用户可以定制符合自己产品线特点的检查策略。

  4、小结

  本文介绍了和js代码静态检查技术相关的内容。代码检查的成本很低,且确实能发现一些潜在的问题。Jshint是业界一款开源的静态代码检查工具,但在易用性方面存在2个突出的问题,针对目前存在的问题,我们基于JSHint开发的一个命令行方式的代码检查工具jshunter,支持自定义的检查策略配置和黑名单过滤机制,并且能生成格式美观的报表。









====================================分割线================================



最新内容请见作者的GitHub页:http://qaseven.github.io/

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
4047 0
静态分析Smali添加日志
如何动手实现Smali添加日志
116 0
检查HTTP 的 Digest 认证代码示例-JSP
检查HTTP 的 Digest  认证. since http1.1 代码如下所示:(此代码还不完善, RFC2617算法未实现).
743 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4248 0
【软件测试】3、代码检查与Code Review
对于一家技术研发流程完善的技术公司来说,代码审查都是必不可少的一部分。虽然大部分代码审查工作都是研发团队的工程师完成,广义上讲,代码审查也是软件测试的一部分。
789 0
使用 Phan 为你的 PHP 项目保驾护航 - 代码静态扫描
原文:我的个人博客 https://mengkang.net/1356.html 很多时候,最大的优势在某些情况下就会变成最大的劣势。PHP 语法非常灵活,也不用编译。但是在项目比较复杂的时候,可能会导致一些意想不到的 bug。
1579 0
+关注
玄学酱
这个时候,玄酱是不是应该说点什么...
17436
文章
438
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载