1.新建一個html頁面,如下
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Collection Test</title> <link rel="stylesheet" href="SlickGrid/lib/qunit.css" type="text/css"/> <script type="text/javascript" src="SlickGrid/lib/qunit.js"> </script> <script type="text/javascript" src="collections.js"> </script> <script type="text/javascript" src="ArrayListTest.js"> </script> <script type="text/javascript" src="MapTest.js"> </script> </head> <body> <h1 id="qunit-header">ArrayList And Map Test</h1> <h2 id="qunit-banner"></h2> <h2 id="qunit-userAgent"></h2> <ol id="qunit-tests"> </ol> <div id="qunit-fixture"> </div> </body> </html>
在頁面中引入qunit.js和qunit.css, 可以去官網下載:http://qunitjs.com/
引入你要測試的js
// 封裝ArrayList類,用法與java類似。 (function(win){ var ArrayList = function(array){ var datas = []; this.setDatas = function(value){ datas = value; }; this.getDatas = function(){ return datas; }; if (array && Object.prototype.toString.call(array) === "[object Array]") { this.setDatas(array); } }; var proto = ArrayList.prototype; // ArrayList的大小 proto.size = function(){ return this.getDatas().length; }; // 判斷是否為空 proto.isEmpty = function(){ return this.size() === 0; }; // 判斷是否包含指定的值 proto.contains = function(value){ return this.indexOf(value) !== -1; }; // 查詢指定的值,如果找到,返回它所在的陣列下標 proto.indexOf = function(value){ var datas = this.getDatas(); for (var index = 0, len = datas.length; index < len; index++) { if (datas[index] === value) { return index; } } return -1; }; // 從後往前找指定的值 proto.lastIndexOf = function(value){ var datas = this.getDatas(); for (var index = datas.length - 1; index >= 0; index--) { if (datas[index] === value) { return index; } } return -1; }; // 把ArrayList轉化為陣列 proto.toArray = function(){ return this.getDatas(); }; // 判斷是否超出範圍 proto.outOfBound = function(index){ return index < 0 || index > (this.size() - 1); }; // 根據位置取得指定的值 proto.get = function(index){ var datas = this.getDatas(); if (this.outOfBound(index)) { return null; } return datas[index]; }; // 根據位置設定指定的值 proto.set = function(index, value){ var datas = this.getDatas(); datas[index] = value; }; // 增加指定的值 proto.add = function(value){ var datas = this.getDatas(); datas.push(value); }; // 在指定的位置插入值 proto.insert = function(index, value){ var datas = this.getDatas(); if (this.outOfBound(index)) { return false; } datas.splice(index, 0, value); return true; }; // 刪除指定位置的值 proto.remove = function(index){ var datas = this.getDatas(); if (this.outOfBound(index)) { return false; } datas.splice(index, 1); return true; }; // 刪除指定的值 proto.removeValue = function(value){ if (this.contains(value)) { this.remove(this.indexOf(value)); return true; } return false; }; // 清空ArrayList proto.clear = function(){ this.getDatas().length = 0; }; // 把另一個ArrayList新增到當前ArrayList中 proto.addAll = function(list){ if (!list instanceof ArrayList) { return false; } var datas = list.getDatas(); for (var index = 0, len = datas.length; index < len; index++) { this.add(list.get(index)); } return true; }; // 在指定位置插入一個ArrayList proto.insertAll = function(index, list){ if (this.outOfBound(index)) { return false; } if (!list instanceof ArrayList) { return false; } var pos = index; var datas = list.getDatas(); for (index = 0, len = datas.length; index < datas.length; index++) { this.insert(pos++, list.get(index)); } return true; }; // 按數字排序 function numberorder(a, b){ return a - b; } // 排序,isNumber為true表示按數字排序 proto.sort = function(isNumber){ var datas = this.getDatas(); if (isNumber) { datas.sort(numberorder); } else { datas.sort(); } }; // 重寫toString方法 proto.toString = function(){ var datas = this.getDatas(); return "[" + datas.join() + "]"; }; // 重寫valueOf方法 proto.valueOf = function(){ return this.toString(); }; win.ArrayList = ArrayList; })(window); // 封裝map類,用法與java類似 (function(win){ var Map = function(obj){ var count = 0; var entrySet = {}; this.setCount = function(value){ count = value; }; this.getCount = function(){ return count; }; this.setEntrySet = function(value){ entrySet = value; }; this.getEntrySet = function(){ return entrySet; }; if (obj && Object.prototype.toString.call(obj) === "[object Object]") { this.setEntrySet(obj); var key = null; for (key in obj) { count++; } } }; var proto = Map.prototype; // map的大小 proto.size = function(){ return this.getCount(); }; // 判斷map是否為空 proto.isEmpty = function(){ return this.size() === 0; }; // 判斷map是否包含指定的key proto.containsKey = function(key){ if (this.isEmpty()) { return false; } var entrySet = this.getEntrySet(); return entrySet.hasOwnProperty(key); }; // 判斷map是否包含指定的值 proto.containsValue = function(value){ var entrySet = this.getEntrySet(); if (this.isEmpty()) { return false; } var key = null; for (key in entrySet) { if (entrySet[key] === value) { return true; } } return false; }; // 根據key取得相應的value proto.get = function(key){ var entrySet = this.getEntrySet(); if (this.isEmpty()) { return null; } if (this.containsKey(key)) { return entrySet[key]; } return null; }; // 把鍵值對放入到map中 proto.put = function(key, value){ var entrySet = this.getEntrySet(); if (!entrySet.hasOwnProperty(key)) { var count = this.getCount(); this.setCount(count + 1); } entrySet[key] = value; this.setEntrySet(entrySet); }; // 移除指定鍵值對 proto.remove = function(key){ if (this.isEmpty()) { return false; } if (this.containsKey(key)) { var entrySet = this.getEntrySet(); var count = this.getCount(); delete entrySet[key]; count--; this.setCount(count); this.setEntrySet(entrySet); return true; } else { return false; } }; // 把指定map放入到當前map中 proto.putAll = function(map){ if (!map instanceof Map) { return false; } var entrySet = map.getEntrySet(); var key = null; for (key in entrySet) { this.put(key, entrySet[key]); } return true; }; // 清除當前map proto.clear = function(){ this.setEntrySet({}); this.setCount(0); }; // 取得當前map中的所有值,返回 一個陣列 proto.values = function(){ var result = []; var entrySet = this.getEntrySet(); var key = null; for (key in entrySet) { result.push(entrySet[key]); } return result; }; // 取得當前map中的所有鍵,返回一個陣列 proto.keySet = function(){ var result = []; var entrySet = this.getEntrySet(); var key = null; for (key in entrySet) { result.push(key); } return result; }; proto.entrySet = function(){ return this.getEntrySet(); }; // 重寫toString方法 proto.toString = function(){ var result = []; var entrySet = this.getEntrySet(); var key = null; for (key in entrySet) { result.push(key + ":" + entrySet[key]); } return "{" + result.join() + "}"; }; // 重寫valueOf方法 proto.valueOf = function(){ return this.toString(); }; win.Map = Map; })(window);
引入你將要編寫的測試的js
body裡的內容固定如上圖。
2.寫自己的測試程式碼
(function(){ var list = null; module("ArrayList", { setup: function(){ list = new ArrayList(); }, teardown: function(){ list = null; } }); test("constructor", function(){ ok(list.isEmpty(), "new ArrayList() is Empty."); list = new ArrayList([1, 2, 3, 4]); equals(4, list.size(), "new ArrayList([1,2,3,4]), list.size()"); list = new ArrayList(null); equals(0, list.size(), "new ArrayList(null), list.size()"); }); test("setDatas", function(){ list.setDatas([8, 6, 3, 7, 9]); equals(5, list.size(), "list.setDatas([8,6,3,7,9]); list.size()"); equals("[8,6,3,7,9]", list.toString(), "list.toString()"); }); test("getDatas", function(){ list.setDatas([8, 6, 3, 7, 9]); equals(5, list.getDatas().length, "list.setDatas([8,6,3,7,9]); list.getDatas().length"); equals("8,6,3,7,9", list.getDatas().toString(), "list.getDatas().toString()"); }); test("size", function(){ equals(0, list.size(), "only call constructor, list.size()"); list.add(1); list.add(2); list.add(3); equals(3, list.size(), "call add method three times, list.size()"); }); test("isEmpty", function(){ equals(true, list.isEmpty(), "only call constructor, list.isEmpty()"); list.add(1); equals(false, list.isEmpty(), "call add method one times, list.isEmpty()"); }); test("contains", function(){ list.add(1); list.add(2); equals(true, list.contains(1), "list is [1,2], list.contains(1)"); equals(true, list.contains(2), "list is [1,2], list.contains(2)"); equals(false, list.contains(3), "list is [1,2], list.contains(3)"); }); test("indexOf", function(){ list.add(1); list.add(2); equals(0, list.indexOf(1), "list is [1,2], list.indexOf(1)"); equals(1, list.indexOf(2), "list is [1,2], list.indexOf(2)"); equals(-1, list.indexOf(3), "list is [1,2], list.indexOf(3)"); }); test("lastIndexOf", function(){ list.add(1); list.add(2); equals(0, list.lastIndexOf(1), "list is [1,2], list.lastIndexOf(1)"); equals(1, list.lastIndexOf(2), "list is [1,2], list.lastIndexOf(2)"); equals(-1, list.lastIndexOf(3), "list is [1,2], list.lastIndexOf(3)"); }); test("toArray", function(){ list.add(1); list.add(2); equals("1,2", list.toArray().toString(), "list is [1,2], list.toArray() is"); same(list.getDatas(), list.toArray()); }); test("outOfBound", function(){ list.add(1); list.add(2); same(true, list.outOfBound(-1), "list is [1,2], list.outOfBound(-1) is"); same(false, list.outOfBound(0), "list is [1,2], list.outOfBound(0) is"); same(false, list.outOfBound(1), "list is [1,2], list.outOfBound(1) is"); same(true, list.outOfBound(2), "list is [1,2], list.outOfBound(2) is"); }); test("get", function(){ list.add("jack"); list.add("mary"); same("jack", list.get(0), "list is [jack, mary], list.get(0) is"); same("mary", list.get(1), "list is [jack, mary], list.get(1) is"); }); test("set", function(){ list.add("jack"); list.set(1, "mary"); same("mary", list.get(1), 'list.set(1, "mary"); list.get(1) is'); list.set(0, "mike"); same("mike", list.get(0), 'list.set(0, "mike"); list.get(0) is'); }); test("add", function(){ list.add(10); list.add(20); equal(10, list.get(0), "list add after is [10,20], list.get(0) is"); equal(20, list.get(1), "list add after is [10,20], list.get(1) is"); }); test("insert", function(){ list.add(10); list.add(20); list.insert(0, 30); equal(30, list.get(0), "list is [10,20], list.insert(0, 30), list.get(0) is"); list.insert(2, 6); equal(6, list.get(2), "list is [30,10,20], list.insert(2, 6), list.get(2) is"); }); test("remove", function(){ list.add(1); list.add(2); equal(true, list.remove(0), "list is [1, 2], list.remove(0) is "); list.clear(); equal(false, list.remove(0), "list is [], list.remove(0) is "); }); test("removeValue", function(){ list.add("jack"); list.add("mike"); equal(true, list.removeValue("jack"), "list is ['jack', 'mike'], list.removeValue('jack') is"); list.clear(); equal(false, list.removeValue("jack"), "list is [], list.removeValue('jack') is"); }); test("clear", function(){ list.add(10); list.add(20); ok(!list.isEmpty(), "Before call clear, list is " + list.toString()); list.clear(); ok(list.isEmpty(), "After call clear, list is " + list.toString()); }); test("addAll", function(){ var tmpList = new ArrayList([10, 20]); list.addAll(tmpList); same(list.getDatas(), tmpList.getDatas(), "tmpList is [10,20], list.addAll(tmpList), list is "); }); test("insertAll", function(){ var tmpList = new ArrayList([10, 20]); list.add(30); list.insertAll(0, tmpList); same(10, list.get(0), "tmpList is [10,20], list is [30], list.insertAll(0, tmpList), list.get(0) is "); same(20, list.get(1), "tmpList is [10,20], list is [30], list.insertAll(0, tmpList), list.get(1) is "); same(30, list.get(2), "tmpList is [10,20], list is [30], list.insertAll(0, tmpList), list.get(2) is "); same(3, list.size(), "list.size() is "); }); test("sort", function(){ list.setDatas([6, 9, 3, 1, 5]); list.sort(true); same("[1,3,5,6,9]", list.toString(), "list is [6,9,3,1,5], list.sort(true), list is "); list.clear(); list.setDatas([4, 33, 222, 1111]); list.sort(); same("[1111,222,33,4]", list.toString(), "list is [4,33,222,1111], list.sort(), list is "); }); test("toString", function(){ list.setDatas([6, 9, 3]); same("[6,9,3]", list.toString(), "list is [6, 9, 3], list.toString() is "); }); test("valueOf", function(){ list.setDatas([6, 9, 3]); same("[6,9,3]", list.valueOf(), "list is [6, 9, 3], list.toString() is "); }); })();
(function(){ var map = null; module("Map", { setup: function(){ map = new Map(); map.put("v001", "jack"); map.put("v002", "mike"); }, teardown: function(){ map = null; } }); test("constructor", function(){ map = new Map(); ok(map.isEmpty(), "only call constructor, map is empty."); map = new Map({ 'v001': 'jack', 'v002': 'mike' }); equal("jack", map.get('v001'), "new Map({'v001' : 'jack', 'v002': 'mike'}), map.get('v001') is"); equal("mike", map.get('v002'), "new Map({'v001' : 'jack', 'v002': 'mike'}), map.get('v002') is"); }); test("put size", function(){ equal(2, map.size(), "call put two times, the key not same, map.size() is"); map.put("v002", "lucy"); equal(2, map.size(), "call put three times , the last time, the key is repeat, map.size() is"); }); test("isEmpty", function(){ equal(false, map.isEmpty(), "call put two times, map.isEmpty() is"); }); test("containsKey", function(){ equal(true, map.containsKey("v001"), "map is {'v001' : 'jack', 'v002': 'mike'}, map.containsKey('v001') is"); equal(true, map.containsKey("v002"), "map is {'v001' : 'jack', 'v002': 'mike'}, map.containsKey('v002') is"); equal(false, map.containsKey("v003"), "map is {'v001' : 'jack', 'v002': 'mike'}, map.containsKey('v003') is"); }); test("containsValue", function(){ equal(true, map.containsValue("jack"), "map is {'v001' : 'jack', 'v002': 'mike'}, map.containsValue('jack') is"); equal(true, map.containsValue("mike"), "map is {'v001' : 'jack', 'v002': 'mike'}, map.containsValue('mike') is"); equal(false, map.containsValue("lucy"), "map is {'v001' : 'jack', 'v002': 'mike'}, map.containsValue('lucy') is"); }); test("get", function(){ equal("jack", map.get("v001"), "map is {'v001' : 'jack', 'v002': 'mike'}, map.get('v001') is"); equal("mike", map.get("v002"), "map is {'v001' : 'jack', 'v002': 'mike'}, map.get('v002') is"); }); test("remove", function(){ equal(true, map.remove("v001"), "map is {'v001' : 'jack', 'v002': 'mike'}, map.remove('v001') is"); equal(false, map.remove("v003"), "map is {'v001' : 'jack', 'v002': 'mike'}, map.remove('v003') is"); }); test("putAll", function(){ var map2 = new Map(); map2.putAll(map); equal(map.size(), map2.size(), "map2 is empty, map2.putAll(map), map2.size() is "); }); test("clear", function(){ equal(2, map.size(), "before call clear method, map.size() is "); map.clear(); equal(0, map.size(), "after call clear method, map.size() is "); }); test("values", function(){ equal('jack,mike', map.values().join(), "map is {'v001' : 'jack', 'v002': 'mike'}, map.values() is "); }); test("keySet", function(){ equal('v001,v002', map.keySet().join(), "map is {'v001' : 'jack', 'v002': 'mike'}, map.keySet() is "); }); test("entrySet", function(){ var map2 = new Map(map.entrySet()); equal('{v001:jack,v002:mike}', map2.toString(), "map is {'v001' : 'jack', 'v002': 'mike'}, map.entrySet() is "); }); test("toString", function(){ equal('{v001:jack,v002:mike}', map.toString(), "map is {'v001' : 'jack', 'v002': 'mike'}, map.toString() is "); }); test("valueOf", function(){ equal('{v001:jack,v002:mike}', map.valueOf(), "map is {'v001' : 'jack', 'v002': 'mike'}, map.valueOf() is "); }); })();
module有兩個主要的方法:setup和teardown, 分別是在方法呼叫前和呼叫後執行。
test("", function(){}); 表示執行一個測試用例
用於診斷的方法主要有:equals、equal、same、deepEqual、notEqual、notDeepEqual、strictEqual、notStrictEqual、ok、expect
詳細用法見官方文件。