NST JavaScript Unit Testing: Difference between revisions
(Another typo) |
|||
(8 intermediate revisions by the same user not shown) | |||
Line 18: | Line 18: | ||
* Verify that expected behaviors are supported by all supported browser environments. | * Verify that expected behaviors are supported by all supported browser environments. | ||
* Be simple to run (simply loading: [http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/TestSuite.html TestSuite.html] into your browser runs all of the unit tests for the NST project). | * Be simple to run (simply loading: [http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/TestSuite.html TestSuite.html] into your browser runs all of the unit tests for the NST project). | ||
* Be usable by anyone wanting to unit test JavaScript code. | |||
== What JavaScript Unit Tests Don't Do == | == What JavaScript Unit Tests Don't Do == | ||
Line 29: | Line 30: | ||
== Skills == | == Skills == | ||
Before proceeding with unit testing, it is recommended that | Before proceeding with unit testing, it is recommended that: | ||
* | * You have a basic understanding of what unit testing means. | ||
* | * You know how to use a web browser to load HTML pages directly from your file system. | ||
* | * You know how to use a text editor to create and modify JavaScript code. | ||
* | * You know how to write JavaScript code and have a basic understanding of JavaScript objects (creating classes) and the JavaScript ''prototype'' keyword. | ||
== Files/Directories == | == Files/Directories == | ||
To add unit testing capabilities to a existing project, create a sub-directory named ''test'' and install the following files into it: | To add unit testing capabilities to a existing project, create a sub-directory named ''test'' and install the following files into it: | ||
; [http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/UnitTest.js UnitTest.js] | |||
: This file implements the JavaScript unit testing framework. All test cases you create for your JavaScript code will extend themselves from this class. | |||
; [http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/UnitTest.css UnitTest.css] | |||
: This file provides some style information for display the results of running the unit tests within a HTML page. | |||
; [http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/TestSuiteTemplate.html TestSuiteTemplate.html] | ; [http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/TestSuiteTemplate.html TestSuiteTemplate.html] | ||
: This file can be saved as ''TestSuite.html''. It will become the file you load into your web browser when you want to run your unit tests. | : This file can be saved as ''TestSuite.html''. It will become the file you load into your web browser when you want to run your unit tests. | ||
; [http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/TestUnitTest.js TestUnitTest.js] | |||
: This file provides an example set of unit tests (for a function in the UnitTest.js file). You won't need this file in the long run, but it is loaded and run by the default [http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/TestSuiteTemplate.html TestSuiteTemplate.html] template file. | |||
= Walk Through = | = Walk Through = | ||
The following section explains how to use the JavaScript unit testing framework by example. | |||
In this example, the goal will be to test two JavaScript functions (each declared in their own file). The functions implemented are designed to behave similar to the '''basename''' and '''dirname''' commands one finds on many Unix systems. | |||
== Two JavaScript Source Files To Unit Test == | == Two JavaScript Source Files To Unit Test == | ||
The JavaScript files to be tested in these examples are minimal in size to help keep the instructions clear. In the real world, you would expect to see a lot more functions and classes defined in a single JavaScript file. | |||
=== basename.js === | === basename.js === | ||
Our example ''basename'' implementation can be downloaded from: | |||
[http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/examples/basename.js basename.js] | |||
=== dirname.js === | === dirname.js === | ||
Our example ''dirname'' implementation can be downloaded from: | |||
[http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/examples/dirname.js dirname.js] | |||
== Downloading and Installing JavaScript Unit Testing Support == | |||
* Create the ''test'' sub directory. | |||
* Download and install [http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/UnitTest.js test/UnitTest.js] into the ''test'' sub directory. | |||
* Download and install [http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/UnitTest.css test/UnitTest.css] into the ''test'' sub directory. | |||
* Download and install [http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/TestUnitTest.js test/TestUnitTest.js] into the ''test'' sub directory. | |||
* Download and install [http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/TestSuiteTemplate.html test/TestSuiteTemplate.html] into the ''test'' sub directory. | |||
* Rename ''test/TestSuiteTemplate.html'' to ''test/TestSuite.html''. | |||
== Adding Unit Test Files == | |||
=== TestBaseName.js === | |||
[http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/examples/test/TestBaseName.js test/TestBaseName.js] | |||
=== TestDirName.js === | |||
[http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/examples/test/TestDirName.js test/TestDirName.js] | |||
== Updating The TestSuite.html File == | |||
You will need to edit the ''TestSuite.html'' file you downloaded in the following manner: | |||
* Find "STEP 1" in ''TestSuite.html'' and update it to include your two new unit test classes. Change: | |||
var unitTests = [ | |||
new TestUnitTest() | |||
]; | |||
To: | |||
var unitTests = [ | |||
new TestBaseName(), | |||
new TestDirName() | |||
]; | |||
* Add the JavaScript code to be unit tested by finding "STEP 2" in ''TestSuite.html'' and updating the <script> statements (look ABOVE the comment) from: | |||
<!-- script src="../YourJavaScriptFile.js" type="text/javascript"></script --> | |||
To: | |||
<script src="../basename.js" type="text/javascript"></script> | |||
<script src="../dirname.js" type="text/javascript"></script> | |||
* Add the JavaScript unit tests files by finding "STEP 2" in ''TestSuite.html'' and update the <script> statements (look ABOVE the comment) from: | |||
<script src="TestUnitTest.js" type="text/javascript"></script> | |||
To: | |||
<script src="TestBaseName.js" type="text/javascript"></script> | |||
<script src="TestDirName.js" type="text/javascript"></script> | |||
* You may optionally remove the ''TestUnitTest.js'' file as it should no longer be referenced after the above updates. | |||
== Running The Unit Tests and Reviewing The Results == | |||
The following is what you should see if you've completed all of the steps in this walk through: | |||
[http://nst.svn.sourceforge.net/viewvc/nst/trunk/include/javascript/test/examples/test/TestSuite.html TestSuite.html] | |||
Notice that there is a failure in one of the unit tests. You can click on the links next to the failure to help drill down to the details of the failure. | |||
When you drill down, you'll notice that the test failed because it expected the ''basename'' of "/var/log/" to be "log" and that the actual implementation produced "". | |||
This error was left in the example to demonstrate the power of using unit tests to help eliminate ambiguity from your code. If you look at the source for this unit test, you notice a comment that indicates that the unit test wasn't really sure what the results should be when passing "/var/log/" to the ''basename'' function. At this point we can proceed to reconcile the discrepency by either updating the ''basename'' function to return "log" in this case, or updating the unit test to expect "". We are forced into thinking about what the correct behavior should be in this case. |
Latest revision as of 10:14, 22 September 2010
Overview
Over the years, we have accumulated numerous JavaScript functions and classes which we use as building blocks when creating the NST website (http://networksecuritytoolkit.org) and the web based user interface (NST WUI) for the Network Security Toolkit distribution.
As we rely on our core set of JavaScript building blocks to perform their tasks in a reliable manner, it became desirable to have a method which would allow us to quickly verify that these building blocks behaved in a consistent manner.
After being exposed to the power of the JUnit (http://junit.org/) unit testing framework for Java based code, we decided to create a unit testing framework for our JavaScript code.
The framework we came up with permits us (actually anyone) to quickly verify that various JavaScript functions and classes are behaving as expected simply by loading the following page into a web browser:
This Wiki page describes the conventions used in our JavaScript unit testing framework. This framework was designed such that it can be used outside of the NST development area (anyone with JavaScript code they would like to apply unit tests to is free to follow these conventions as well).
Goals of JavaScript Unit Tests
- Verify expected behaviors of simple JavaScript functions and classes.
- Verify that expected behaviors are supported by all supported browser environments.
- Be simple to run (simply loading: TestSuite.html into your browser runs all of the unit tests for the NST project).
- Be usable by anyone wanting to unit test JavaScript code.
What JavaScript Unit Tests Don't Do
- Test service based behaviors (AJAX based features are difficult to unit test).
- Test modifications to the active document (DOM changes are difficult to unit test).
- Test visual renderings or appearance of rendered pages.
Requirements
Skills
Before proceeding with unit testing, it is recommended that:
- You have a basic understanding of what unit testing means.
- You know how to use a web browser to load HTML pages directly from your file system.
- You know how to use a text editor to create and modify JavaScript code.
- You know how to write JavaScript code and have a basic understanding of JavaScript objects (creating classes) and the JavaScript prototype keyword.
Files/Directories
To add unit testing capabilities to a existing project, create a sub-directory named test and install the following files into it:
- UnitTest.js
- This file implements the JavaScript unit testing framework. All test cases you create for your JavaScript code will extend themselves from this class.
- UnitTest.css
- This file provides some style information for display the results of running the unit tests within a HTML page.
- TestSuiteTemplate.html
- This file can be saved as TestSuite.html. It will become the file you load into your web browser when you want to run your unit tests.
- TestUnitTest.js
- This file provides an example set of unit tests (for a function in the UnitTest.js file). You won't need this file in the long run, but it is loaded and run by the default TestSuiteTemplate.html template file.
Walk Through
The following section explains how to use the JavaScript unit testing framework by example.
In this example, the goal will be to test two JavaScript functions (each declared in their own file). The functions implemented are designed to behave similar to the basename and dirname commands one finds on many Unix systems.
Two JavaScript Source Files To Unit Test
The JavaScript files to be tested in these examples are minimal in size to help keep the instructions clear. In the real world, you would expect to see a lot more functions and classes defined in a single JavaScript file.
basename.js
Our example basename implementation can be downloaded from:
dirname.js
Our example dirname implementation can be downloaded from:
Downloading and Installing JavaScript Unit Testing Support
- Create the test sub directory.
- Download and install test/UnitTest.js into the test sub directory.
- Download and install test/UnitTest.css into the test sub directory.
- Download and install test/TestUnitTest.js into the test sub directory.
- Download and install test/TestSuiteTemplate.html into the test sub directory.
- Rename test/TestSuiteTemplate.html to test/TestSuite.html.
Adding Unit Test Files
TestBaseName.js
TestDirName.js
Updating The TestSuite.html File
You will need to edit the TestSuite.html file you downloaded in the following manner:
- Find "STEP 1" in TestSuite.html and update it to include your two new unit test classes. Change:
var unitTests = [ new TestUnitTest() ];
To:
var unitTests = [ new TestBaseName(), new TestDirName() ];
- Add the JavaScript code to be unit tested by finding "STEP 2" in TestSuite.html and updating the <script> statements (look ABOVE the comment) from:
<!-- script src="../YourJavaScriptFile.js" type="text/javascript"></script -->
To:
<script src="../basename.js" type="text/javascript"></script> <script src="../dirname.js" type="text/javascript"></script>
- Add the JavaScript unit tests files by finding "STEP 2" in TestSuite.html and update the <script> statements (look ABOVE the comment) from:
<script src="TestUnitTest.js" type="text/javascript"></script>
To:
<script src="TestBaseName.js" type="text/javascript"></script> <script src="TestDirName.js" type="text/javascript"></script>
- You may optionally remove the TestUnitTest.js file as it should no longer be referenced after the above updates.
Running The Unit Tests and Reviewing The Results
The following is what you should see if you've completed all of the steps in this walk through:
Notice that there is a failure in one of the unit tests. You can click on the links next to the failure to help drill down to the details of the failure.
When you drill down, you'll notice that the test failed because it expected the basename of "/var/log/" to be "log" and that the actual implementation produced "".
This error was left in the example to demonstrate the power of using unit tests to help eliminate ambiguity from your code. If you look at the source for this unit test, you notice a comment that indicates that the unit test wasn't really sure what the results should be when passing "/var/log/" to the basename function. At this point we can proceed to reconcile the discrepency by either updating the basename function to return "log" in this case, or updating the unit test to expect "". We are forced into thinking about what the correct behavior should be in this case.