JS测试之自写断言

Mar 22, 2017


在JS中写测试往往让我们甚觉苦恼,众多的Test Framework,Test Runner, Test Assertion, Test Mocking, Testing Utilites,我们该如何选择呢?什么的测试需要借助浏览器,什么样的测试直接在后端可以测试? ES6, ES7编写的代码我们如何运行测试,生成测试报告?怎么样获取代码的测试覆盖率?

本系列文章将尝试抽丝剥茧的方式来让我们逐渐接触和了解JS的测试,为我们在JS项目上TDD,BDD扫除障碍。在这之前,让我们先了解几个基本概念: JavaScript, Node.js, V8引擎。

提到Javascript,大家首先想到的是日常使用的浏览器,现代浏览器包含了各种组件,包括渲染引擎、Javascript引擎等,其中Javascript引擎负责解释执行网页中的Javascript代码。作为Web前端最重要的语言之一,Javascript一直是前端工程师的专利。

而Node.js是一个基于Chrome V8引擎的后端JavaScript运行环境,其采用C++语言编写而成。V8引擎是node的心脏,V8采用JIT——即时编译技术,直接将js代码编译成本地平台的机器码。Node.js还提供了很多系统级的API,如文件操作、网络编程等。

Node.js自写测试断言

我们用最简单的方式来实现自己的assertEqual方法,如index.js:

const add = (a, b) => a + b;

const assertEqual = (actual, expected, message) => {
  if(actual != expected) {
    message = (message || "Assertion failed") + ", expect [ " + actual +" ], but get[ " + expected + " ]";
    if (typeof Error !== "undefined") {
      throw new Error(message);
    }
    throw message;
  }
}

assertEqual(add(2,3), 4);

如果你的已经有支持Node.js的环境,可以执行node index.js查看运行结果。程序会抛出异常且打印出错误堆栈。但是此时我们仅仅能测试一种情况就退出了,如果我们希望测试多种情况并返回错误提示结果,可以小小改造下程序:

const add = (a, b) => a + b;

let results = {
  total: 0,
  fail: 0
};

const assertEqual = (actual, expected, message) => {
  results.total += 1;
  if(actual != expected) {
    results.fail += 1;
    message = (message || "Assertion failed") + ", expect [ " + actual +" ], but get[ " + expected + " ]";
    console.log(message);
  }
}

assertEqual(add(2,3), 4);
assertEqual(add(6,7), 13);
assertEqual(add(7,7), 10);

console.log("Total " + results.total + " tests, " + results.fail + " failed, "
        + (results.total - results.fail) + " passed.");

运行后,得到的打印结果就有点意思了:

Assertion failed, expect [ 5 ], but get[ 4 ]
Assertion failed, expect [ 14 ], but get[ 10 ]
Total 3 tests, 2 failed, 1 passed.

浏览器的JS测试

上一段介绍的Node.js写的测试,需要有一个Node.js的环境,在浏览器上我们也能很方便执行我们的javascrip代码。但是需要注意的是浏览器(非Chrome)可能不支持const以及let关键字。

创建math.js:

function add(a, b) {
  return a + b;
}

创建执行测试的index.html文件:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Javascript Test examples</title>
    <script src="math.js"></script>
    <script>
    var results = {
      total: 0,
      fail: 0
    };

    function assertEqual(actual, expected, message) {
      results.total += 1;
      if(actual != expected) {
        results.fail += 1;
        message = (message || "Assertion failed") + ", expect [ " + actual +" ], but get[ " + expected + " ]";
        console.log(message);
      }
    }

    assertEqual(add(2,3), 4);
    assertEqual(add(6,7), 13);
    assertEqual(add(7,7), 10);

    console.log("Total " + results.total + " tests, " + results.fail + " failed, "
            + (results.total - results.fail) + " passed.");
    </script>
</head>
<body>

</body>
</html>

浏览器打开次index.html文件,打开浏览器的Console可以看到测试结果打印。