Special Thanks to FlexBuilder Team
Advanced Unit Testing Patterns at Adobe MAX 2008
Yeah, but does it run on [ENTER YOUR CF SERVER HERE] ?
I'm going to describe a couple of things: (1) How I set up my environment for testing, and (2) how I leverage MXUnit and Ant to perform concurrent tests on each platform.
There's a number of different approaches to this problem (VWMare or VirtualBox come to mind). This particular method is not so sophisticated but should be portable to various virtual images targeted to be run on different OSs.
The following should allow any developer on any platform with a couple of hours to be able to put together something that allows him or her to test their application on ColdFusion, Railo, and Open Blue Dragon. And it won't cost you anything but some bandwidth, and hopefully the headache was mine.
The napkin design ...
For the app I want to test (MXUnit, natually), I want each CFML server to point to the same set of files on disk. I don't want to have different versions of the app in different web roots. Think a about that - I would have test in one server, then copy to another, test there, copy to the other, and round and round trying to keep track of changes... eek! Another thing I want is the URLs I use to test my apps be descriptive and simple: http://adobe, http://railo, http://obd. Lastly, I want the ability to run my tests on each platform concurrently.
These are the general steps: 1. Download and install server software 2. Decide on a web root location 3. Edit your hosts file 4. Connect your CFML Engines to Apache 5. Create Apache Virtual Hosts 6. Configure your CFML Engines 7. Run Smoke Test 8. Build and Run Ant based MXUnit tests
1. Download and install server software: 1. Apache 2.2 2. Adobe ColdFusion 8 (Multi-instance) 3. Railo Server /Resin 4. Open Blue Dragon - Jetty/Ready2Run
I won't bore your with talk about installing these products, as most are well documented.At this point you have Apache running on localhost:80, a ColdFusion instance on localhost:8301, Railo on localhost:8600, and Open Blue Dragon on localhost:8080. Don't worry if your ports are not the same, just as long as they don't conflict with one another, you should be ok.
2. Decide on a web root location. I use D:/webapps on Windows or /home/billy/webapps on Ubuntu
3. Edit your hosts file On Windows this should be in C:\Windows\system32\drivers\etc\hosts, Unix /etc/hosts.
On Windows it may only have one entry: 127.0.0.1 localhost
Add the following:
127.0.0.1 railo 127.0.0.1 adobe 127.0.0.1 obd
This tells your machine to resolve the names to your localhost address, 127.0.0.1.
4. Connect your CFML Engines to Apache
4a. Adobe: Adobe ColdFusion has the webserver connector tool, which does the work for you. This should be located in {CF-Install}/bin/wsconfig.exe. Check the Adobe documentation for details.
This will make some entries in {Apache}/conf/http.conf See below.
4b. Railo - Open up the {Apache}/conf/http.conf file and add the following at the bottom.
#Load Railo Module LoadModule caucho_module "{Railo-Install}/win32/apache-2.2/mod_caucho.dll"
Where {Railo-Install} is the full path to your installation; e.g. LoadModule caucho_module "C:/railo-3.0.0.005-resin-3.1.2-with-jre-windows/win32/apache-2.2/mod_caucho.dll"
4c. Open Blue Dragon - OBD does not have a web server connector, but you will need to do some URL re-writing in the virtual host config - a whopping 2 lines of code! See next section #5.
The bottom of my httpd.conf looks like this:
########################################################## # # Load CFML Engine Plugins # ########################################################## # JRun Settings LoadModule jrun_module "C:/JRun4/lib/wsconfig/1/mod_jrun22.so" <IfModule mod_jrun22.c> JRunConfig Verbose true JRunConfig Apialloc true JRunConfig Ignoresuffixmap false JRunConfig Serverstore "C:/JRun4/lib/wsconfig/1/jrunserver.store" JRunConfig Bootstrap 127.0.0.1:51000 #JRunConfig Errorurl url <optionally redirect to this URL on errors> #JRunConfig ProxyRetryInterval 600 <number of seconds to wait before trying to reconnect to unreachable clustered server> #JRunConfig ConnectTimeout 15 <number of seconds to wait on a socket connect to a jrun server> #JRunConfig RecvTimeout 300 <number of seconds to wait on a socket receive to a jrun server> #JRunConfig SendTimeout 15 <number of seconds to wait on a socket send to a jrun server> AddHandler jrun-handler .jsp .jws .cfm .cfml .cfc .cfr .cfswf </IfModule> #Load Railo Module LoadModule caucho_module "C:/railo-3.0.0.005-resin-3.1.2-with-jre-windows/win32/apache-2.2/mod_caucho.dll"Note: Make sure the mod_rewrite and mod_vhost_alias module lines are uncommented (top of file). These are needed to create virtual hosts and to do the URL rewriting for Open Blue Dragon 5. Configure Apache Virtual Hosts Each virtual host entry represents a unique host url I want to invoke for each CFML server.
#Make any requests for http://adobe get processed by the Adobe CFML engine <VirtualHost adobe:80> ServerName adobe ServerAlias adobe DocumentRoot "D:/webapps/" <Directory "D:/webapps/"> Order allow,deny Allow from all Options Indexes SymLinksIfOwnerMatch DirectoryIndex index.html index.cfm </Directory> </VirtualHost> #Make any requests for http://railo get processed by the Railo engine <VirtualHost railo:80> ServerName railo ServerAlias railo DocumentRoot "D:/webapps/" <Directory "D:/webapps/"> Order allow,deny Allow from all Options Indexes SymLinksIfOwnerMatch DirectoryIndex index.html index.cfm </Directory> ResinConfigServer railo 6800 </VirtualHost> <VirtualHost obd:80> ServerName obd ServerAlias obd DocumentRoot "D:/webapps" RewriteEngine On RewriteRule ^(.*)$ http://localhost:8080$1 [P] <Directory "D:/webapps/"> Order allow,deny Allow from all Options Indexes SymLinksIfOwnerMatch DirectoryIndex index.html index.cfm </Directory> </VirtualHost> ###################################################### # End httpd-vhosts.conf ######################################################
Notes:
Each virtual host correlates to a host name in my hosts file. So, when the web browser requests http://adobe, my machine forwards that to Apache on port 80. Apache is configured, by default, to use Adobe ColdFusion to process any CFML file. Next, if I request http://railo, again, my machine forwards the request to Apache, but, this time Apache has the instruction to process ResinConfigServer railo 6800. This tells caucho_module to process requests on the server named "railo" (localhost) on port 6800. This is the port Resin is listening on. All results are sent back to Apache and then web browser.
Also note that the Document Root for all these virtual hosts is the same, d:/webapps.
6. Configure CFML Server
Open Blue Dragon
1. Since ODB does not have web connector, we will use Apache's URL rewriting capabilities. In the above, any request made to http://obd will be processed by http://localhost:8080, which is where OpenBlueDragon and Jetty are running.
2. You will also need to edit the jetty.xml configuration file to specify the common webroot. This is located in C:\jetty-6.1.12-OpenBD\etc\jetty.xml. In this file we have to tell Jetty about our d:/webapps. Find the <Set name="handler"> elements and add the following above the <New id="cfmlWebContext_1" class="org.mortbay.jetty.webapp.WebAppContext">...</New> element. Note that the cfmlWebContext_1 element points to a sample Open Blue Dragon app with a couple of CFML pages. You should be able to keep that there.
<Item> <New id="mxunit_qa" class="org.mortbay.jetty.webapp.WebAppContext"> <Set name="contextPath">/</Set> <Set name="war">D:/webapps/</Set> <Set name="defaultsDescriptor"> <SystemProperty name="jetty.home" default="."/>/etc/webdefault.xml</Set> <Set name="VirtualHosts"> <Array type="java.lang.String"> <Item>127.0.0.1</Item> <Item>localhost</Item> </Array> </Set> </New> </Item>
Railo
In the Railo web administrator (http://localhost:8600/railo-context/admin/web.cfm), under Archives & Resources, create a Mapping. For the Virtual value enter a "/" and for the Resource value, enter D:\webapps. The primary should be Resource and I'm not sure what trusted does, but I left that unchecked.
ColdFusion
Nothing special is apparently needed. If you run into an issue you could create a mapping in the ColdFusion Administrator for "/" pointing to D:\webapps. But this was not needed for me.
7. Run A Simple Smoke Test
Now, you should be able to start all these servers and they should all be running. When developing I always start my servers from the command line. That way, I can watch for debug output to stdout instead of digging through log files.
C:\> C:\apache\Apache2.2\bin\httpd.exe C:\> C:\Jrun4\bin\jrun start dev C:\> C:\railo-3.0.0.005-resin-3.1.2-with-jre-windows\httpd.exe C:\jetty-6.1.12-OpenBD\> java -jar start.jar
A Quick Visual Inspection: Here's a basic web page with an iframe for each virtual host. Formatting HTML omitted. <iframe src="http://adobe/mxunit"></iframe> <iframe src="http://railo/mxunit"></iframe> <iframe src="http://obd/mxunit"></iframe>Naturally, I'm using MXUnit, but this would apply to any app you want to test. Again, the goal is to have a common webroot for all CFML servers.
8. Build and Run MXUnit Ant-based tests
Now here's where the real power comes in! I totally heart Ant's <parallel> task and would buy it a lobster dinner if I could.
At this point you can run your tests anyway you please - open a web browser, er eh, and click each page one at a time and visually compare results. But what if you could do this really really fast? How about running 100 or more tests on each server at the same time? And be able to repeat it? Enter Ant and MXUnit ... Details on the MXUnit Ant task can be found here and the Test Automation section here.
Luis Majano's ColdBox Framework has been reporting some issues with MXUnit when run on Railo. In order to help find these pesky critters, I set up an Ant build to run Luis's tests on Railo and Adobe at the same time.
<project name="MXUnitTask" basedir="." default="runtests"> <property name="mxunit.jar" value="ant/lib/mxunit-ant.jar" /> <taskdef name="mxunittask" classname="org.mxunit.ant.MXUnitAntTask" classpath="${mxunit.jar}" /> <property name="test.dir" value="D:\webapps\coldbox\testing\tests\cases\beans" /> <property name="component.path" value="coldbox.testing.tests.cases.beans" /> <property name="output.dir" value="tmp" /> <target name="runtests" description="Run same tests on all servers concurrently"> <taskdef name="mxunittask" classname="org.mxunit.ant.MXUnitAntTask" classpath="${mxunit.jar}" /> <parallel> <!-- run Adobe Tests --> <mxunittask server="adobe" port="80" outputdir="${output.dir}/adobe" defaultrunner="/mxunit/runner/HttpAntRunner.cfc" verbose="true" haltonfailure="false" haltonerror="false"> <directory runner="/mxunit/runner/HttpAntRunner.cfc" remoteMethod="run" path="${test.dir}" packageName="adobe.${component.path}" componentPath="${component.path}" recurse="true"/> </mxunittask> <!-- run Railo Tests --> <mxunittask server="railo" port="80" outputdir="${output.dir}/railo" defaultrunner="/mxunit/runner/HttpAntRunner.cfc" verbose="true" haltonfailure="false" haltonerror="false"> <directory runner="/mxunit/runner/HttpAntRunner.cfc" remoteMethod="run" path="${test.dir}" packageName="railo.${component.path}" componentPath="${component.path}" recurse="true" /> </mxunittask> </parallel> </target> </project>
Take note of parallel, which spawns a separate thread for each sub-task. This effectively cuts this test's time in half!
Tip: It's also possible to speed up any testing effort simply by leveraging the the parallel task but point the mxunit ant task to different directories.
Using the junitreport task (not displayed here), I can then print a report. I particularly like this one - 168 tests, 0 Failures, 0 Errors. No critters found here, but they may be lurking somewhere.
Happy testing,
bill
References:
Setting up Railo and Apache on Unix
- http://www.garyrgilbert.com/blog/index.cfm/2008/11/6/Installing-Railo-3-on-Linux-CentOS-Part-1
- http://www.hockeypfef.net/index.cfm/2008/9/29/Railo-Server-and-Apache
Setting Up Railo and Apache on Windows
- http://www.railo.ch/blog/index.cfm/2008/5/2/Railo-and-Apache
Open Blue Dragon
- http://www.openbluedragon.org/
MXUnit
ColdFusion
- http://www.adobe.com/products/coldfusion/
Apache Ant
- http://ant.apache.org/
- http://www.thecrumb.com/