|
GettingStarted
Writing your first test using Google JS Test.
This document contains a tutorial for writing your first test using the Google JS Test framework. If you haven't yet, you'll need to first follow the instructions on the Installing page to get the gjstest tool set up on your system. IntroductionGoogle JS Test consists of the following parts:
The sections below take you through writing a toy class and testing it with Google JS Test. Code under testFor the purposes of this tutorial, let's assume that we're working on a file called some_functions.js with containing several functions we want to test. Create the file some_functions.js and put the following code in it: // Return some interesting words.
myproject.getSomeWords = function() {
return ['Hello', 'World'];
};
// Add the supplied numbers and then call back with the result.
myproject.addNumbersAndCallBack = function(a, b, resultCallback) {
var result = a + b;
resultCallback(a + b);
};These are just toy functions; you'd probably have something more interesting in your project. Note that the object myproject (serving as a namespace here) has not been defined within this file. Let's suppose its definition is in a separate file, so that it can be shared with other code in your project. Add the following to a file called namespace.js: var myproject = {};Writing testsNow we want to write some tests for the functions defined in some_functions.js, which you created above. Create a new file called some_functions_test.js and put the following into it. (Note that there's nothing special about the filename some_functions_test.js; it's just a convention.) //////////////////////////
// getSomeWords
//////////////////////////
function GetSomeWordsTest() {}
registerTestSuite(GetSomeWordsTest);
GetSomeWordsTest.prototype.ReturnsCorrectWords = function() {
var words = myproject.getSomeWords();
// Assert directly what the words should be.
expectThat(words, elementsAre(['Hello', 'world']));
// Note that you could have also done so as follows, but it doesn't give
// error messages that are as nice.
expectEq(2, words.length);
expectEq('Hello', words[0]);
expectEq('world', words[1]);
};
//////////////////////////
// addNumbersAndCallBack
//////////////////////////
function AddNumbersAndCallBackTest() {
// Create a mock function and store it in a place accessible to the test
// functions below. A new one will be created for each test method.
this.resultCallback_ = createMockFunction();
}
registerTestSuite(AddNumbersAndCallBackTest);
AddNumbersAndCallBackTest.prototype.HandlesPositiveNumbers = function() {
var a = 17;
var b = 23;
// Assert that the mock callback will created above will be called with the
// appropriate result.
expectCall(this.resultCallback_)(40);
// Call the function being tested with the appropriate arguments, including
// our mock callback.
myproject.addNumbersAndCallBack(a, b, this.resultCallback_);
};
AddNumbersAndCallBackTest.prototype.HandlesNegativeNumbers = function() {
var a = -17;
var b = -5;
expectCall(this.resultCallback_)(-22);
myproject.addNumbersAndCallBack(a, b, this.resultCallback_);
};
AddNumbersAndCallBackTest.prototype.ThrowsErrorForStringArg = function() {
// Make sure that if we give a string instead of a number for the first
// argument, the function under test throws an appropriate error.
var trivialCallback = function() {};
var callWithString =
function() {
myproject.addNumbersAndCallBack('foo', 17, trivialCallback);
};
expectThat(callWithString, throwsError(/TypeError.*must be a number/));
};This file defines two test suites, one for each function we're testing. A test suite is a way to group logically related tests that may need to share setup code. For example, the constructor of AddNumbersAndCallBackTest creates a mock function that can be used as a callback in its test methods if desired. Notice a few things about these tests:
Running testsNow we're ready to run the tests we wrote above, making sure that the functions we're testing do the write thing. We do this using the gjstest tool, which we must tell where to find the code. Run the command below: gjstest --js_files=namespace.js,some_functions.js,some_functions_test.js Note that we have to give all of the JS files needed by our test and the code it is testing, and we have to do so in order. If we left out namespace.js or put it after some_functions.js, we'd find that the first time our code accesses myproject it gets an undefined object error. You should see output like the following: [----------] [ RUN ] GetSomeWordsTest.ReturnsCorrectWords some_functions_test.js:12 Expected: is an array or Arguments object of length 2 with elements matching: [ 'Hello', 'world' ] Actual: [ 'Hello', 'World' ], whose element 1 doesn't match some_functions_test.js:18 Expected: 'world' Actual: 'World' [ FAILED ] GetSomeWordsTest.ReturnsCorrectWords (4 ms) [----------] [----------] [ RUN ] AddNumbersAndCallBackTest.HandlesPositiveNumbers [ OK ] AddNumbersAndCallBackTest.HandlesPositiveNumbers (1 ms) [ RUN ] AddNumbersAndCallBackTest.HandlesNegativeNumbers [ OK ] AddNumbersAndCallBackTest.HandlesNegativeNumbers (0 ms) [ RUN ] AddNumbersAndCallBackTest.ThrowsErrorForStringArg some_functions_test.js:64 Expected: is a function that throws an error matching /TypeError.*must be a number/ Actual: function (), which threw no errors [ FAILED ] AddNumbersAndCallBackTest.ThrowsErrorForStringArg (0 ms) [----------] [ FAILED ] It turns out that we have some bugs in our code. Notice how the first error message output in GetSomeWordsTest.ReturnsCorrectWords gives nicer output than the second – it shows the entire array, which is extra important if the array is of the wrong length. Go ahead and fix these bugs, it's left as an exercise to the reader. You'll want to fix the capitilization on the second word returned by getSomeWords, and add type checking logic to addNumbersAndCallBack. Once you do, you should be able to run the gjstest command given above again, and see that your tests pass. |
alert("a")
What is the main advantage of this framework compare to other java script framework ?