目錄
#什麼是 QUnit
為什麼應該測試程式碼
如何使用 QUnit 寫單元測試
更多断言
比较断言
相同的断言
构建你的断言
异步测试
结论
首頁 web前端 js教程 使用 QUnit 測試 JavaScript 程式碼:逐步指南

使用 QUnit 測試 JavaScript 程式碼:逐步指南

Sep 02, 2023 pm 05:09 PM

QUnit 由 jQuery 團隊開發,是一個用於對 JavaScript 進行單元測試的出色框架。在本教學中,我將介紹 QUnit 具體是什麼,以及為什麼您應該關心嚴格測試您的程式碼。

#什麼是 QUnit

QUnit 是一個強大的 JavaScript 單元測試框架,可以幫助您偵錯程式碼。它由 jQuery 團隊成員編寫,是 jQuery 的官方測試套件。但 QUnit 足夠通用,可以測試任何常規 JavaScript 程式碼,甚至可以透過某些 JavaScript 引擎(如 Rhino 或 V8)測試伺服器端 JavaScript。

如果您不熟悉「單元測試」的概念,請不要擔心。理解起來並不難:

在電腦程式設計中,單元測試是一種軟體驗證和確認方法,程式設計師在其中測試原始程式碼的各個單元是否適合使用。單元是應用程式最小可測試的部分。在過程式編程中,一個單元可以是一個單獨的函數或過程。

此內容引自維基百科。簡而言之,您為程式碼的每個功能編寫測試,如果所有這些測試都通過了,您可以確定程式碼將沒有錯誤(主要取決於您的測試的徹底程度)。

為什麼應該測試程式碼

如果您以前沒有編寫過任何單元測試,您可能只是將程式碼直接應用到網站上,點擊一會兒看看是否出現任何問題,並在發現問題時嘗試修復它。這種方法存在著許多問題。

首先,這非常乏味。點擊實際上並不是一件容易的事,因為你必須確保所有內容都被點擊,並且很可能你會錯過一兩件事。其次,您為測試所做的一切都不可重複使用,這意味著找到回歸並不容易。什麼是回歸?想像一下,您編寫了一些程式碼並對其進行了測試,修復了發現的所有錯誤,然後發布了它。然後,用戶發送一些有關新錯誤的回饋,並要求一些新功能。您返回程式碼,修復這些新錯誤並新增這些新功能。接下來可能發生的是一些舊的錯誤再次出現,這被稱為“回歸”。看,現在你必須再次點擊,很可能你就不會再發現這些舊的錯誤了;即使你這樣做了,你也需要一段時間才能發現問題是由回歸引起的。透過單元測試,您可以編寫測試來查找錯誤,一旦程式碼被修改,您可以再次透過測試對其進行過濾。如果出現回歸,某些測試肯定會失敗,並且您可以輕鬆發現它們,知道程式碼的哪一部分包含錯誤。由於您知道剛剛修改的內容,因此可以輕鬆修復它。

單元測試的另一個優點尤其適用於 Web 開發:它簡化了跨瀏覽器相容性的測試。只需在不同的瀏覽器上執行測試,如果一種瀏覽器出現問題,您可以修復它並再次執行這些測試,確保它不會在其他瀏覽器上引入回歸。一旦所有目標瀏覽器都通過測試,您就可以確定它們都受支援。

我想提一下 John Resig 的專案之一:TestSwarm。透過使其分佈式,它將 JavaScript 單元測試提升到一個新的水平。這是一個包含許多測試的網站,任何人都可以去那裡,運行一些測試,然後將結果返回到伺服器。這樣,程式碼就可以非常快速地在不同瀏覽器甚至不同平台上進行測試。

如何使用 QUnit 寫單元測試

那麼到底要如何使用 QUnit 來寫單元測試呢?首先需要建置測試環境:

<!DOCTYPE html>
<html>
<head>
	<title>QUnit Test Suite</title>
	<link rel="stylesheet" href="http://github.com/jquery/qunit/raw/master/qunit/qunit.css" type="text/css" media="screen">
	<script type="text/javascript" src="http://github.com/jquery/qunit/raw/master/qunit/qunit.js"></script>
	<!-- Your project file goes here -->
	<script type="text/javascript" src="myProject.js"></script>
	<!-- Your tests file goes here -->
	<script type="text/javascript" src="myTests.js"></script>
</head>
<body>
	<h1 id="qunit-header">QUnit Test Suite</h1>
	<h2 id="qunit-banner"></h2>
	<div id="qunit-testrunner-toolbar"></div>
	<h2 id="qunit-userAgent"></h2>
	<ol id="qunit-tests"></ol>
</body>
</html>
登入後複製

如您所看到的,這裡使用了 QUnit 框架的託管版本。

要測試的程式碼應放入 myProject.js,並且您的測試應插入 myTests.js。要執行這些測試,只需在瀏覽器中開啟此 HTML 檔案即可。現在是時候編寫一些測試了。

單元測試的建構塊是斷言。

斷言是預測程式碼回傳結果的語句。如果預測是錯誤的,則斷言失敗,並且您知道出了問題。

要執行斷言,您應該將它們放入測試案例中:

// Let's test this function
function isEven(val) {
	return val % 2 === 0;
}

test('isEven()', function() {
	ok(isEven(0), 'Zero is an even number');
	ok(isEven(2), 'So is two');
	ok(isEven(-4), 'So is negative four');
	ok(!isEven(1), 'One is not an even number');
	ok(!isEven(-7), 'Neither is negative seven');
})
登入後複製

這裡我們定義了一個函數 isEven,它檢測一個數字是否為偶數,我們想測試這個函數以確保它不會回傳錯誤的答案。

我們首先呼叫test(),它建構一個測試案例;第一個參數是將在結果中顯示的字串,第二個參數是包含我們的斷言的回調函數。一旦 QUnit 運行,就會呼叫此回調函數。

我們寫了五個斷言,所有斷言都是布林值。布林斷言期望其第一個參數為 true。第二個參數也是一則會在結果中顯示的訊息。

執行測試後,您將得到以下結果:

使用 QUnit 测试 JavaScript 代码:分步指南

#

由于所有这些断言都已成功通过,我们可以非常确定 isEven() 将按预期工作。

让我们看看如果断言失败会发生什么。

// Let's test this function
function isEven(val) {
	return val % 2 === 0;
}

test('isEven()', function() {
	ok(isEven(0), 'Zero is an even number');
	ok(isEven(2), 'So is two');
	ok(isEven(-4), 'So is negative four');
	ok(!isEven(1), 'One is not an even number');
	ok(!isEven(-7), 'Neither does negative seven');

	// Fails
	ok(isEven(3), 'Three is an even number');
})
登入後複製

结果如下:

使用 QUnit 测试 JavaScript 代码:分步指南

断言失败是因为我们故意写错了,但在你自己的项目中,如果测试没有通过,并且所有断言都是正确的,你就知道发现了一个bug。

更多断言

ok() 并不是 QUnit 提供的唯一断言。在测试项目时,还有其他类型的断言很有用:

比较断言

比较断言 equals() 期望其第一个参数(即实际值)等于其第二个参数(即期望值)。它与 ok() 类似,但同时输出实际值和期望值,使调试更加容易。与 ok() 一样,它采用可选的第三个参数作为要显示的消息。

所以代替:

test('assertions', function() {
	ok( 1 == 1, 'one equals one');
})
登入後複製

使用 QUnit 测试 JavaScript 代码:分步指南

你应该写:

test('assertions', function() {
	equals( 1, 1, 'one equals one');
})
登入後複製

使用 QUnit 测试 JavaScript 代码:分步指南

注意最后一个“1”,这是比较值。

如果值不相等:

test('assertions', function() {
	equals( 2, 1, 'one equals one');
})
登入後複製

使用 QUnit 测试 JavaScript 代码:分步指南

它提供了更多信息,使生活变得更加轻松。

比较断言使用“==”来比较其参数,因此它不处理数组或对象比较:

test('test', function() {
	equals( {}, {}, 'fails, these are different objects');
	equals( {a: 1}, {a: 1} , 'fails');
	equals( [], [], 'fails, there are different arrays');
	equals( [1], [1], 'fails');
})
登入後複製

为了测试这种相等性,QUnit 提供了另一种断言:相同断言

相同的断言

相同的断言,same(),需要与 equals() 相同的参数,但它是一个深度递归比较断言,不仅适用于基本类型,还适用于数组和对象。在前面的示例中,如果将断言更改为相同的断言,它们将全部通过:

test('test', function() {
	same( {}, {}, 'passes, objects have the same content');
	same( {a: 1}, {a: 1} , 'passes');
	same( [], [], 'passes, arrays have the same content');
	same( [1], [1], 'passes');
})
登入後複製

请注意,same() 在可能的情况下使用“===”进行比较,因此在比较特殊值时它会派上用场:

test('test', function() {
	equals( 0, false, 'true');
	same( 0, false, 'false');
	equals( null, undefined, 'true');
	same( null, undefined, 'false');
})
登入後複製

构建你的断言

将所有断言放在一个测试用例中是一个非常糟糕的主意,因为它很难维护,并且不会返回干净的结果。您应该做的是构建它们,将它们放入不同的测试用例中,每个测试用例都针对单一功能。

您甚至可以通过调用模块函数将测试用例组织到不同的模块中:

module('Module A');
test('a test', function() {});
test('an another test', function() {});

module('Module B');
test('a test', function() {});
test('an another test', function() {});
登入後複製

使用 QUnit 测试 JavaScript 代码:分步指南

异步测试

在前面的示例中,所有断言都是同步调用的,这意味着它们依次运行。在现实世界中,还有很多异步函数,例如ajax调用或setTimeout()和setInterval()调用的函数。我们如何测试这些类型的功能? QUnit 提供了一种特殊的测试用例,称为“异步测试”,专门用于异步测试:

我们先尝试用常规的方式来写:

test('asynchronous test', function() {
	setTimeout(function() {
		ok(true);
	}, 100)
})
登入後複製

使用 QUnit 测试 JavaScript 代码:分步指南

看到了吗?就好像我们没有写任何断言一样。这是因为断言是异步运行的,当它被调用时,测试用例已经完成。

这是正确的版本:

test('asynchronous test', function() {
	// Pause the test first
	stop();
	
	setTimeout(function() {
		ok(true);

		// After the assertion has been called,
		// continue the test
		start();
	}, 100)
})
登入後複製

使用 QUnit 测试 JavaScript 代码:分步指南

在这里,我们使用 stop() 暂停测试用例,调用断言后,我们使用 start() 继续。

调用 test() 后立即调用 stop() 是很常见的;所以QUnit提供了一个快捷方式:asyncTest()。您可以像这样重写前面的示例:

asyncTest('asynchronous test', function() {
	// The test is automatically paused
	
	setTimeout(function() {
		ok(true);

		// After the assertion has been called,
		// continue the test
		start();
	}, 100)
})
登入後複製

有一点需要注意:setTimeout() 将始终调用其回调函数,但如果它是自定义函数(例如 ajax 调用)怎么办?您如何确定回调函数将被调用?如果不调用回调,则不会调用 start(),整个单元测试将挂起:

使用 QUnit 测试 JavaScript 代码:分步指南

所以这就是你要做的:

// A custom function
function ajax(successCallback) {
	$.ajax({
		url: 'server.php',
		success: successCallback
	});
}

test('asynchronous test', function() {
	// Pause the test, and fail it if start() isn't called after one second
	stop(1000);
	
	ajax(function() {
		// ...asynchronous assertions

		start();
	})
})
登入後複製

您将超时传递给 stop(),它告诉 QUnit,“如果在该超时后未调用 start(),则该测试应该失败。”您可以确信整个测试不会挂起,并且如果出现问题您将会收到通知。

多个异步函数怎么样?你把start()放在哪里?你把它放在setTimeout()中:

// A custom function
function ajax(successCallback) {
	$.ajax({
		url: 'server.php',
		success: successCallback
	});
}

test('asynchronous test', function() {
	// Pause the test
	stop();
	
	ajax(function() {
		// ...asynchronous assertions
	})

	ajax(function() {
		// ...asynchronous assertions
	})

	setTimeout(function() {
		start();
	}, 2000);
})
登入後複製

超时应该足够长,以允许在测试继续之前调用两个回调。但是如果其中一个回调没有被调用怎么办?你怎么知道这一点?这就是expect() 发挥作用的地方:

// A custom function
function ajax(successCallback) {
	$.ajax({
		url: 'server.php',
		success: successCallback
	});
}

test('asynchronous test', function() {
	// Pause the test
	stop();

	// Tell QUnit that you expect three assertions to run
	expect(3);

	ajax(function() {
		ok(true);
	})

	ajax(function() {
		ok(true);
		ok(true);
	})

	setTimeout(function() {
		start();
	}, 2000);
})
登入後複製

你向expect()传递一个数字来告诉QUnit你期望运行X个断言,如果其中一个断言没有被调用,数字将不匹配,并且你会被通知有事情发生错了。

expect() 还有一个快捷方式:只需将数字作为第二个参数传递给 test() 或 asyncTest():

// A custom function
function ajax(successCallback) {
	$.ajax({
		url: 'server.php',
		success: successCallback
	});
}

// Tell QUnit that you expect three assertion to run
test('asynchronous test', 3, function() {
	// Pause the test
	stop();

	ajax(function() {
		ok(true);
	})

	ajax(function() {
		ok(true);
		ok(true);
	})

	setTimeout(function() {
		start();
	}, 2000);
})
登入後複製

结论

这就是开始使用 QUnit 所需了解的全部内容。单元测试是在发布代码之前测试代码的好方法。如果您之前没有编写过任何单元测试,那么现在就开始吧!感谢您的阅读!

  • 在 Twitter 上关注我们,或订阅 Nettuts+ RSS Feed 以获取网络上最好的 Web 开发教程。

以上是使用 QUnit 測試 JavaScript 程式碼:逐步指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前 By 尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

在JavaScript中替換字符串字符 在JavaScript中替換字符串字符 Mar 11, 2025 am 12:07 AM

在JavaScript中替換字符串字符

jQuery檢查日期是否有效 jQuery檢查日期是否有效 Mar 01, 2025 am 08:51 AM

jQuery檢查日期是否有效

jQuery獲取元素填充/保證金 jQuery獲取元素填充/保證金 Mar 01, 2025 am 08:53 AM

jQuery獲取元素填充/保證金

10個jQuery手風琴選項卡 10個jQuery手風琴選項卡 Mar 01, 2025 am 01:34 AM

10個jQuery手風琴選項卡

10值得檢查jQuery插件 10值得檢查jQuery插件 Mar 01, 2025 am 01:29 AM

10值得檢查jQuery插件

HTTP與節點和HTTP-Console調試 HTTP與節點和HTTP-Console調試 Mar 01, 2025 am 01:37 AM

HTTP與節點和HTTP-Console調試

自定義Google搜索API設置教程 自定義Google搜索API設置教程 Mar 04, 2025 am 01:06 AM

自定義Google搜索API設置教程

jQuery添加捲軸到Div jQuery添加捲軸到Div Mar 01, 2025 am 01:30 AM

jQuery添加捲軸到Div

See all articles