QUnit, entwickelt vom jQuery-Team, ist ein hervorragendes Framework für Unit-Tests von JavaScript. In diesem Tutorial erkläre ich, was QUnit genau ist und warum Sie Ihren Code gründlich testen sollten.
QUnit ist ein leistungsstarkes JavaScript-Unit-Test-Framework, das Ihnen beim Debuggen Ihres Codes hilft. Es wurde von Mitgliedern des jQuery-Teams geschrieben und ist die offizielle Testsuite für jQuery. Aber QUnit ist allgemein genug, um jeden regulären JavaScript-Code und sogar serverseitiges JavaScript über bestimmte JavaScript-Engines wie Rhino oder V8 zu testen.
Wenn Sie mit dem Konzept des „Unit-Tests“ nicht vertraut sind, machen Sie sich keine Sorgen. Es ist nicht schwer zu verstehen:
In der Computerprogrammierung ist Unit-Test eine Methode zur Softwareverifizierung und -validierung, bei der Programmierer einzelne Einheiten des Quellcodes auf ihre Eignung für die Verwendung testen. Eine Einheit ist der kleinste testbare Teil einer Anwendung. Bei der prozeduralen Programmierung kann eine Einheit eine einzelne Funktion oder Prozedur sein.
Dieser Inhalt wird aus Wikipedia zitiert. Kurz gesagt, Sie schreiben Tests für jede Funktion Ihres Codes, und wenn alle diese Tests erfolgreich sind, können Sie sicher sein, dass Ihr Code fehlerfrei ist (hauptsächlich abhängig davon, wie gründlich Ihre Tests sind).
Wenn Sie noch keine Unit-Tests geschrieben haben, wenden Sie den Code möglicherweise direkt auf die Website an, klicken Sie eine Weile herum, um zu sehen, ob Probleme auftreten, und versuchen Sie, das Problem zu beheben, wenn Sie welche finden. Bei diesem Ansatz gibt es viele Probleme.
Erstens ist es sehr mühsam. Das Klicken ist eigentlich keine leichte Aufgabe, da Sie sicherstellen müssen, dass alles angeklickt wird, und es besteht die Möglichkeit, dass Sie das eine oder andere verpassen. Zweitens ist nichts, was Sie zum Testen tun, wiederverwendbar, was bedeutet, dass es nicht einfach ist, Regressionen zu finden. Was ist Regression? Stellen Sie sich vor, Sie haben Code geschrieben, ihn getestet, alle gefundenen Fehler behoben und ihn dann veröffentlicht. Benutzer senden dann Feedback zu neuen Fehlern und fordern einige neue Funktionen an. Sie gehen zurück zum Code, beheben diese neuen Fehler und fügen diese neuen Funktionen hinzu. Als nächstes kann es sein, dass einige alte Fehler wieder auftauchen. Dies wird als „Regression“ bezeichnet. Sehen Sie, jetzt, wo Sie noch einmal klicken müssen, werden Sie diese alten Fehler wahrscheinlich nicht mehr finden, und selbst wenn Sie das tun, wird es eine Weile dauern, bis Sie herausfinden, dass das Problem durch eine Regression verursacht wird. Mit Unit-Tests können Sie Tests schreiben, um Fehler zu finden, und sobald der Code geändert wurde, können Sie ihn erneut durch die Tests filtern. Wenn eine Regression auftritt, werden einige Tests definitiv fehlschlagen, und Sie können sie leicht erkennen, indem Sie wissen, welcher Teil des Codes den Fehler enthält. Da Sie wissen, was Sie gerade geändert haben, können Sie es leicht beheben.
Ein weiterer Vorteil von Unit-Tests gilt insbesondere für die Webentwicklung: Es vereinfacht das Testen auf Cross-Browser-Kompatibilität. Führen Sie die Tests einfach in verschiedenen Browsern aus. Wenn bei einem Browser etwas schief geht, können Sie das Problem beheben und die Tests erneut ausführen. So stellen Sie sicher, dass es bei anderen Browsern nicht zu Regressionen kommt. Sobald alle Zielbrowser den Test bestanden haben, können Sie sicher sein, dass sie alle unterstützt werden.
Ich möchte eines von John Resigs Projekten erwähnen: TestSwarm. Durch die Verteilung wird das JavaScript-Unit-Testen auf die nächste Stufe gehoben. Es handelt sich um eine Website mit vielen Tests. Jeder kann dorthin gehen, einige Tests durchführen und die Ergebnisse dann an den Server zurücksenden. Auf diese Weise kann der Code sehr schnell über verschiedene Browser und sogar verschiedene Plattformen hinweg getestet werden.
Wie schreibe ich Unit-Tests mit QUnit? Zuerst müssen Sie eine Testumgebung einrichten:
<!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>
Wie Sie sehen, wird hier die verwaltete Version des QUnit-Frameworks verwendet.
Der Code, den Sie testen möchten, sollte in myProject.js eingefügt werden, und Ihre Tests sollten in myTests.js eingefügt werden. Um diese Tests durchzuführen, öffnen Sie einfach diese HTML-Datei in Ihrem Browser. Jetzt ist es an der Zeit, einige Tests zu schreiben.
Der Baustein des Unit-Tests sind Behauptungen.
Assertions sind Anweisungen, die vorhersagen, was der Code zurückgeben wird. Wenn die Vorhersage falsch ist, schlägt die Behauptung fehl und Sie wissen, dass etwas schief gelaufen ist.
Um Behauptungen auszuführen, sollten Sie sie in Testfälle einfügen:
// 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'); })
Hier haben wir eine Funktion isEven definiert, die prüft, ob eine Zahl gerade ist, und wir möchten diese Funktion testen, um sicherzustellen, dass sie nicht die falsche Antwort zurückgibt.
Wir rufen zuerst test() auf, das einen Testfall erstellt. Der erste Parameter ist die Zeichenfolge, die in den Ergebnissen angezeigt wird, und der zweite Parameter ist die Rückruffunktion, die unsere Behauptung enthält. Diese Rückruffunktion wird aufgerufen, sobald QUnit ausgeführt wird.
Wir haben fünf Behauptungen geschrieben, die alle boolesch sind. Eine boolesche Behauptung erwartet, dass ihr erstes Argument wahr ist. Der zweite Parameter ist ebenfalls eine Meldung, die in den Ergebnissen angezeigt wird.
Nachdem Sie den Test durchgeführt haben, erhalten Sie folgende Ergebnisse:
由于所有这些断言都已成功通过,我们可以非常确定 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'); })
结果如下:
断言失败是因为我们故意写错了,但在你自己的项目中,如果测试没有通过,并且所有断言都是正确的,你就知道发现了一个bug。
ok() 并不是 QUnit 提供的唯一断言。在测试项目时,还有其他类型的断言很有用:
比较断言 equals() 期望其第一个参数(即实际值)等于其第二个参数(即期望值)。它与 ok() 类似,但同时输出实际值和期望值,使调试更加容易。与 ok() 一样,它采用可选的第三个参数作为要显示的消息。
所以代替:
test('assertions', function() { ok( 1 == 1, 'one equals one'); })
你应该写:
test('assertions', function() { equals( 1, 1, 'one equals one'); })
注意最后一个“1”,这是比较值。
如果值不相等:
test('assertions', function() { equals( 2, 1, 'one equals one'); })
它提供了更多信息,使生活变得更加轻松。
比较断言使用“==”来比较其参数,因此它不处理数组或对象比较:
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() {});
在前面的示例中,所有断言都是同步调用的,这意味着它们依次运行。在现实世界中,还有很多异步函数,例如ajax调用或setTimeout()和setInterval()调用的函数。我们如何测试这些类型的功能? QUnit 提供了一种特殊的测试用例,称为“异步测试”,专门用于异步测试:
我们先尝试用常规的方式来写:
test('asynchronous test', function() { setTimeout(function() { ok(true); }, 100) })
看到了吗?就好像我们没有写任何断言一样。这是因为断言是异步运行的,当它被调用时,测试用例已经完成。
这是正确的版本:
test('asynchronous test', function() { // Pause the test first stop(); setTimeout(function() { ok(true); // After the assertion has been called, // continue the test start(); }, 100) })
在这里,我们使用 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(),整个单元测试将挂起:
所以这就是你要做的:
// 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 所需了解的全部内容。单元测试是在发布代码之前测试代码的好方法。如果您之前没有编写过任何单元测试,那么现在就开始吧!感谢您的阅读!
Das obige ist der detaillierte Inhalt vonTesten von JavaScript-Code mit QUnit: eine Schritt-für-Schritt-Anleitung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!