XUnit是一套标准化的独立于语言的概念和结构集合,用于编写和运行单元测试(Unit tests).javascript
每个语言都有一个用于单元测试的XUnit框架,好比Java有JUnit, C++有CppUnit, PHP有PHPUnit, Oracle SQL有UTPL/SQL.html
JsUnit的官网: http://jsunit.net/java
JsUnit遵循XUnit的一些惯例:web
单元测试在JsUnit中叫作Test Functions.服务器
Test Functions所在的HTML页面叫作Test Page.app
一个Test Page是一个包含jsUnitCore.js的HTML页面. jsUnitCore.js提供了一些断言函数, 好比assertEquals(comment, arg1, arg2).框架
JsUnit支持setUp()和tearDown().函数
Test Suite Page声明了一个suite()函数,返回一个JsUnitTestSuite, 用来运行含多个测试的套件.单元测试
JsUnit的testRunner.html页运行Test Pages.测试
TestRunner页面能够运行在一个文件服务器或者web服务器上.
因为JavaScript没有访问修饰符,因此一般在JavaScript中,不但愿外界访问的成员和方法名如下划线开始.
这是一种编码规范,不是语言的规定,虽然外界仍然能够访问可是不推荐.
JsUnit测试函数要遵循的规则与JUnit3.8相似,好比说测试函数名以test开头等.
待测试的源代码:test1.js
function add(num1, num2) { return num1 + num2; } function subtract(num1, num2) { return num1 - num2; } function multiply(num1, num2) { return num1 * num2; } function addNumbers() { var v1 = document.getElementById("value1").value; var v2 = document.getElementById("value2").value; v1 = parseInt(v1); v2 = parseInt(v2); var v3 = v1 + v2; document.getElementById("value3").value = v3; }
测试页面:test1.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title> New Document </title> <meta name="Generator" content="EditPlus"> <meta name="Author" content=""> <meta name="Keywords" content=""> <meta name="Description" content=""> <script type="text/javascript" src="..\jsunit2_2\jsunit\app\jsUnitCore.js"></script> <script type="text/javascript" src="test1.js"></script> <script type="text/javascript"> var count = 0; // 此函数只执行一次(在页面加载后),相似于JUnit 4.x中的@BeforeClass // 注意:并无与@AfterClass对应的函数存在 function setUpPage() { alert('setUpPage Invoked'); // 这行代码必须放在setUpPage函数的最后一行 // 告诉JsUnit,setUpPage函数已经执行完毕 setUpPageStatus = "complete"; } // setUp run before every test function function setUp() { //alert(count++); //JUnit若这样执行,count全是0,由于每个测试方法都会生成新的测试对象; //JsUnit会递增count, 由于都是在同一个页面里去执行,因此会基于原有的值 //设定初始条件 document.getElementById("value1").value = 2; document.getElementById("value2").value = 3; } // tearDown run after every test function function tearDown() { //alert("tearDown"); //清理状态 document.getElementById("value1").value = ""; document.getElementById("value2").value = ""; document.getElementById("value3").value = ""; } // 如下为测试函数(Test Function) function testAdd() { var result = add(1, 2); assertEquals(3, result); } function testSubtract() { var result = subtract(1, 2); assertEquals(-1, result); } function testMultiply() { var result = multiply(1, 2); assertEquals(2,result); } function testAddNumbers() { addNumbers(); assertEquals("5", document.getElementById("value3").value); } </script> </head> <body> <input type="text" id="value1"><br> <input type="text" id="value2"><br> <input type="text" id="value3"><br> <input type="button" value="Add" onclick="addNumbers();"> </body> </html>
使用JsUnit提供的测试运行器: testRunner.html, 加载测试页面,便可运行相关测试,并报告结果.
setUp()在每个测试方法运行以前运行;
tearDown()在每个测试方法运行以后运行.
对于JsUnit来讲, 其setUp()和tearDown()方法与JUnit的运行原理是不一样的.
JUnit中的setUp()和tearDown()之间是没有关系的,也就是说不一样的测试方法运行在不一样的测试对象之中;
而JsUnit的各个测试函数是运行在同一个测试页面中,所以同一个页面中setUp()和tearDown()运行屡次(每一个测试函数以前和以后),会针对同一个变量进行操做.
setUpPage()在测试页面加载时执行,每次运行只执行一次.
这个方法的末尾必须加上:
setUpPageStatus = "complete";
表示setUpPage()执行完成,不然会提示setUpPage not completed, 从而没法执行测试用例.
JsUnitTestSuite定义在jsUnitCore.js中, JsUnitTestSuite表明多个JsUnit测试页面的套件,测试页面和测试套件均可以被加在套件中,即套件是可嵌套的.(组合模式).
JsUnitTestSuite的定义(见jsUnitCore.js):
/** * @class * A JsUnitTestSuite represents a suite of JsUnit Test Pages. Test Pages and Test Suites can be added to a * JsUnitTestSuite * @constructor */ function JsUnitTestSuite() { /** * Declares that this object is a JsUnitTestSuite */ this.isJsUnitTestSuite = true; /** * @private */ this._testPages = Array(); /** * @private */ this._pageIndex = 0; for (var i = 0; i < arguments.length; i++) { if (arguments[i]._testPages) { this.addTestSuite(arguments[i]); } else { this.addTestPage(arguments[i]); } } }
测试套件的使用例子1: test2.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title> New Document </title> <meta name="Generator" content="EditPlus"> <meta name="Author" content=""> <meta name="Keywords" content=""> <meta name="Description" content=""> <script type="text/javascript" src="..\jsunit2_2\jsunit\app\jsUnitCore.js"></script> <script type="text/javascript"> //测试套件名必定为suite function suite() { var testSuite = new top.jsUnitTestSuite(); // 增长的测试页面的路径是相对于测试运行器(testRunner.html)的路径 // 而不是当前页面 testSuite.addTestPage("../../jsUnit_code/test1.html"); testSuite.addTestPage("../../jsUnit_code/test1.html"); testSuite.addTestPage("../../jsUnit_code/test1.html"); return testSuite; // 最后须要返回套件 } </script> </head> <body> </body> </html>
测试套件的使用例子2: test3.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title> New Document </title> <meta name="Generator" content="EditPlus"> <meta name="Author" content=""> <meta name="Keywords" content=""> <meta name="Description" content=""> <script type="text/javascript" src="..\jsunit2_2\jsunit\app\jsUnitCore.js"></script> <script type="text/javascript"> // 自定义的测试套件 function mySuite() { var testSuite = new top.jsUnitTestSuite(); testSuite.addTestPage("../../jsUnit_code/test1.html"); testSuite.addTestPage("../../jsUnit_code/test1.html"); testSuite.addTestPage("../../jsUnit_code/test1.html"); return testSuite; } function suite() { var testSuite = new top.jsUnitTestSuite(); testSuite.addTestPage("../../jsUnit_code/test1.html"); // 在测试套件中加入页面 testSuite.addTestSuite(mySuite()); // 在测试套件中加入测试套件 return testSuite; // 记得返回套件 } </script> </head> <body> </body> </html>
圣思园张龙老师Java Web培训视频教程: 60-62.
JsUnit官网: http://jsunit.net/