静态代码工具,实现高质量代码编写

2017-06-19  本文已影响734人  itclanCoder

前言

giphy-downsized.gif
点击链接可收听音频,旧号itclan已暂停使用,可移步新号itclanCoder收听更多内容使用静态代码工具,实现高质量代码编写

对于少量的代码,我们通常能够通过肉眼或者代码编辑器,甚至控制台出现的错误,找出对应有问题的代码行,可以进行排错,但是若是对于大量的代码,光靠肉眼的识别,少则几百行,多则上千行的代码,光靠眼力劲来察觉bug,整个工作量是非常大的,也很难预测,特别是某些库或者产品的迭代开发时,随着代码越来越庞大,根本不适合所谓的眼力劲来找出代码中潜在的错误,那么这时候在运行代码之前,使用代码分析工具进行检测,那就非常友好了,静态分析工具能够发现代码中常见的出错因素和陷阱并进行提示,从而可以避免有bug的代码被执行,使用该工具可以发现代码中语句结束时是否缺分号,使用了未定义的变量,以及语法错误,更为重要一点是,如果你使用了javascript中eval方法将字符串转换js代码来执行,他也会对代码进行安全提示的检查,只要确定这些有潜在风险的代码操作,没有在你的源码中出现,就能够减少程序中Bug,自己写的代码也更加有信心,而在非正规军的团队开发中,也许本身就没有静态代码分析这一环节,很多时候,绝大部分都是以业务为导向的,无论你代码写得有多么low,只要能跑起来,实现了就行,对于代码的质量和潜在的问题并没有过多的在意,自己挖的坑,让别人来填补,这是平时开发当中常有的事,使用这些工具本身就是非硬性的,因人而异,但是我觉得一个强悍的团队的leader,保证各个小伙伴写出更规范,更高效的代码,使用这些代码软技能无论是对人对己,还是对产品都是很有利的,无论别人是否要求,为了自身优质代码的输出,习以为常的应用这些代码软技能也是自我很好的提升,本篇并不涉及什么高大上的内容,可归为工具篇,一起来跟大家分享一下使用静态代码分析工具,实现高质量代码的编写使用心得,让代码写得放心,远离臭虫

JSLint

在线测试代码

在线使用jslint进行代码检查.gif
/*jslint devel:true,nomen:true,white:true*/
/*global Class:false*/
var Accomodation  = Class.create((function(){
      "use strict" // 使用严格模式,在这个函数作用范围内都会生效
      var _isLocked = true,
          publicPropertiesAndMethods = { 
              lock:function(){
                 _isLocked = true;
              },
              unlock:function(){
                 _isLocked = false;
              },
              getIsLocked:function(){
                 return _isLocked;
              },
              initialize:function(){
                 this.unlock();
              }
         };
        return publicPropertiesAndMethods; 
}()));
var House = Accomodation.extend({
      isAlarmed:false,
      alarm:function(){
          this.isAlarmed = true;
          alert("Alarm activated");
      },
      lock:function(){
          Accomodation.prototype.lock.call(this);
          this.alarm();
      }
});

缺点:

这只是线上进行检查,对于非线上的,针对Node.js应用框架有JSlint工具,可以通过终端命令行的方式来运行jsLint版本,使用方法如下:

JSHint

Eslint

使用方法:

小结

JSlint,jsHint,ESlint比较

javascript中的单元测试

上面的静态代码分析工具能够检测出代码中存在的错误,如果想要更进一步的对代码进行分析,那么就需要进行单元测试了,把代码中每个函数都写成一个具有独立的功能单元,这个单元有输入和输出,并执行一个 明确,有文档说明的操作,那么测试也就是这个javascript函数,它要做的是用不同的输入依次执行你写的每个函数,然后检查函数的输出是否符合预期值
如下示例代码

var add  = function(){
    var total = 0,
    len = arguments.length;                    
    for(var index = 0;index<len;index++){
         total+= arguments[index];
    }
    return total;
}
console.log(add(1,2,3,4,5));  //15

控制台输出结果


一个简单的测试函数.png

针对函数的设计单元测试要用不同的输入来执行这个函数,比如说空值,非number数值等进行测试这样能够保证该函数的行为符合预期,而且对于不同的输入组合能够输出正确结果,在有些时候,当我们想要得到某些特殊值的时候,我们还会进行判断,对得出结果进行过滤,筛选,通过对代码中的每个函数进行严格的测试,能够确保代码少出问题
如下代码对结果进行条件判断:

var add  = function(){
    var total = 0,
    len = arguments.length;
    for(var index = 0;index<len;index++){
        total+= arguments[index];
    }
    if(isNaN(total)){
        console.log("请输入正确的number值");
    }else{
       return total;
    }
    /*
    if(typeof total === "number"){
        return total;
    }else{
        console.log("请输入正确的number值");
    }
    */  
}
console.log(add("asdfs"));  // 请输入正确的number值

控制台输出测试输出结果


一个简单的测试函数结果判断.png

javascript单元测试框架

可以手动编写代码挨个的进行单元测试,但是很多时候,已经有现成的测试框架供我们使用

jasmine(茉莉花)使用

上述的框架有兴趣的话,可以依次的进行测试学习的,至于单元测试的框架很多,我觉得你可以通过star数来自行判断,选择最多的那个,也是最流行的那个,使用的人多,文档也是最多的,工作方式都比较类似,都需要三个文件

jasmine单元测试

describe("The add function", function() {
    it("Adds 1 + 2 + 3 together correctly" , function() {
        var output = add(1, 2, 3);
        expect(output).toEqual(6);
    });

    it("Adds negative numbers together correctly", function() {
        var output = add(-1, -2, -3);
        expect(output).toEqual(-6);
    });
});

上面的示例代码中使用jasmine的describle()函数,并通过对该函数将针对add()函数的所有单元测试几种在一个组中,describle()函,第一个参数为描述the add function,用来对这一组测试进行描述,第二个参数为回调函数,每个测试被包装在一个单独的匿名函数当中,每个单元测试都是用jasmine的it方法来定义的,其中同样第一个参数包含一个字符串来对单元测试进行描述,该测试函数还包含了对add()函数的一次调用,最后用jasmine的export()函数对返回值进行检查,expect函数后面跟着toEqual()函数的链式调用,这个函数就是一个匹配器,匹配器是一个jasmine函数,能够检查被测试函数的输出,并与预期的结果进行比较,看两者是否相匹配
测试代码如下所示

<!DOCTYPE>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Jasmine Spec Runner</title>
  <link rel="stylesheet" type="text/css" href="lib/jasmine-1.3.1/jasmine.css">
  <script type="text/javascript" src="lib/jasmine-1.3.1/jasmine.js"></script>
  <script type="text/javascript" src="lib/jasmine-1.3.1/jasmine-html.js"></script>

  <!-- include source files here... -->
  <!-- <script type="text/javascript" src="src/Player.js"></script>
  <script type="text/javascript" src="src/Song.js"></script> -->
  <script type="text/javascript" src="spec/add.js"></script>
  <script type="text/javascript" src="spec/add-spec.js"></script>

  <!-- include spec files here... -->
  <!-- <script type="text/javascript" src="spec/SpecHelper.js"></script>
  <script type="text/javascript" src="spec/PlayerSpec.js"></script> -->
 

  <script type="text/javascript">
    (function() {
      var jasmineEnv = jasmine.getEnv();
      jasmineEnv.updateInterval = 1000;

      var htmlReporter = new jasmine.HtmlReporter();

      jasmineEnv.addReporter(htmlReporter);

      jasmineEnv.specFilter = function(spec) {
        return htmlReporter.specFilter(spec);
      };

      var currentWindowOnload = window.onload;

      window.onload = function() {
        if (currentWindowOnload) {
          currentWindowOnload();
        }
        execJasmine();
      };

      function execJasmine() {
        jasmineEnv.execute();
      }

    })();
  </script>
</head>
<body>
</body>
</html>

这里使用的是jasmine的1.3.1版本的,按照如上gif操作找到对应的版本进行下载即可,找到一个SpecRunner.html的示例文件,直接打开即可,把你自己要测试的源码xxx.js文件和测试套件放在spec目录里面,在html页面中直接引入即可,在浏览器中打开html文件即可,会自动的运行这些单元测试,然后再浏览器上输出结果,从浏览器的结果中显示出可以看出,对于给定的两个单元测试结果都符合预期,浏览器中输出结果为绿色的,表示的是正确的


jasmine测试.gif
describe("The add function", function() {
    // 第一个单元测试
    it("Adds 1 + 2 + 3 together correctly", function() {
        var output = add(1, 2, 3);
        expect(output).toEqual(6);
    });
    // 第二个单元测试
    it("Adds negative numbers together correctly", function() {
        var output = add(-1, -2, -3);
        expect(output).toEqual(-6);
    });
    // 第三个单元测试
    it("Returns 0 if no inputs are provided", function() {
        var output = add();
        expect(output).toEqual(0);
    });
    // 第四个单元测试
    it("Adds only numeric inputs together", function() {
        var output = add(1, "1", 2, "2", 3, "3");
        expect(output).toEqual(6);
    });
});

将上面的代码单独为一个js脚本文件引入到SpecRunner.html中去,在浏览器打开


针对代码add()函数测试.gif

对于前三个单元测试给出的条件与结果符合,测试成功,而最后一个单元测试不通过,浏览器标识为红色,从浏览上jasmine版本下方的四个圆点点,其实就是对应的每个单元测试的结果,如果为绿色,那么表示成功,反之失败,会用红色的X表示,关于失败的具体原因,点击失败处的链接会给出提示,我们预期单元测试的结果函数输出应该是6但是实际输却为112233,其实它输出是一个字符串(其实不测试也很好理解一个数字加上一个字符串肯定是字符串,在没有对数值进行转换类型的话,肯定是字符串)

小结
上述例子很简单,其实不用单元测试,自己也能够进行判断,只是为了作为单元测试演示jasmine是怎样进行单元测试的,单元测试暴露出代码中存在的一些潜在的问题,这些问题可能导致在真实网页中运行时发生错误,所以我们要回到自己写的源代码中进行修正,加条件判断进行过滤筛选,检查输入的参数是否为数字,如果是的话,那么输出正确的值,不是的话,给出一个友好的用户提示,至于一些条件则具体根据实际情况的业务走,当然也这其中也包括编码经验,总之,使用单元测试能够很好的保证代码的健壮性,在复杂的业务的逻辑处理中,使用单元测试还是很有必要的,使用单元测试的过程其实就是排坑扫雷的过程,如上上代码条件代码所示
注意

两款棒棒的在线测试服务

基于虚拟机的在线测试服务,通过这些服务可以同时在不同的web浏览器和操作系统上自动的运行单元测试,并获取测试结果,这些服务是对手动运行测试的一种替代,都是免费开源的

jasmine框架中其他的匹配器

至于更多的jasmine匹配器可以参考官方文档,当然自己也是可以自定义编写定制版的匹配函数的

总结:
本篇从刚开始介绍了在代码提交前三种校验工具,分别是jslint,jshint,Eslint主要是用于发现代码中那些已知的错误(语法检测,规范,潜在的风险检查),确保项目遵循的代码规范,其中jslnt比较严格,连代码格式什么空格也不放过,缺点也很明显,文档记录规则不全,而jsHint相对比较好,不拘于代码风格格式等问题,较为自由,文档说明都很全,个人也是比较推荐这种,而Eslint更是前两者的升级版,最为强大,功能齐全,中英文档也齐全,对Es6``nodejs等支持度高,唯一可能觉得麻烦的就是配置比较唬人,如果使用过一些前端自动化构建工具的话,那么会比较熟悉,那些webpack等打包工具其实内部也集成了这些代码校验工具,或者也可以单独在代码编辑器(比如sublime)中安装这些代码校验的工具,具体三种校验工具的简单使用可见上文,紧接着就是大篇幅的进行 javascript中的单元测试,介绍了Qunit,Mocha,jasmine,并且着重的介绍了如何使用jasmine框架进行单元的测试,自己编写的源码独立文件,与要对它进行测试单元的文件,放入到SpecRunner.html文件当中,依赖jasmine库对应版本的css和js,在浏览器上打开SpecRunner.html文件就能看到对应测试单元的结果,具体一些细节操作见上面,又介绍了两款比较好的在线测试服务的工具,Browserstack,Sauce Labs,以及介绍了jasmine框架中其他的匹配器的使用,其实这种代码检测工具很多,之前呢,我对于单元测试非常不解,觉得很是神秘,遥不可及,单元测试更多的是后端小伙伴进行业务逻辑处理测试就很常见了的,而现在前端的业务也越来越复杂,同样也存在在着复杂的交互逻辑处理,我觉得同样也是需要单元测试的,可能平时更多是在实现UI层比较多,对于这种频繁使用单元测试确实很少用,但是习惯使用代码检验工具,和单元测试无疑是一个好的习惯,能够保证生产优质的代码,这也是保证产品的迭代开发质量,为什么bug修的没完没了,我想,这也是有一定的原因的,其实,这些工具的软技能,细心的小伙伴发现,在一些招聘需求上,也是屡见不鲜的,也是自我进阶的一部分

以下是本篇提点概要

更多内容尽在微信itclancoder公众号.jpg
扫一扫二维码,关注微信itclanCoder公众号,一个具有情怀的代码男,听声音,温暖你的耳朵,阅读文字,直戳你内心的心灵
上一篇 下一篇

猜你喜欢

热点阅读