Difference between revisions of "Real World Mozilla Unit Testing Lab"

From CDOT Wiki
Jump to: navigation, search
 
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
[[Dive into Mozilla]] > [[Dive into Mozilla Day 4]] > Mozilla Unit Testing Lab
+
[[Real World Mozilla]] > [[Real World Mozilla Day 4]] > Mozilla Unit Testing Lab
  
 
== Overview ==
 
== Overview ==
Line 9: Line 9:
 
== Instructions ==
 
== Instructions ==
  
Mozilla currently uses three unit test methods:
+
Mozilla [http://developer.mozilla.org/en/docs/Mozilla_automated_testing currently uses] three unit test methods:
  
 
# The first is '''xpcshell''' for C++ unit tests that run on the command line. These are the best method to use whenever possible. Using them effectively requires composing code as stateless functions that return values whenever possible--always a good practice.
 
# The first is '''xpcshell''' for C++ unit tests that run on the command line. These are the best method to use whenever possible. Using them effectively requires composing code as stateless functions that return values whenever possible--always a good practice.
Line 17: Line 17:
 
For purposes of testing our FirstXpcom component, we will use xpcshell tests.  This will allow us to easily write tests to insure the functionality of our class's methods.  
 
For purposes of testing our FirstXpcom component, we will use xpcshell tests.  This will allow us to easily write tests to insure the functionality of our class's methods.  
  
You're correct that you find too many tests in the tree :/. We're working on that. browser/components/places/tests have some good examples.
+
* Begin by creating a new directory to hold our tests:
  
 +
$ cd mozilla/extensions/firstxpcom
 +
$ mkdir test
  
 +
* Now copy the xpcshell test-harness code into this directory:
  
 +
$ cd mozilla/extensions/firstxpcom/test
 +
$ cp -r ../../../tools/test-harness/xpcshell-simple/example/* .
  
* Now create some Unit Tests for your component so you can easily test things as you go (see the following for more details -- http://developer.mozilla.org/en/docs/Writing_xpcshell-based_unit_tests)
+
* This will result in the following file/directories being copied to '''test''':
  
- mkdir mozilla/extensions/weblock/test
+
$ ls
- cp mozilla/tools/test-harness/xpcshell-simple/example/ mozilla/extensions/weblock/test
+
CVS  Makefile.in unit
- edit mozilla/extensions/weblock/test/Makefile.in to be:
 
  
-----------start--------------
+
* The file, '''test/Makefile.in''', needs to be modified:
  
DEPTH = ../../..
+
# Note: DEPTH should be set to the relative path to mozilla/
topsrcdir = @top_srcdir@
+
DEPTH = ../../..
srcdir = @srcdir@
+
topsrcdir = @top_srcdir@
VPATH = @srcdir@
+
srcdir = @srcdir@
 +
VPATH = @srcdir@
 +
 +
include $(DEPTH)/config/autoconf.mk
 +
 +
# Note: set the test module's name to test_<yourmodule>
 +
MODULE = test_firstxpcom
 +
 +
# This is a list of directories containing tests to run, separated by spaces.
 +
# Most likely, tho, you won't use more than one directory here.
 +
XPCSHELL_TESTS = unit
 +
 +
include $(topsrcdir)/config/rules.mk
 +
 +
# Note: Invoke any additional (non-xpcshell) test programs here.
 +
check::
  
include $(DEPTH)/config/autoconf.mk
+
* Your component's Makefile needs to include this new test directory.  Modify '''mozilla/extensions/firstxpcom/Makefile.in''' (change shown in bold):
  
MODULE = weblock
+
DEPTH = ../..
 +
topsrcdir = @top_srcdir@
 +
srcdir = @srcdir@
 +
VPATH = @srcdir@
 +
 +
include $(DEPTH)/config/autoconf.mk
 +
 +
MODULE = firstxpcom
 +
 +
DIRS = public \
 +
  src \
 +
  $(NULL)
 +
 +
'''# Adding xpcshell unit tests'''
 +
'''ifdef ENABLE_TESTS'''
 +
'''DIRS  += test'''
 +
'''endif'''
 +
 +
XPI_NAME = firstxpcom
 +
 +
# A Unique ID for your extension
 +
INSTALL_EXTENSION_ID = firstxpcom@senecac.on.ca
 +
 +
# Will create a .xpi in /mozilla/$(MOZ_OBJDIR)/dist/xpi-stage/
 +
XPI_PKGNAME = firstxpcom
 +
 +
# install.rdf will tell Firefox how to install our extension and
 +
# this says, "copy install.rdf into our extension dir and xpi"
 +
DIST_FILES = install.rdf
 +
 +
include $(topsrcdir)/config/rules.mk
  
include $(topsrcdir)/config/rules.mk
+
* Recreate your component's Makefile (make sure you use your own objdir name below):
  
_TEST_FILES = test_all.sh
+
$ cd mozilla/''objdir''
_UNIT_FILES = head.js \
+
$ ../build/autoconf/make-makefile extensions/firstxpcom
  tail.js \
+
$ cd extensions/firstxpcom
  $(NULL)
+
$ make
# Not sure if I need to alter these...
 
libs:: $(_UNIT_FILES)
 
$(INSTALL) $^ $(DIST)/bin/test-harness/xpcshell-simple
 
  
libs:: $(_TEST_FILES)
+
* Write your JavaScript unit tests for your FirstXpcom component in '''mozilla/extensions/firstxpcom/test/unit/test_firstxpcom.js''':
$(INSTALL) $^ $(DIST)/bin/
 
  
 +
function run_test() {
 +
  // Create an instance of FirstXpcom to test
 +
  try {
 +
    const cid = "@senecac.on.ca/firstxpcom;1";
 +
   
 +
    var obj = Components.classes[cid].createInstance();
 +
    obj = obj.QueryInterface(Components.interfaces.IFirstXpcom);
 +
  } catch (err) {
 +
    do_throw(err);
 +
    return;
 +
  }
 +
 +
  // Test Add
 +
  var result = obj.add(1, 2);
 +
  do_check_eq(3, result);
 +
 +
  // Test Name get and set
 +
  var name = "New String";
 +
  obj.name = name;
 +
  do_check_eq(name, obj.name);
 +
}
  
----------end-------------------
+
* Finally, run your test suite:
  
- Add the following to mozilla/extensions/weblock/Makefile.in
+
$ cd mozilla/''objdir''/extensions/firstxpcom
 +
$ make check
  
ifdef ENABLE_TESTS
+
* You can safely delete '''mozilla/extensions/firstxpcom/test/unit/test_sample.js''', as it is just an example of basic tests you can run:
DIRS  += test
 
endif
 
 
 
- rebuild your Makefiles like so:
 
 
 
cd mozilla/objdir
 
../build/autoconf/make-makefile extensions/weblock
 
make
 
 
 
- finally, run your test suite once (it is empty right now, but this is how you do it):
 
 
 
make check
 
  
 +
/* This is the most basic testcase.  It makes some trivial assertions,
 +
  * then sets a timeout, and exits the test harness when that timeout
 +
  * fires. This is meant to demonstrate that there is a complete event
 +
  * system available to test scripts.
 +
  * Available functions are described at:
 +
  * http://developer.mozilla.org/en/docs/Writing_xpcshell-based_unit_tests
 +
  */
 +
function run_test() {
 +
  do_check_eq(57, 57)
 +
  do_check_neq(1, 2)
 +
  do_check_true(true);
 +
 +
  do_test_pending();
 +
  do_timeout(100, "do_test_finished();");
 +
}
  
 
== Resources ==
 
== Resources ==
Line 78: Line 148:
 
* [http://developer.mozilla.org/en/docs/Creating_reftest-based_unit_tests Creating reftest-based tests]
 
* [http://developer.mozilla.org/en/docs/Creating_reftest-based_unit_tests Creating reftest-based tests]
 
* [http://lxr.mozilla.org/seamonkey/source/browser/components/places/tests/ Examples of good xpcshell tests, from mozilla/browser/components/places/tests]
 
* [http://lxr.mozilla.org/seamonkey/source/browser/components/places/tests/ Examples of good xpcshell tests, from mozilla/browser/components/places/tests]
* [https://bugzilla.mozilla.org/show_bug.cgi?id=371329 bug 371329]
+
* [https://bugzilla.mozilla.org/show_bug.cgi?id=371329 Bug 371329]

Latest revision as of 15:26, 13 April 2007

Real World Mozilla > Real World Mozilla Day 4 > Mozilla Unit Testing Lab

Overview

This lab is designed to give you first-hand experience writing a build-time xpcshell unit test for your XPCOM component. This lab will also serve as a starting point for our discussions of bugs and bugzilla.

NOTE: At the time of writing (February 28, 2007), this lab does not work due to bug bug 371329. While this is regrettable, it still shows an important concept, and further, deals with the reality of bugs in Mozilla.

Instructions

Mozilla currently uses three unit test methods:

  1. The first is xpcshell for C++ unit tests that run on the command line. These are the best method to use whenever possible. Using them effectively requires composing code as stateless functions that return values whenever possible--always a good practice.
  2. Second, since xpcshell tests are not always possible (i.e., a lot of code terminates at OS paint functions that return void, or depends on aspects of the entire browser), so called reftests are used. A reftest compares two screens side by side.
  3. For complex JavaScript and integration bugs, we have mochitest, based on the DHTML framework MochiKit. Mochitest is very flexible and powerful.

For purposes of testing our FirstXpcom component, we will use xpcshell tests. This will allow us to easily write tests to insure the functionality of our class's methods.

  • Begin by creating a new directory to hold our tests:
$ cd mozilla/extensions/firstxpcom
$ mkdir test
  • Now copy the xpcshell test-harness code into this directory:
$ cd mozilla/extensions/firstxpcom/test
$ cp -r ../../../tools/test-harness/xpcshell-simple/example/* .
  • This will result in the following file/directories being copied to test:
$ ls
CVS  Makefile.in  unit
  • The file, test/Makefile.in, needs to be modified:
# Note: DEPTH should be set to the relative path to mozilla/
DEPTH		= ../../..
topsrcdir	= @top_srcdir@
srcdir		= @srcdir@
VPATH		= @srcdir@

include $(DEPTH)/config/autoconf.mk

# Note: set the test module's name to test_<yourmodule>
MODULE		= test_firstxpcom

# This is a list of directories containing tests to run, separated by spaces.
# Most likely, tho, you won't use more than one directory here.
XPCSHELL_TESTS = unit

include $(topsrcdir)/config/rules.mk

# Note: Invoke any additional (non-xpcshell) test programs here.
check::
  • Your component's Makefile needs to include this new test directory. Modify mozilla/extensions/firstxpcom/Makefile.in (change shown in bold):
DEPTH		= ../..
topsrcdir	= @top_srcdir@
srcdir		= @srcdir@
VPATH		= @srcdir@

include $(DEPTH)/config/autoconf.mk

MODULE 	= firstxpcom

DIRS		= public \
		  src \
		  $(NULL)

# Adding xpcshell unit tests
ifdef ENABLE_TESTS
DIRS  += test
endif

XPI_NAME 	= firstxpcom

# A Unique ID for your extension
INSTALL_EXTENSION_ID	= firstxpcom@senecac.on.ca

# Will create a .xpi in /mozilla/$(MOZ_OBJDIR)/dist/xpi-stage/
XPI_PKGNAME	= firstxpcom

# install.rdf will tell Firefox how to install our extension and 
# this says, "copy install.rdf into our extension dir and xpi"
DIST_FILES = install.rdf

include $(topsrcdir)/config/rules.mk
  • Recreate your component's Makefile (make sure you use your own objdir name below):
$ cd mozilla/objdir
$ ../build/autoconf/make-makefile extensions/firstxpcom
$ cd extensions/firstxpcom
$ make
  • Write your JavaScript unit tests for your FirstXpcom component in mozilla/extensions/firstxpcom/test/unit/test_firstxpcom.js:
function run_test() {
  // Create an instance of FirstXpcom to test
  try {
    const cid = "@senecac.on.ca/firstxpcom;1";
    
    var obj = Components.classes[cid].createInstance();
    obj = obj.QueryInterface(Components.interfaces.IFirstXpcom);
  } catch (err) {
    do_throw(err);
    return;
  }

  // Test Add
  var result = obj.add(1, 2);
  do_check_eq(3, result);

  // Test Name get and set
  var name = "New String";
  obj.name = name;
  do_check_eq(name, obj.name);
}
  • Finally, run your test suite:
$ cd mozilla/objdir/extensions/firstxpcom
$ make check
  • You can safely delete mozilla/extensions/firstxpcom/test/unit/test_sample.js, as it is just an example of basic tests you can run:
/* This is the most basic testcase.  It makes some trivial assertions, 
 * then sets a timeout, and exits the test harness when that timeout 
 * fires. This is meant to demonstrate that there is a complete event 
 * system available to test scripts.
 * Available functions are described at:
 * http://developer.mozilla.org/en/docs/Writing_xpcshell-based_unit_tests
 */
function run_test() {
  do_check_eq(57, 57)
  do_check_neq(1, 2)
  do_check_true(true);

  do_test_pending();
  do_timeout(100, "do_test_finished();");
}

Resources