【大前端攻城狮之路·二】Javascript&QA⼯程师

  今天给大家分享的主题的是Javascript&QA⼯程师。看到这个主题,可能有人问:前端开发完就OK了,剩下的丢给测试就行,哪里还需要关心这些?但事实上呢,测试是前端开发非常重要的环节,也是迈向高级前端工程师的必经之路!

  本文主要分为一下四个部分:

  · 单元测试

  · 性能测试

  · 功能测试

  · 安全测试

 

  一. 单元测试

  单元测试(unit testing),是指对程序中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

  在一种传统的结构化编程语言中,比如C,要进行测试的单元一般是函数或子过程。在像C++这样的面向对象的语言中, 要进行测试的基本单元是类。对Ada语言来说,开发人员可以选择是在独立的过程和函数,还是在Ada包的级别上进行单元测试。单元测试的原则同样被扩展到第四代语言(4GL)的开发中,在这里基本单元被典型地划分为一个菜单或显示界面。

  经常与单元测试联系起来的另外一些开发活动包括代码走读(Code review),静态分析(Static analysis)和动态分析(Dynamic analysis)。静态分析就是对软件的源代码进行研读,查找错误或收集一些度量数据,并不需要对代码进行编译和执行。动态分析就是通过观察软件运行时的动作,来提供执行跟踪,时间分析,以及测试覆盖度方面的信息。

  对于前端来说就是一个函数。

  (1)前端为什么要做单元测试

  我认为主要原因为一下5点:

  1.正确性

  测试可以验证代码的正确性,在上线前做到心里有底。

  2.自动化

  当然手工也可以测试,通过console可以打印出内部信息,但是这是一次性的事情,下次测试还需要从头来过,效率不能得到保证。通过编写测试用例,可以做到一次编写,多次运行

  3.解释性

  测试用例用于测试接口、模块的重要性,那么在测试用例中就会涉及如何使用这些API。其他开发人员如果要使用这些API,那阅读测试用例是一种很好地途径,有时比文档说明更清晰。

  4.驱动开发,指导设计

    代码被测试的前提是代码本身的可测试性,那么要保证代码的可测试性,就需要在开发中注意API的设计,TDD将测试前移就是起到这么一个作用。

  5.保证重构

  互联网行业产品迭代速度很快,迭代后必然存在代码重构的过程,那怎么才能保证重构后代码的质量呢?有测试用例做后盾,就可以大胆的进行重构。

 

   (2)单元测试原则&测试风格

  单元测试的目的是为了让开发者明确的知道代码结果,原则有三点:单一职责,接口抽象,层次分离。而单元测试必备的东西是断言库,断言库是保证最小单元能否正常运行的检测方法。

  测试风格:测试驱动开发(Test-Driven Development,TDD)、(BehaviorDriven Development,BDD)行为驱动开发均是敏捷开发方法论。

  TDD关注所有的功能是否被实现(每一个功能都必须有对应的测试用例),suite配合test利用assert('tobi' == user.name);

  BDD关注整体行为是否符合整体预期,编写的每一行代码都有目的提供一个全面的测试用例集。expect/should,describe配合it利用自然语言expect(1).toEqual(fn())执行结果。

  

  (3)单元测试框架

  单元测试的主要框架

  

 

  (3)单元测试运行流程

  

  每一个测试用例组通过 describe进行设置

  1.before单个测试用例(it)开始前
  2.beforeEach每一个测试用例开始前
  3.it定义测试用例 并利用断言库进行
  设置chai如:expect(x).to.equal(true);异步mocha。
  4.以上专业术语叫mock

  

  (4)自动化单元测试 karma

  Karma是Testacular的新名字,在2012年google开源了Testacular,2013年Testacular改名为Karma。Karma是一个让人感到非常神秘的名字,表示佛教中的缘分。这个名字和LOL中的扇子妈同名 - -,比较佛系。

  On the AngularJS team, we rely on testing and we always seek better tools to make our life easier. That‘s why we created Karma - a test runner that fits all our needs.

  Karma是一个基于Node.js的JavaScript测试执行过程管理工具(Test Runner)。该工具可用于测试所有主流Web浏览器,也可集成到CI(Continuous integration)工具,也可和其他代码编辑器一起使用。

  可以生成报告和单测覆盖率检查。

  Karma.conf.js

  

// Karma configuration
// Generated on Thu Mar 22 2018 20:30:24 GMT+0800 (CST)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      './unit/**/*.js',
      './unit/**/*.spec.js'
    ],


    // list of files / patterns to exclude
    exclude: [
    ],
    //指定对应的JS文件 去执行代码的覆盖率
    preprocessors: {
      './unit/**/*.js': ['coverage']
    },


    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress', 'coverage'],
    coverageReporter: {
      type : 'html',
      dir : 'coverage/'
    },
    // web server port
    port: 9876,


    // enable / disable colors in the output (reporters and logs)
    colors: true,


    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,


    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,


    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['PhantomJS'],


    //黑窗小独立的运行环境
    singleRun: true,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  })
}

  单元测试demo:

// index.js
window.test = function (num) {
    if(num == 1){
        return 1
    }else{
        return num + 1;
    }
}

// index.spec.js
describe("测试基本的函数API",function(){
    it("+1函数的应用",function(){
        expect(window.test(1)).toBe(1);
    });
});

  

  . 功能测试

  功能测试主要是e2e测试。端到端测试是一种用于测试应用程序的流程是否从开始到结束执行的方法。执行端到端测试的目的是识别系统依赖性,并确保在各种系统组件和系统之间传递正确的信息。

  通俗点说,就是把整个系统当作一个黑盒,测试人员模拟真实用户在浏览器中操作UI来测试。

  常见的几种e2e测试框架,今天主要讲selenium,因为phantomjs,无头浏览器不在维护,所以rize与其形成犄角之势。可以在终端进行端对端测试。
  Nightwatch是一个功能非常强大,配置巨复杂的端对端测试框架,vue-cli就是用的night watch。

  (1)Selenium

  Selenium 是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。这个工具的主要功能包括:测试与浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能——创建回归测试检验软件功能和用户需求。支持自动录制动作和自动生成 .Net、Java、Perl等不同语言的测试脚本。

  Selenium是ThoughtWorks公司的一个强大的开源Web功能测试工具系列,采用Javascript来管理整个测试过程,包括读入测试套件、执行测试和记录测试结果。它采用Javascript单元测试工具JSUnit为核心,模拟真实用户操作,包括浏览页面、点击链接、输入文字、提交表单、触发鼠标事件等等,并且能够对页面结果进行种种验证。也就是说,只要在测试用例中把预期的用户行为与结果都描述出来,我们就得到了一个可以自动化运行的功能测试套件。(Selenium的核心是Javascript写的,他和浏览器进行通信,把测试用例的信息发送给浏览器执行,从而达到自动化测试的目的。)

  我这里是用火狐测试的,需要先下载一个driver,geckdriver。然后nmp i selenium-webdriver --save;

  这里用代码控制打开火狐,找到name为‘wd’的元素并键入‘node’,然后按会车,最后退出火狐。代码如下:

  

const {Builder, By, Key, until} = require('selenium-webdriver');

(async function example() {
  let driver = await new Builder().forBrowser('firefox').build();
  try {
    await driver.get('https://www.baidu.com/');
    await driver.findElement(By.name('wd')).sendKeys('node', Key.RETURN);
    await driver.wait(until.titleIs('node_百度搜索'), 1000);
  } finally {
    await driver.quit();
  }
})();

  

  使用rize框架,写法更为简洁:

const Rize = require('rize');
const rize = new Rize();
rize
  .goto('https://github.com/')
  .type('input.header-search-input', 'node')
  .press('Enter')
  .waitForNavigation()
  .assertSee('Node.js')
  .end();

  

  . UI测试

  前端,作为一个传统的页面仔,自己写的样式,心里得有点B数,不能老等着人家UI走查,说你哪哪差几像素。

  这里给大家介绍一个神奇的框架 BackstopJs。

  BackstopJS automates visual regression testing of your responsive web UI by comparing DOM screenshots over time.

  

    

  Backstop配置文件,backstop.json。

  

{
  "id": "天骄",
  "viewports": [
    {
      "label": "phone",
      "width": 375,
      "height": 667
    },
    {
      "label": "tablet",
      "width": 1024,
      "height": 768
    }
  ],
  "onBeforeScript": "chromy/onBefore.js",
  "onReadyScript": "chromy/onReady.js",
  "scenarios": [
    {
      "label": "qq",
      "cookiePath": "backstop_data/engine_scripts/cookies.json",
      "url": "http://map.qq.com/m/", // 这里是待测试的UI界面URL
      "referenceUrl": "",
      "readyEvent": "",
      "readySelector": "",
      "delay": 0,
      "hideSelectors": [],
      "removeSelectors": [],
      "hoverSelector": "",
      "clickSelector": "",
      "postInteractionWait": "",
      "selectors": [],
      "selectorExpansion": true,
      "misMatchThreshold" : 0.1,
      "requireSameDimensions": true
    }
  ],
  "paths": {
    "bitmaps_reference": "backstop_data/bitmaps_reference",
    "bitmaps_test": "backstop_data/bitmaps_test", // 这里放UI的设计图
    "engine_scripts": "backstop_data/engine_scripts",
    "html_report": "backstop_data/html_report",
    "ci_report": "backstop_data/ci_report"
  },
  "report": ["browser"], // 报表的方式,这里是浏览器
  "engine": "chrome",
  "engineFlags": [],
  "asyncCaptureLimit": 5,
  "asyncCompareLimit": 50,
  "debug": false,
  "debugWindow": false
}

  测试的结果页面非常友好,她会把你的界面和UI图的差异标注出来:

  

 

  . 性能测试   

  下面说下性能测试。

  前端性能主要分为两部分,第一是页面性能,如秒开率等,第二是代码性能。今天主要说代码性能。

  今天主要讲代码性能测试 benchmarkjs,A benchmarking library that supports high-resolution timers & returns statistically significant results

  字面意思理解,支持高分辨率计时器的基准测试库,并返回统计上显著的结果。

  面向切面编程AOP无侵入式统计。Benchmark基准测试方法,它并不是简单地统计 执行多少次测试代码后对比时间,它对测试有着 严密的抽样过程。执行多少次取决于采样到的数 据能否完成统计。根据统计次数计算方差。

话不多说,直接看代码:

  

var Benchmark = require('benchmark');
var suite = new Benchmark.Suite;
suite.add('使用正则匹配字符串', function() {
    /o/.test('Hello World!');
  })
  .add('使用字符串查找', function() {
    'Hello World!'.indexOf('o') > -1;
  })
  //添加监听
  .on('cycle', function(event) {
    console.log(String(event.target));
  })
  //执行结果
  .on('complete', function() {
    console.log('更快的是-》 ' + this.filter('fastest').map('name'));
  })
  // run async
  .run({ 'async': true });

  执行结果如下:

  

  

  下面说下 压力测试

  对网络接口做压力测试需要检查的几个常用指标有吞吐率、响应时间和并发数,这些指标反映了服务器并发处理能力。

  PV网站当日访问人数 UV独立访问人数。PV每天几十万甚至上百万就 需要考虑压力测试。换算公式QPS=PV/t ps:1000000/ 10*60*60=27.7(100万请求集中在10个小时,服务器每秒处理27.7 个业务请求);

  ab -c 100 -n 100 http://localhost:8001 每秒持续发出28个请求。
 Request per second 表示服务器每秒处理请求数 即为QPS
 。Failed requests 表示此次请求失败的请求数 理论上压测值越大增加
 Connection Times 连接时间,它包括客户端向服务器端建立连接、服 务器端处理请求、等待报文响应的过程。

  常用的压力测试工具是ab、siege、http_load。

  . 安全测试

  常见的安全攻击有三种:XSS, CSRF, SQL注入。

  (1)XSS 跨站点脚本攻击

  在input中输入未闭合标签,测试是否会执行。

><scrīpt>alert(document.cookie)</scrīpt>

  (2)CSRF,Sql注入。

 

  Sql注入。 ' or 1=1- -

 

  (3)Csrf跨站请求伪造
  这是一个cookies漏洞(身份验证),用户访问了危险网站B后,B会访问偷偷的让用户访问正规网站A。正规网站对身份进行校验后(通过cookies)认为这是同一个用户,则进行操作
目前没找到什么好的测试方法。

 

  总结:前段时间很多前端名人的博客网站都被攻击了,很多人吐槽前端天花板低,所以学习一门后台语言对我们前端开发人员对思维培养至关重要。而是否能写好单测非常重要。这也是我们迈向高级前端工程师的必经之路。

  最后我想说一句话:不懂测试的UI不是好前端;不懂后台的产品不是好前端。前端路漫漫,吾将上下而求索。

 

posted @ 2018-09-04 11:35  TJYoung  阅读(829)  评论(0编辑  收藏  举报