课堂练习(四)

ESLint

实验目的

  1. 学会使用 ESLint 进行代码检查。

操作步骤

(1)进入demos/eslint-demo目录,安装 ESLint。

$ cd demos/eslint-demo
$ npm install eslint --save-dev

(2)通常,我们会使用别人已经写好的代码检查规则,这里使用的是 Airbnb 公司的规则。所以,还要安装 ESLint 这个规则模块。

$ npm install eslint-plugin-import eslint-config-airbnb-base --save-dev

上面代码中,eslint-plugin-import是运行这个规则集必须的,所以也要一起安装。

(3)ESLint 的配置文件是.eslintrc.json,放置在项目的根目录下面。新建这个文件,在里面指定使用 Airbnb 的规则。

{
  "extends": "airbnb-base"
}

(4)打开项目的package.json,在scripts字段里面添加三个脚本。

{
  // ...
  "scripts" : {
    "test": "echo "Error: no test specified" && exit 1",
    "lint": "eslint **/*.js",
    "lint-html": "eslint **/*.js -f html -o ./reports/lint-results.html",
    "lint-fix": "eslint --fix **/*.js"
  },
  // ...
}

除了原有的test脚本,上面代码新定义了三个脚本,它们的作用如下。

  • lint:检查所有js文件的代码
  • lint-html:将检查结果写入一个网页文件./reports/lint-results.html
  • lint-fix:自动修正某些不规范的代码

(5)运行静态检查命令。

$ npm run lint

  1:5  error    Unexpected var, use let or const instead  no-var
  2:5  warning  Unexpected console statement              no-console

✖ 2 problems (1 error, 1 warning)

正常情况下,该命令会从index.js脚本里面,检查出来两个错误:一个是不应该使用var命令,另一个是不应该在生产环境使用console.log方法。

(6)修正错误。

$ npm run lint-fix

运行上面的命令以后,再查看index.js,可以看到var x = 1;被自动改成了const x = 1;。这样就消除了一个错误,但是还留下一个错误。

(7)修改规则。

由于我们想要允许使用console.log方法,因此可以修改.eslintrc.json,改变no-console规则。请将.eslintrc.json改成下面的样子。

{
  "extends": "airbnb-base",

  "rules": {
    "no-console": "off"
  }
}

再运行npm run lint,就不会报错了。

$ npm run lint

Mocha

实验目的

  1. 学会使用 Mocha 进行单元测试。

操作步骤

(1) 进入demos/mocha-demo目录,安装 Mocha 和 Chai。

$ cd demos/mocha-demo
$ npm install -D mocha
$ npm install -D chai

(2)打开add.js文件,查看源码,我们要测试的就是这个脚本。

function add(x, y) {
  return x + y;
}

module.exports = add;

(3)编写一个测试脚本add.test.js

var add = require("./add.js");
var expect = require("chai").expect;

describe("加法函数的测试", function() {
  it("1 加 1 应该等于 2", function() {
    expect(add(1, 1)).to.be.equal(2);
  });
});

测试脚本与所要测试的源码脚本同名,但是后缀名为.test.js(表示测试)或者.spec.js(表示规格)。比如,add.js的测试脚本名字就是add.test.js

测试脚本里面应该包括一个或多个describe块,每个describe块应该包括一个或多个it块。

describe块称为"测试套件"(test suite),表示一组相关的测试。它是一个函数,第一个参数是测试套件的名称("加法函数的测试"),第二个参数是一个实际执行的函数。

it块称为"测试用例"(test case),表示一个单独的测试,是测试的最小单位。它也是一个函数,第一个参数是测试用例的名称("1 加 1 应该等于 2"),第二个参数是一个实际执行的函数。

上面的测试脚本里面,有一句断言。

expect(add(1, 1)).to.be.equal(2);

所谓"断言",就是判断源码的实际执行结果与预期结果是否一致,如果不一致就抛出一个错误。上面这句断言的意思是,调用add(1, 1),结果应该等于2

所有的测试用例(it块)都应该含有一句或多句的断言。它是编写测试用例的关键。断言功能由断言库来实现,Mocha本身不带断言库,所以必须先引入断言库。

var expect = require("chai").expect;

断言库有很多种,Mocha并不限制使用哪一种。上面代码引入的断言库是chai,并且指定使用它的expect断言风格。

(4)打开package.json文件,改写scripts字段的test脚本。

"scripts": {
  "test": "echo "Error: no test specified" && exit 1"
},

// 改成

"scripts": {
  "test": "mocha *.test.js"
},

(5)命令行下,执行下面的命令,运行测试用例。

$ npm test

正常情况下,命令行会有提示,表示测试用例已经通过了。

练习

  1. 请在add.test.js里面添加一个测试用例,测试3加上-3add函数应该返回0

Nightmare

实验目的

  1. 学会使用 Nightmare 完成功能测试。

操作步骤

(1)进入./demos/nightmare-demo目录,安装依赖。

$ cd demos/nightmare-demo

# Linux & Mac
$ env ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/ npm install

# Windows
$ set ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/
$ npm install

注意,Nightmare 会先安装 Electron,而 Electron 的安装需要下载境外的包,有时会连不上,导致安装失败。所以,这里先设置了环境变量,指定使用国内的 Electron 源,然后才执行安装命令。

(2)查看一下浏览器自动化脚本taobao.test.js

var Nightmare = require("nightmare");
var nightmare = Nightmare({ show: true });

上面代码表示新建一个 Nightmare 实例,并且运行功能中,自动打开浏览器窗口。

nightmare
  .goto("https://www.taobao.com/")
  .type("#q", "电视机")
  .click("form[action*="/search"] [type=submit]")
  .wait("#spulist-grid")
  .evaluate(function () {
    return document.querySelector("#spulist-grid .grid-item .info-cont")
      .textContent.trim();
  })
  .end()

上面代码表示,打开淘宝首页,在搜索框键入电视机,点击”搜索“按钮,等待#spulist-grid元素出现,在页面内注入(evaluate)代码,将执行结果返回。

  .then(function (result) {
    console.log(result);
  })
  .catch(function (error) {
    console.error("Search failed:", error);
  });

Nightmare 会返回一个 Promise 对象,then方法指定操作成功的回调函数,catch方法指定操作失败的回调函数。

(3)命令行下运行这个示例脚本。

$ node taobao.test.js

正常情况下,运行结束后,命令行会显示淘宝”电视机“搜索结果的第一项。

(4)浏览器打开index.html文件,这是 React 练习时做过的一个例子,点击Hello World,标题会变成Hello Clicked。我们就要编写测试脚本,测试这个功能。

(5)打开测试脚本test.js

var Nightmare = require("nightmare");
var expect = require("chai").expect;
var fork = require("child_process").fork;

describe("test index.html", function() {
  var child;

  before(function (done) {
    child = fork("./server.js");
    child.on("message", function (msg) {
      if (msg === "listening") {
        done();
      }
    });
  });

  after(function () {
    child.kill();
  });

上面代码中,beforeafter是 Mocha 提供的两个钩子方法,分别在所有测试开始前和结束后运行。这里,我们在before方法里面,新建一个子进程,用来启动 HTTP 服务器;测试结束后,再杀掉这个子进程。

注意,before方法的参数是一个函数,它接受done作为参数。done是 Mocha 提供的一个函数,用来表示异步操作完成。如果不调用done,Mocha 就会认为异步操作没有结束,一直停在这一步,不往下执行,从而导致超时错误。

子进程脚本server.js的代码非常简单,只有四行。

var httpServer = require("http-server");
var server = httpServer.createServer();
server.listen(8080);
process.send("listening");

上面代码中,我们在8080端口启动 HTTP 服务器,然后向父进程发消息,表示启动完成。

(6)真正的自动化测试脚本如下。

  it("点击后标题改变", function(done) {
    var nightmare = Nightmare({ show: true });
    nightmare
      .goto("http://127.0.0.1:8080/index.html")
      .click("h1")
      .wait(1000)
      .evaluate(function () {
        return document.querySelector("h1").textContent;
      })
      .end()
      .then(function(text) {
        expect(text).to.equal("Hello Clicked");
        done();
      })
  });

上面代码中,首先打开网页,点击h1元素,然后等待 1 秒钟,注入脚本获取h1元素的文本内容。接着,在then方法里面,做一个断言,判断获取的文本是否正确。

(7)运行这个测试脚本。

$ npm test

如果一切正常,命令行下会显示测试通过。

练习

  1. 请写一个测试用例,验证<h1>的字体颜色是红色。(提示:可以使用Window.getComputedStyle()方法,获取元素的最终样式。)

Travis CI

实验目的

  1. 了解持续集成的做法,学会使用 Travis CI。

操作步骤

(1)注册 Github 的账户。如果你已经注册过,跳过这一步。

(2)访问这个代码库github.com/ruanyf/travis-ci-demo,点击右上角的Fork按钮,将它克隆到你自己的空间里面。

(3)将你fork的代码库,克隆到本地。注意,要将下面网址之中的[your_username]改成你的 Github 用户名。

// Linux & Mac
$ git clone git@github.com:[your_username]/travis-ci-demo.git

// Windows
$ git clone https://github.com:[your_username]/travis-ci-demo

(4)使用你的 Github 账户,登录 Travis CI 的首页。然后,访问 Profile 页面,选定travis-ci-demo代码库运行自动构建。

(5)回到命令行,进入你本地的travis-ci-demo目录,切换到demo01分支。

$ cd travis-ci-demo
$ git checkout demo01

项目根目录下面有一个.travis.yml文件,这是 Travis CI 的配置文件。如果没有这个文件,就不会触发 Travis CI 的自动构建。打开看一下。

language: node_js
node_js:
  - "node"

上面代码指定,使用 Node 完成构建,版本是最新的稳定版。

指定 Node 的版本号也是可以的。

language: node_js
node_js:
  - "4.1"

上面代码指定使用 Node 4.1 版。

(6)Travis CI 默认依次执行以下九个脚本。

  • before_install
  • install
  • before_script
  • script
  • after_success 或者 after_failure
  • after_script
  • before_deploy(可选)
  • deploy(可选)
  • after_deploy(可选)

用户需要用到哪个脚本,就需要提供该脚本的内容。

对于 Node 项目,以下两个脚本有默认值,可以不用自己设定。

"install": "npm install",
"script": "npm test"

(7)打开当前分支的package.json,可以发现它的test脚本是一个lint命令。

"scripts": {
  "test": "jshint hello.js"
},

(8)在项目根目录下,新建一个新文件NewUser.txt,内容是你的用户名。提交这个文件,就会触发 Travis CI 的自动构建。

$ git add -A
$ git commit -m "Testing Travis CI"
$ git push

(9)等到 Travis CI 完成自动构建,到页面上检查构建结果。

(10)切换到demo02分支,打开package.json,可以看到test脚本,现在需要完成两步操作了。

  "scripts": {
    "lint": "jshint hello.js hello.test.js",
    "test": "npm run lint && mocha hello.test.js"
  },

(11)重复上面第 8 步和第 9 步。

练习

  1. 修改hello.js,让其输出Hello Node。并修改测试用例hello.test.js,使之能够通过 Travis CI 的自动构建。
文章导航