Js 单元测试框架介绍
- 3. Jörn Zaefferer : QUnit是一个JavaScript
单元测试框架,主要用于在浏览器中运行单
元测试。虽然这个项目从属于jQuery,但却
不依赖于jQuery,也不依赖于浏览器DOM。
因此你也可以在node.js或Rhino上使用。
QUnit很容易学习,你只需在html页面中包
含两个文件,��需要安装或者构建任何其他
东西。最短的测试集只需要一个11行的html
文件。
特点:
1.使用方便,界面美观
2.支持异步
3.手工加载
4.对html文件有约束
4.适合开发调试阶段使用
- 4. Davis Frank: Jasmine是一个 JavaScript
测试框架,目的是将BDD风格引入
JavaScript测试之中。至于区别嘛,我们的
目标是BDD(相比标准的TDD),因此我们尽
力帮助开发人员编写比一般xUnit框架表达
性更强,组织更好的代码。此外我们还力图
减少依赖,这样你可以在node.js上使用
Jasmine,也可以在浏览器或移动程序中使
用。
特点:
1.语法简洁,describe ,it
2.Browsers,servers,phones,etc
3.支持自定义Matchers
4.beforeEach()、afterEach()、
Single-spec After functions
5.spies,mock
6.异步,runs(),waits(),waitsFor()
- 5. YUI Test features:
Rapid creation of test cases through simple syntax.
Advanced failure detection for methods that throw errors.
Grouping of related test cases using test suites.
Mock objects for writing tests without external dependencies.
Asynchronous tests for testing events and Ajax communication.
DOM Event simulation in all A-grade browsers (through Event).
- 6. 引入测试框架
YUITest Standalone Library
<script src="http://192.168.194.159/test/yuitest/yuitest.js"></script>
YUI Test for YUI 3.x
<script src="http://192.168.194.159/test/yui/build/yui/yui.js"></script>
// Create a new YUI instance and populate it with the required modules.
YUI().use('test', function (Y) {
// Test is available and ready for use. Add implementation
// code here.
});
- 7. Using Test Cases
YUITest Standalone Library
var testCase = new YUITest.TestCase({
name: "TestCase Name",
//traditional test names
testSomething : function () {
//...
},
testSomethingElse : function () {
//...
}
});
var testCase = new YUITest.TestCase({
name: "TestCase Name",
//friendly test names
"Something should happen here" : function () {
//...
},
"Something else should happen here" : function () {
//...
}
});
- 8. Using Test Cases
YUI Test for YUI 3.x
var testCase = new Y.Test.Case({
name: "TestCase Name",
//traditional test names
testSomething : function () {
//...
},
testSomethingElse : function () {
//...
}
});
var testCase = new Y.Test.Case({
name: "TestCase Name",
//friendly test names
"Something should happen here" : function () {
//...
},
"Something else should happen here" : function () {
//...
}
});
- 9. setUp() and tearDown()
var testCase = new YUITest.TestCase({
name: "TestCase Name",
//---------------------------------------------
// Setup and tear down
//---------------------------------------------
setUp : function () {
this.data = { name : "Nicholas", age : 28 };
},
tearDown : function () {
delete this.data;
},
//---------------------------------------------
// Tests
//---------------------------------------------
testName: function () {
YUITest.Assert.areEqual("Nicholas", this.data.name, "Name should be 'Nicholas'");
},
testAge: function () {
YUITest.Assert.areEqual(28, this.data.age, "Age should be 28");
}
});
- 10. init() and destroy()
var testCase = new YUITest.TestCase({
name: "TestCase Name",
//---------------------------------------------
// init and destroy
//---------------------------------------------
init : function () {
this.data = { name : "Nicholas", age : 28 };
},
destroy : function () {
delete this.data;
},
//---------------------------------------------
// Tests
//---------------------------------------------
testName: function () {
YUITest.Assert.areEqual("Nicholas", this.data.name, "Name should be 'Nicholas'");
},
testAge: function () {
YUITest.Assert.areEqual(28, this.data.age, "Age should be 28");
}
});
- 11. Ignoring Tests
var testCase = new YUITest.TestCase({
name: "TestCase Name",
//---------------------------------------------
// Special instructions
//---------------------------------------------
_should: {
ignore: {
testName: true //ignore this test
}
},
//---------------------------------------------
// Tests
//---------------------------------------------
testName: function () {
YUITest.Assert.areEqual("Nicholas", this.data.name, "Name should be 'Nicholas'");
},
testAge: function () {
YUITest.Assert.areEqual(28, this.data.age, "Age should be 28");
}
});
- 12. Intentional Errors
testGenericError : function() {
YUITest.Assert.throwsError(Error, function() {
throw new Error("Generic error");
});
},
testStringError : function() {
YUITest.Assert.throwsError("I'm a specific error message.", function() {
throw new Error("I'm a specific error message.");
});
},
testObjectError : function() {
YUITest.Assert.throwsError(new TypeError("Number expected."), function() {
throw new TypeError("Number expected.");
});
},
- 13. Assertions
Equality Assertions Sameness Assertions Forced Failures
areEqual() areNotSame() fail()
areNotEqual() areSame()
Special Value Assertions Data Type Assertions
isFalse() isArray()
isTrue() isBoolean()
isNaN() isFunction()
isNotNaN() isNumber()
isNull() isObject()
isNotNull() isString()
isUndefined() isTypeOf()
isNotUndefined()
- 14. ArrayAssert
contains()
containsItems()
containsMatch()
doesNotContain()
doesNotContainItems()
doesNotContainMatch()
indexOf()
isEmpty()
isNotEmpty()
itemsAreEqual()
itemsAreEquivalent()
itemsAreSame()
lastIndexOf()
- 16. ObjectAssert
hasKey()
hasKeys()
ownsKey()
ownsKeys()
ownsNoKeys()
areEqual()
inheritsKey()
inheritsKeys()
ownsOrInheritsKey()
ownsOrInheritsKeys()
- 17. Mock Objects
//code being tested
function logToServer(message, xhr){
xhr.open("get", "/log.php?msg=" + encodeURIComponent(message), true);
xhr.send(null);
}
//test case for testing the above function
var testCase = new YUITest.TestCase({
name: "logToServer Tests",
testPassingDataToXhr : function () {
var mockXhr = YUITest.Mock();
//I expect the open() method to be called with the given arguments
YUITest.Mock.expect(mockXhr, {
method: "open",
args: ["get", "/log.php?msg=hi", true]
});
//I expect the send() method to be called with the given arguments
YUITest.Mock.expect(mockXhr, {
method: "send",
args: [null]
});
//now call the function
logToServer("hi", mockXhr);
//verify the expectations were met
YUITest.Mock.verify(mockXhr);
}
});
- 18. Special Argument Values
YUITest.Mock.Value.Any - any value is valid regardless of type.
YUITest.Mock.Value.String - any string value is valid.
YUITest.Mock.Value.Number - any number value is valid.
YUITest.Mock.Value.Boolean - any Boolean value is valid.
YUITest.Mock.Value.Object - any non-null object value is valid.
YUITest.Mock.Value.Function - any function value is valid.
YUITest.Mock.expect(mockXhr, {
method: "open",
args: [YUITest.Mock.Value.String, "/log.php?msg=hi“, YUITest.Mock.Value.Boolean]
});
- 19. Property Expectations
var testCase = new YUITest.TestCase({
name : "TestCase Name",
testMock : function() {
var mockMyObject = YUITest.Mock();
YUITest.Mock.expect(mockMyObject,{
method: "add",
args: [1,2],
returns: 3,
property: "status",
value: 404
});
var result = mockMyObject.add(1,2);
mockMyObject.status = 100;
Assert.areEqual(3,result,"1 + 2 = 3");
YUITest.Mock.verify(mockMyObject);
}
});
- 20. Asynchronous Tests
var testCase = new YUITest.TestCase({
name: "TestCase Name",
setUp : function () {
this.data = { name : "Nicholas", age : 29 };
},
tearDown : function () {
delete this.data;
},
testAsync: function () {
YUITest.Assert.areEqual("Nicholas", this.data.name, "Name should be 'Nicholas'");
//wait 1000 milliseconds and then run this function
this.wait(function(){
YUITest.Assert.areEqual(29, this.data.age, "Age should be 29");
}, 1000);
}
});
- 21. Asynchronous Tests
var testCase = new YUITest.TestCase({
name: "TestCase Name",
testAnimation : function (){
//animate width to 400px
var myAnim = new Y.Anim({
node: '#testDiv',
to: {width: 400},
duration: 3});
var test = this;
//assign oncomplete handler
myAnim.on("end", function(){
//tell the TestRunner to resume
test.resume(function(){
YUITest.Assert.areEqual(myAnim.get("node").get("offsetWidth"), 400, "Width of the
DIV should be 400.");
});
});
//start the animation
myAnim.run();
//wait until something happens
this.wait(3000);
}
});
- 22. Test Suites
//create the test suite
var suite = new YUITest.TestSuite("TestSuite Name");
//add test cases
suite.add(new YUITest.TestCase({
//...
}));
suite.add(new YUITest.TestCase({
//...
}));
//add the second suite to the first
suite.add(anotherSuite);
//create a test suite
var suite = new YUITest.TestSuite({
name : "TestSuite Name",
setUp : function () {
//test-suite-level setup
},
tearDown: function () {
//test-suite-level teardown
}
});
- 23. Context Data
var testSuite = new YUITest.TestSuite({
name: "Test Suite Name",
setUp: function(data){
data.topLevel = 1;}
});
testSuite.add(new YUITest.TestCase({
name: "First Test Case",
init: function(data){
data.foo = "bar";},
testValueOfFoo : function (data) {
YUITest.Assert.areEqual("bar", data.foo); //from init
},
testValueOfTopLevel: function(data){
YUITest.Assert.areEqual(1, data.topLevel); //from test suite
}
});
testSuite.add(new YUITest.TestCase({
name: "Second Test Case",
testValueOfFoo : function (data) {
YUITest.Assert.areEqual("bar", data.foo); //from init in First Test Case
},
testValueOfTopLevel: function(data){
YUITest.Assert.areEqual(1, data.topLevel); //from test suite
}
});
- 24. Running Tests
//add the test cases and suites
YUITest.TestRunner.add(testCase);
YUITest.TestRunner.add(testSuite);
//run all tests
YUITest.TestRunner.run();
YUITest.TestRunner.clear();
- 25. TestRunner Events
Test-Level Events
YUITest.TestRunner.TEST_PASS_EVENT - occurs when the test passes.
YUITest.TestRunner.TEST_FAIL_EVENT - occurs when the test fails.
YUITest.TestRunner.TEST_IGNORE_EVENT - occurs when a test is ignored.
For each of these events, the event data object has three properties:
type - indicates the type of event that occurred.
testCase - the test case that is currently being run.
testName - the name of the test that was just executed or ignored.
- 26. TestRunner Events
TestCase-Level Events
YUITest.TestRunner.TEST_CASE_BEGIN_EVENT
occurs when the test case is next to be executed but before the first test
is run.
YUITest.TestRunner.TEST_CASE_COMPLETE_EVENT
occurs when all tests in the test case have been executed or ignored.
For these two events, the event data object has three properties:
type - indicates the type of event that occurred.
testCase - the test case that is currently being run.
- 27. TestRunner Events
TestSuite-Level Events
YUITest.TestRunner.TEST_SUITE_BEGIN_EVENT
occurs when the test suite is next to be executed but before the first
test is run.
YUITest.TestRunner.TEST_SUITE_COMPLETE_EVENT
occurs when all tests in all test cases in the test suite have been
executed or ignored.
For these two events, the event data object has three properties:
type - indicates the type of event that occurred.
testSuite - the test suite that is currently being run.
- 28. TestRunner Events
TestRunner-Level Events
YUITest.TestRunner.BEGIN_EVENT
occurs when testing is about to begin but before any tests are run.
YUITest.TestRunner.COMPLETE_EVENT
occurs when all tests in all test cases and test suites have been executed or ignored.
Subscribing to Events
function handleTestFail(data){
alert("Test named '" + data.testName + "' failed with message: '" +
data.error.message + "'.");
}
var TestRunner = YUITest.TestRunner;
TestRunner.subscribe(TestRunner.TEST_FAIL_EVENT, handleTestFail);
TestRunner.run();
- 29. Viewing Results
YUI({ logInclude: { TestRunner: true } }).use("console", function(Y){
//tests go here
//initialize the console
var yconsole = new Y.Console({
newestOnTop: false
});
yconsole.render('#log');
//run the tests
YUITest.TestRunner.run();
});
- 31. Viewing Results
YUI({ useBrowserConsole: true }).use("test", function(Y){
//tests go here
//get object of results
var resultsObject = YUITest.TestRunner.getResult();
//get XML results
var resultsXML = YUITest.TestRunner.getResult(YUITest.TestFormat.XML);
});
YUITest.TestFormat.XML - YUI Test XML (default)
YUITest.TestFormat.JSON - JSON
YUITest.TestFormat.JUnitXML - JUnit XML
YUITest.TestFormat.TAP - TAP
- 33. Test Reporting
var reporter = new
YUITest.Reporter("http://www.yourserver.com/path/to/target",
YUITest.TestFormat.JSON);
reporter.report(results);
results - the serialized results object.
useragent - the user-agent string of the browser.
timestamp - the date and time that the report was sent.
reporter.addField("color", "blue");
reporter.addField("message", "Hello world!");
- 34. Yeti: YUI’s Easy Testing Interface
Yeti is a command-line tool for launching JavaScript unit tests in a
browser and reporting the results without leaving your terminal. Yeti is
designed to work with existing unmodified YUI-based tests.
Yeti is designed to help you run tests before you commit. It
compliments existing CI tools like Selenium and Hudson which run tests
post-commit. Yeti is not a replacement for those tools.