测试驱动javascript开发 -- 2.单元测试一例:学习断言、测试用例函数的编写

简介:   本篇我们将通过对Date.strftime编写单元测试的例子,学会断言、测试用例函数的相关知识。   首先我们先来看Date.strftime的实现代码。 Date.prototype.strftime = (function () {   function strftime(form...

  本篇我们将通过对Date.strftime编写单元测试的例子,学会断言、测试用例函数的相关知识。

  首先我们先来看Date.strftime的实现代码。

Date.prototype.strftime = (function () {
  function strftime(format) {
    var date = this;
    return (format + "").replace(/%([a-zA-Z])/g,
      function (m, f) {
        var formatter = Date.formats && Date.formats[f];
        if (typeof formatter == "function") {
          return formatter.call(Date.formats, date);
        } else if (typeof formatter == "string") {
          return date.strftime(formatter);
        }
        return f;
      });
  }
  // 内部帮助函数
  function zeroPad(num) {
    return (+num < 10 ? "0" : "") + num;
  }
  Date.formats = {
    // Formatting 方法
    d: function (date) {
      return zeroPad(date.getDate());
    },
    m: function (date) {
      return zeroPad(date.getMonth() + 1);
    },
    y: function (date) {
      return zeroPad(date.getYear() % 100);
    },
    Y: function (date) {
      return date.getFullYear();
    },
    // Format 速记方式
    F: "%Y-%m-%d",
    D: "%m/%d/%y"
  };
  return strftime;
}());

  Date.prototype.strftime函数整体是一个即时匿名函数,该函数会自动执行,把strftime函数作为结果返回。strftime()通过正则表的式判断格式化标示符,返回正确的结果。 zeroPad()在1-9的数据前加0 。Date.formats 对象提供一系列辅助方法,用来处理时间。

  如果代码有哪里看不懂可以给我留言,我会尽量讲解。

 

  断言

  单元测试的核心是断言,通过它的自动运行来比较开发者对于系统的预期结果是否和执行结果一致。两者一致则说明我们的系统一切正常,否则就存在问题,需要我们进一步确认。我们先来看一个简单的断言函数:

function assert(message, expr) {
  if (!expr) {
    throw new Error(message);
  }
  assert.count++;
  return true;
}
assert.count = 0;

  上面的函数只是简单的验证第二个参数是否是真值(除了false, null, undefined, 0, "", 和 NaN这些值之外的都可以)。断言成功,assert.count会加1,失败则抛出异常。

  我们可以使用他来测试strftime() 方法。

var date = new Date(2009, 9, 2);
try {
  assert("%Y should return full year", date.strftime("%Y") === "2009");
  assert("%m should return month", date.strftime("%m") === "10");
  assert("%d should return date", date.strftime("%d") === "02");
  assert("%y should return year as two digits", date.strftime("%y") === "09");
  assert("%F should act as %Y-%m-%d", date.strftime("%F") === "2009-10-02");
  console.log(assert.count + " tests OK");
} catch (e) {
  console.log("Test failed: " + e.message);
}

  在自动化测试中,我们经常使用绿色代表成功,红色代表失败。我们可以创建一个output方法输出不同颜色的信息条,代替console.log的功能。

function output(text, color) {
  var p = document.createElement("p");
  p.innerHTML = text;
  p.style.color = color;
  document.body.appendChild(p);
}
// 可以用它来代替上面断言例子中的 console.log
output(assert.count + " tests OK", "#0c0");
// 失败的时候使用下面的方法:
output("Test failed: " + e.message, "#c00");

 

  测试用例函数

  在创建断言函数之后,我们需要创建测试用例函数,以便把断言组织起来。测试用例里面包含很多子的测试方法,每个测试方法针对被测对象的一部分行为进行测试。下面我们看一个简单的测试用例函数的实现,其中name是测试用例的名称,tests是一组测试方法,其中每个测试方法以‘test’开头。

function testCase(name, tests) {
  assert.count = 0;
  var successful = 0;
  var testCount = 0;
  
for (var test in tests) {     if (!/^test/.test(test)) {       continue;     }
    testCount
++;
    
try {       tests[test]();       output(test, "#0c0");       successful++;     } catch (e) {       output(test + " failed: " + e.message, "#c00");     }   }
  
var color = successful == testCount ? "#0c0" : "#c00";   output("<strong>" + testCount + " tests, " + (testCount - successful) + " failures</strong>", color); }

  下面我们使用上面的方法测试strftime()。

var date = new Date(2009, 9, 2);
testCase("strftime test", {
  "test format specifier %Y": function () {
    assert("%Y should return full year", date.strftime("%Y") === "2009");
  },
  "test format specifier %m": function () {
    assert("%m should return month", date.strftime("%m") === "10");
  },
  "test format specifier %d": function () {
    assert("%d should return date", date.strftime("%d") === "02");
  },
  "test format specifier %y": function () {
    assert("%y should return year as two digits", date.strftime("%y") === "09");
  },
  "test format shorthand %F": function () {
    assert("%F should act as %Y-%m-%d", date.strftime("%F") === "2009-10-02");
  }
});

  这组测试方法针对strftime()不同功能点进行测试,组合起来实现了对其全部功能的测试,最后把测试结果展现给用户。可以说效果还是相当不错的。

  Setup 和 Teardown

  接下来我们介绍setup()和teardown()方法的实现。这两个方法分别在tests执行之前和之后运行,setup()可以用来初始化测试条件,teardown()可以用来销毁相关条件。下面我们完善之前的testCase()方法,添加对setup和teardown()的支持。

function testCase(name, tests) {
  assert.count = 0;
  var successful = 0;
  var testCount = 0;
  var hasSetup = typeof tests.setUp == "function";
  var hasTeardown = typeof tests.tearDown == "function";
  for (var test in tests) {
    if (!/^test/.test(test)) {
      continue;
    }
    testCount++;
    try {
      if (hasSetup) {
        tests.setUp();
      }
      tests[test]();
      output(test, "#0c0");
      if (hasTeardown) {
        tests.tearDown();
      }
      successful++;
    } catch (e) {
      output(test + " failed: " + e.message, "#c00");
    }
  }
  var color = successful == testCount ? "#0c0" : "#c00";
  output("<strong>" + testCount + " tests, " + (testCount - successful) + " failures</strong>", color);
}

  下面我们用改进后的testCase()重新测试strftime()方法。

testCase("strftime test", {
  setUp: function () {
    this.date = new Date(2009, 9, 2, 22, 14, 45);
  },
  "test format specifier Y": function () {
    assert("%Y should return full year", this.date.strftime("%Y") == 2009);
  },
  // ...
});

 

  总结

  本文提供的断言和测试用例函数比较简单,相信大家一看就会,其他复杂的测试框架则要相对复杂的多。但是他们在基本原理上没有太大差别,只是代码实现方式不同,再者就是api提供的更多些。本文主要目地在于抛砖引玉,向大家介绍测试框架中相关方法大致的实现方式,以及如何使用测试框架进行单元测试。要想更好的精通单元测试,除了继续加强理论知识的学习、不断的实践之外,还可以看看其他框架的源代码,相信对你定会有比较大的帮助。

目录
相关文章
|
7月前
|
机器学习/深度学习 JavaScript 前端开发
JS进阶教程:递归函数原理与篇例解析
通过对这些代码示例的学习,我们已经了解了递归的原理以及递归在JS中的应用方法。递归虽然有着理论升华,但弄清它的核心思想并不难。举个随手可见的例子,火影鸣人做的影分身,你看到的都是同一个鸣人,但他们的行为却能在全局产生影响,这不就是递归吗?雾里看花,透过其间你或许已经深入了递归的魅力之中。
328 19
|
8月前
|
测试技术 数据库 Python
解释测试中setup和teardown函数的应用。
总结起来,`setup`和 `teardown`函数就像扔宴会的主人,他们保障了宴会的流畅进行。他们是准备环境和清理现场的重要工作人员,他们的工作直接影响着我们的测试效率和质量。我们可以把 `setup`和 `teardown`想象成隐藏在幕后,默默为我们服务的工作者,他们做着我们需要但是往往忽视的工作。所以,下次当你写测试的时候,别忘了给你的 `setup`和 `teardown`留出足够的位置,因为他们的作用可能是你成功的保证。
200 14
|
9月前
|
人工智能 自然语言处理 JavaScript
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
Magnitude是一个基于视觉AI代理的开源端到端测试框架,通过自然语言构建测试用例,结合推理代理和视觉代理实现智能化的Web应用测试,支持本地运行和CI/CD集成。
1276 15
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
|
9月前
|
JavaScript
JS实现多条件搜索函数
JS封装的多条件搜索
|
11月前
|
JavaScript 前端开发
JavaWeb JavaScript ③ JS的流程控制和函数
通过本文的详细介绍,您可以深入理解JavaScript的流程控制和函数的使用,进而编写出高效、可维护的代码。
261 32
|
前端开发 JavaScript 测试技术
使用ChatGPT生成登录产品代码的测试用例和测试脚本
使用ChatGPT生成登录产品代码的测试用例和测试脚本
372 35
|
数据挖掘 测试技术 项目管理
2025年测试用例管理看这一篇就够了 ----Codes 开源免费、全面的测试管理解决方案
Codes 是国内首款重新定义 SaaS 模式的开源项目管理平台,支持云端认证、本地部署、全部功能开放,并且对 30 人以下团队免费。它通过整合迭代、看板、度量和自动化等功能,简化测试协同工作,使敏捷测试更易于实施。并提供低成本的敏捷测试解决方案,如同步在线离线测试用例、流程化管理缺陷、低代码接口自动化测试和 CI/CD,以及基于迭代的测试管理和测试用时的成本计算等,践行敏捷测试。
2025年测试用例管理看这一篇就够了 ----Codes 开源免费、全面的测试管理解决方案
|
前端开发 JavaScript Java
通过ChatGPT生成测试用例和测试脚本(2)
通过ChatGPT生成测试用例和测试脚本
356 21
|
数据采集 人工智能 自然语言处理
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
Midscene.js 是一款基于 AI 技术的 UI 自动化测试框架,通过自然语言交互简化测试流程,支持动作执行、数据查询和页面断言,提供可视化报告,适用于多种应用场景。
3432 1
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
|
10月前
|
JavaScript 前端开发 Java
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
柯里化是一种强大的函数式编程技术,它通过将函数分解为单参数形式,实现了灵活性与可复用性的统一。无论是参数复用、延迟执行,还是函数组合,柯里化都为现代编程提供了极大的便利。 从 Redux 的选择器优化到复杂的数据流处理,再到深度嵌套的函数优化,柯里化在实际开发中展现出了非凡的价值。如果你希望编写更简洁、更优雅的代码,柯里化无疑是一个值得深入学习和实践的工具。从简单的实现到复杂的应用,希望这篇博客能为你揭开柯里化的奥秘,助力你的开发之旅! 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一