Use the left or right arrow key to walk through the modifications.
first | last ![]() |
| Changes from: | |
| to: | |
| Type: | |
first | last ![]() |
CoUnit is a unit testing framework for Cocoon applications.
It can be used to specify and execute unit tests for pipelines and stylesheets.
CoUnit is not meant for testing components written in Java; we have JUnit for that. It will also not help to test the web-frontend of your application; HttpUnit does a fine job in that realm, and so does AntEater. CoUnit helps you to test the bits in between: All the code that lives in the pipelines, transforming XML (SAX events). At the moment, it is particularly good at testing XSLT stylesheets. Flowscript is not yet covered.
CoUnit can be used with Cocoon 2.1.6 and higher. If you need to use an earlier version of Cocoon, you will need to 'retrofit' the MountTableMatcher from the Cocoon repository after 11 October 2004.
Unit (and regression) testing has been one of the best practices in software development for a long time (I first came across it in an article in Dr. Dobbs Journal , February 1997). More recently it has become popular as part of the eXtreme Programming method, where it has evolved into test-driven development. There are many good books and web sites about unit testing, which you should have a look at if you have never heard about these methods:
Unit testing is about testing your code at a fine level of granularity; a single method or function. Regression testing extends this method by making a set of unit tests repeatable and automated, thus giving you an instant picture of the quality of your code.
Test-driven development takes this idea a step further, and demands that you do not write tests to check your code after it has been written, but write them before you write code, as part of the specification of what that code is supposed to do. The development cycle now becomes:
On a project, this should be done following these rules:
There are many benefits to this approach, please see the references cited above.
Unit testing, and test-driven development, must be easy to do and take as little time as possible. If not, software developers will avoid it, because "it is a waste of time", and their managers won't allow it, because "it is a waste of time". And even if you have experienced the time savings (especially in non-trivial projects), it is nice to be able to do something useful with as little effort as possible, so you can concentrate on those things that are more difficult and time-comsuming than they should be.
Unit-testing frameworks have been developed, which facilitate writing unit tests, run test suites, and generate reports. One of the most well-known is JUnit, from which many other XUnit frameworks sprang. Each of these frameworks targets a specific language or development environment.
For the purpose of testing Cocoon applications, the following are interesting:
None of these does exactly what you need to test Cocoon pipelines, which is why I decided to build a specific unit-testing framework for this purpose. After a few iterations, this became CoUnit, which was first presented at the Cocoon GetTogether 2004.
CoUnit is based on XSLTUnit, which is a single stylesheet developed by Eric van der Vlist of Dyomeda. XSLTUnit performs a single unit test on a XSLT style sheet by transforming a XML document, and comparing the result to a 'reference' output. Unfortunately, it falls short of being a framework, because it cannot execute test suites, and it doesn't do much reporting. These blind spots are filled in by CoUnit.
XSLTUnit needs the exsl:node-set() extension function, which is present in both Xalan-J and Saxon.
Before starting to create code for CoUnit, I should have defined unit tests for it, but I didn't because I had no unit-testing framework to run them. What I did do, was to make a list of requirements which should ensure that CoUnit is a nice tool to work with:
You must have a working Cocoon installation already.
CoUnit can be downloaded from this page; look for the section "Project resources".
Installing CoUnit is simple: Just unpack it at a convenient place, like in a sub-directory of the directory where you put all your Cocoon projects.
For example, if your Cocoon projects are in /home/cocoon-projects, create a sub-directory called CoUnit, and unpack in that directory.
CoUnit uses a mount-table. The MountTableMatcher is a relatively new component, which you may not be familiar with yet. This component allows you to use a <map:mount> with uri-prefixes and src-paths taken from a separate file. Thus, the mount points may be changed without changing the sitemap.
CoUnit needs to be mounted in your Cocoon installation. This is typically done from the main sitemap, or from the main mount-table.
If you plan to run unit tests for CoUnit itself (which I should add), use the mount-table, because all testable components need to be mounted that way, as described later.
We assume that CoUnit will be mounted under the "/test/" URI-prefix, but you are free to choose something different.
Mounting from the main sitemap:
<map:match pattern="test/**"> <map:mount check-reload="yes" src="/home/cocoon-projects/CoUnit/" uri-prefix="test"/> </map:match>
Mounting from mount-table.xml:
<mount-table> ... <mount uri-prefix="test" src="/home/cocoon-projects/CoUnit/"/> ... <mount-table>
For Windows users, use the following:
<mount-table> ... <mount uri-prefix="test" src="file://D:/cocoon-projects/CoUnit/"/> ... <mount-table>
Suppose we are going to (test-driven) develop a Cocoon application called 'resourcebrowser', The code (sitemap, XSLT style sheets, resources) will be in the directory '/home/cocoon-projects/resourcebrowser' (or D:\cocoon-projects\resourcebrowser). In order to be testable, the resourcebrowser must be mounted via the main mount-table, 'mount-table.xml', which is referred to from the main sitemap (somewhere around line 830 in Cocoon 2.1.6). We add the following line to the main mount-table:
<mount uri-prefix="resourcebrowser" src="file:///home/cocoon-projects/resourcebrowser/" test="yes"/>
or (not using the default sitemap)
<mount uri-prefix="resourcebrowser" src="file:///home/cocoon-projects/resourcebrowser/my-sitemap.xmap" test="yes"/>
The 'test' attribute (which is added for CoUnit, and not in the documentation of the MountTableMatcher, indicates that this sitemap has CoUnit test suites.
The test suites reside in the '_test' directory, to keep them apart from the actual application code. So the next step is to create the directory '/home/cocoon-projects/resourcebrowser/_test'. The test-sitemap is in this directory, and has the same name as the tested sitemap, either 'sitemap.xmap' or 'my-sitemap.xmap'. This allows you to have two or more testable sitemaps in one directory.
Other files related to the unit tests, such as test stylesheets, test inputs and reference outputs are also put in the _test directory.
Tests are run by issuing a requesting URIs with the "/test/" prefix (or whatever you have chosen).
The following URIs are available:
http://server:port/test/unit/suite/unit_test
http://server:port/test/unit/suite
http://server:port/test/all.xsltunit
http://server:port/test/
TO BE CONTINUED... SOON
Q: I always get a NullPointerException trying to run unit tests, even those that come with CoUnit. A: You need to update Cocoon to version 2.1.6 or higher, or at least update the MountTableMatcher to a version later than 11 October 2004. On that date, Sylvain Wallez fixed bug #31637.
| Mime type | text/xml | ![]() | text/xml |
| File name | ![]() | ||
| Size (bytes) | 12075 | ![]() | 12183 |
|
Version 17 by Bruno Dumon
on 3/13/07 5:07:24 AM Name: CoUnit Variant: main - en State: publish | ![]() |
Version 18 by Nico Verwer
on 5/18/07 2:46:02 AM Name: CoUnit Variant: main - en State: publish |