QUnit系列 -- 2.介绍单元测试(下)

简介:   JavaScript测试框架:QUnit   下面我们将介绍使用QUnit来完成前一章中的单元测试。 DOCTYPE html> Refactored date examples test...

  JavaScript测试框架:QUnit

  下面我们将介绍使用QUnit来完成前一章中的单元测试。

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Refactored date examples</title>
 
    <link rel="stylesheet" href="../qunit.css" />
    <script src="../qunit.js"></script>
    <script src="prettydate.js"></script>
 
    <script>
    test("prettydate basics", function() {
        var now = "2008/01/28 22:25:00";
        equal(prettyDate(now, "2008/01/28 22:24:30"), "just now");
        equal(prettyDate(now, "2008/01/28 22:23:30"), "1 minute ago");
        equal(prettyDate(now, "2008/01/28 21:23:30"), "1 hour ago");
        equal(prettyDate(now, "2008/01/27 22:23:30"), "Yesterday");
        equal(prettyDate(now, "2008/01/26 22:23:30"), "2 days ago");
        equal(prettyDate(now, "2007/01/26 22:23:30"), undefined);
    });
    </script>
</head>
<body>
    <div id="qunit"></div>
</body>
</html>

  运行实例

 

  这里有三点需要注意。

  首先,我们包含了三个文件:两个和 QUnit 相关(qunit.css and qunit.js) ,另一个是包含测试函数的prettydate.js。

  其次,是断言部门的脚本。test方法只会调用一次,第一个参数是测试名称,第二个参数是实际的测试代码。然后代码定义了变量now,便于后面使用。接下来使用equal方法来执行断言操作,他是QUnit提供的一系列方法中的一个。第一个参数是函数执行后的结果,第二个参数是期望值,如果两个值一致则断言通过,否则就失败。

  最后,页面body中包含一些和QUnit相关的标签,这些元素是可选的。如果我们使用了,QUnit会使用他们来输出结果。

输出结果:

包含失败的输出结果:

 

  因为测试包含一个失败的断言,所以QUnit没有把结果收起来,我们可以马上看到错误。我们把期望值和实际值都显示了出来,还显示了他们的不同点,这样对于我们找到问题很有帮助。

 

  重构:2

  我们的断言还没结束,还没有判断“几个星期”的情况。 再次之前,我们再把代码重构下。现在的版本每次断言的时候,都会去调用 prettyDate,并传递 now 参数。 我们可以重构一个自定义的断言函数:

test("prettydate basics", function() {
    function date(then, expected) {
        equal(prettyDate("2008/01/28 22:25:00", then), expected);
    }
    date("2008/01/28 22:24:30", "just now");
    date("2008/01/28 22:23:30", "1 minute ago");
    date("2008/01/28 21:23:30", "1 hour ago");
    date("2008/01/27 22:23:30", "Yesterday");
    date("2008/01/26 22:23:30", "2 days ago");
    date("2007/01/26 22:23:30", undefined);
});

  运行实例

  这样我们就把prettyDate封装到了date函数中,date里面会提供now变量,这样外面使用的时候就不需要再传递了。这样会让我们的代码更简单。

  

  测试DOM操作

  现在prettyDate已经可以被很好的测试了,让我们回过头来看之前的例子。借助于window的load事件,我们可以使用prettyDate函数选择DOM元素并更新他们。和之前一样,我们需要重构他并使之能够测试。另外,我们把两个方法放到同一个模块中,避免命名空间的混乱并且让代码更容易维护。

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Refactored date examples</title>
    <link rel="stylesheet" href="../qunit.css" />
    <script src="../qunit.js"></script>
    <script src="prettydate2.js"></script>
    <script>
    test("prettydate.format", function() {
        function date(then, expected) {
            equal(prettyDate.format("2008/01/28 22:25:00", then), expected);
        }
        date("2008/01/28 22:24:30", "just now");
        date("2008/01/28 22:23:30", "1 minute ago");
        date("2008/01/28 21:23:30", "1 hour ago");
        date("2008/01/27 22:23:30", "Yesterday");
        date("2008/01/26 22:23:30", "2 days ago");
        date("2007/01/26 22:23:30", undefined);
    });
 
    test("prettyDate.update", function() {
        var links = document.getElementById("qunit-fixture").getElementsByTagName("a");
        equal(links[0].innerHTML, "January 28th, 2008");
        equal(links[2].innerHTML, "January 27th, 2008");
        prettyDate.update("2008-01-28T22:25:00Z");
        equal(links[0].innerHTML, "2 hours ago");
        equal(links[2].innerHTML, "Yesterday");
    });
 
    test("prettyDate.update, one day later", function() {
        var links = document.getElementById("qunit-fixture").getElementsByTagName("a");
        equal(links[0].innerHTML, "January 28th, 2008");
        equal(links[2].innerHTML, "January 27th, 2008");
        prettyDate.update("2008/01/29 22:25:00");
        equal(links[0].innerHTML, "Yesterday");
        equal(links[2].innerHTML, "2 days ago");
    });
    </script>
</head>
<body>
    <div id="qunit"></div>
    <div id="qunit-fixture">
        <ul>
            <li class="entry" id="post57">
                <p>blah blah blah...</p>
                <small class="extra">
                    Posted <span class="time"><a href="/2008/01/blah/57/" title="2008-01-28T20:24:17Z">January 28th, 2008</a></span>
                    by <span class="author"><a href="/john/">John Resig</a></span>
                </small>
            </li>
            <li class="entry" id="post57">
                <p>blah blah blah...</p>
                <small class="extra">
                    Posted <span class="time"><a href="/2008/01/blah/57/" title="2008-01-27T22:24:17Z">January 27th, 2008</a></span>
                    by <span class="author"><a href="/john/">John Resig</a></span>
                </small>
            </li>
        </ul>
    </div>
</body>
</html>

  prettydate2.js代码:

var prettyDate = {
    format: function(now, time){
        var date = new Date(time || ""),
            diff = (((new Date(now)).getTime() - date.getTime()) / 1000),
            day_diff = Math.floor(diff / 86400);
 
        if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 )
            return;
 
        return day_diff === 0 && (
                diff < 60 && "just now" ||
                diff < 120 && "1 minute ago" ||
                diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
                diff < 7200 && "1 hour ago" ||
                diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
            day_diff === 1 && "Yesterday" ||
            day_diff < 7 && day_diff + " days ago" ||
            day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago";
    },
 
    update: function(now) {
        var links = document.getElementsByTagName("a");
        for ( var i = 0; i < links.length; i++ ) {
            if ( links[i].title ) {
                var date = prettyDate.format(now, links[i].title);
                if ( date ) {
                    links[i].innerHTML = date;
                }
            }
        }
    }
};

  运行实例

 

  prettyDate.update方法是从之前例子中提取出来的,他含有now参数,方法里面把now传给了prettyDate.format。基于QUnit的测试,开始的时候会把所有包含在#qunit-fixture中的元素找出来。<div id="qunit-fixture">…</div>是页面新加入的标签,这里我们放置之前例子使用的DOM标签,这样我们就可以用于测试了。你不用担心这里DOM元素的改变会影响到其他的测试,因为QUnit会为每次测试重置这些标签的。

  这里你也许会有疑问,为什么测试页面没有显示<div id="qunit-fixture">…</div>的内容呢,原因是QUnit把他放在了一个离我们屏幕很远的地方,看截图:

 

 

  重构:3

  上面的代码还是有很多重复的内容,我们进一步重构,把测试DOM的测试抽到方法domtest中,方便多次调用:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Refactored date examples</title>
    <link rel="stylesheet" href="../qunit.css" />
    <script src="../qunit.js"></script>
    <script src="prettydate2.js"></script>
    <script>
    test("prettydate.format", function() {
        function date(then, expected) {
            equal(prettyDate.format("2008/01/28 22:25:00", then), expected);
        }
        date("2008/01/28 22:24:30", "just now");
        date("2008/01/28 22:23:30", "1 minute ago");
        date("2008/01/28 21:23:30", "1 hour ago");
        date("2008/01/27 22:23:30", "Yesterday");
        date("2008/01/26 22:23:30", "2 days ago");
        date("2007/01/26 22:23:30", undefined);
    });
 
    function domtest(name, now, first, second) {
        test(name, function() {
            var links = document.getElementById("qunit-fixture").getElementsByTagName("a");
            equal(links[0].innerHTML, "January 28th, 2008");
            equal(links[2].innerHTML, "January 27th, 2008");
            prettyDate.update(now);
            equal(links[0].innerHTML, first);
            equal(links[2].innerHTML, second);
        });
    }
    domtest("prettyDate.update", "2008-01-28T22:25:00Z", "2 hours ago", "Yesterday");
    domtest("prettyDate.update, one day later", "2008/01/29 22:25:00", "Yesterday", "2 days ago");
    </script>
</head>
<body>
    <div id="qunit"></div>
    <div id="qunit-fixture">
        <ul>
            <li class="entry" id="post57">
                <p>blah blah blah...</p>
                <small class="extra">
                    Posted <span class="time"><a href="/2008/01/blah/57/" title="2008-01-28T20:24:17Z">January 28th, 2008</a></span>
                    by <span class="author"><a href="/john/">John Resig</a></span>
                </small>
            </li>
            <li class="entry" id="post57">
                <p>blah blah blah...</p>
                <small class="extra">
                    Posted <span class="time"><a href="/2008/01/blah/57/" title="2008-01-27T22:24:17Z">January 27th, 2008</a></span>
                    by <span class="author"><a href="/john/">John Resig</a></span>
                </small>
            </li>
        </ul>
    </div>
</body>
</html>

  运行实例

 

  回到开始

  重构之前,我们之前的代码会变的很简单:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Final date examples</title>
    <script src="prettydate2.js"></script>
    <script>
    window.onload = function() {
        prettyDate.update("2008-01-28T22:25:00Z");
    };
    </script>
</head>
<body>
 
<ul>
    <li class="entry" id="post57">
        <p>blah blah blah...</p>
        <small class="extra">
            Posted <span class="time"><a href="/2008/01/blah/57/" title="2008-01-28T20:24:17Z"><span>January 28th, 2008</span></a></span>
            by <span class="author"><a href="/john/">John Resig</a></span>
        </small>
    </li>
    <-- 更多内容... -->
</ul>
 
</body>
</html>

  运行实例

 

  结论

  测试JavaScript不简单是使用测试运行器,写写测试用例。他要求你需要对代码结构作比较大的改变,以方便他能被执行单元测试。我们通过一个例子演示了如何实现特定的测试框架,也介绍了如何重构代码,以使他能使用QUnit做测试。QUnit提供了很多功能,例如支持测试异步代码,例如timeouts,ajax和事件。他的可视化测试运行器可以帮助我们debug代码,对特性测试的重新执行,并且方便我们跟踪错误信息。

 

文章来源:http://qunitjs.com/intro/

目录
相关文章
|
JavaScript 前端开发 测试技术
|
JavaScript 前端开发 机器人
|
Web App开发 JavaScript 测试技术
QUnit系列 -- 1.介绍单元测试(上)
  大家都知道单元测试对于保证代码质量的重要性,但是对客户端代码进行单元测试则要困难的多。一个比较棘手的问题是,因为JavaScript代码和后台代码或者html结合的比较紧密,他缺少真正单元的概念。例如对dom的操作,无论我们是借助jquery这样的类库,把js代码单独放在一个文件,还是直接使用内嵌代码的实现方式,都没有可以测试的单元。
1012 0
|
2月前
|
数据可视化 前端开发 测试技术
接口测试新选择:Postman替代方案全解析
在软件开发中,接口测试工具至关重要。Postman长期占据主导地位,但随着国产工具的崛起,越来越多开发者转向更适合中国市场的替代方案——Apifox。它不仅支持中英文切换、完全免费不限人数,还具备强大的可视化操作、自动生成文档和API调试功能,极大简化了开发流程。
|
1月前
|
JSON 前端开发 测试技术
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
98 10
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
|
1月前
|
JSON 前端开发 API
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
64 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
|
8天前
|
存储 JSON API
Python测试淘宝店铺所有商品接口的详细指南
本文详细介绍如何使用Python测试淘宝店铺商品接口,涵盖环境搭建、API接入、签名生成、请求发送、数据解析与存储、异常处理等步骤。通过具体代码示例,帮助开发者轻松获取和分析淘宝店铺商品数据,适用于电商运营、市场分析等场景。遵守法规、注意调用频率限制及数据安全,确保应用的稳定性和合法性。
|
2天前
|
监控 API 开发工具
Socket.IO介绍,以及怎么连接测试Socket.IO接口?
Socket.IO 是一个用于浏览器和服务器间实时双向通信的库,支持低延迟消息传递、跨平台运行及自动重连。文章介绍了其特点与调试需求,并详细说明如何使用 Apifox 工具创建、连接、发送/接收 Socket.IO 事件,以及团队协作和调试技巧。掌握这些技能可提升实时应用开发效率与质量。
|
21天前
|
小程序 测试技术 数据安全/隐私保护
微信公众号接口测试实战指南
微信公众号接口测试是确保系统稳定性和功能完整性的重要环节。本文详细介绍了测试全流程,包括准备、工具选择(如Postman、JMeter)、用例设计与执行,以及常见问题的解决方法。通过全面测试,可以提前发现潜在问题,优化用户体验,确保公众号上线后稳定运行。内容涵盖基础接口、高级接口、微信支付和数据统计接口的测试,强调了功能验证、性能优化、安全保护及用户体验的重要性。未来,随着微信生态的发展,接口测试将面临更多挑战和机遇,如小程序融合、AI应用和国际化拓展。

热门文章

最新文章