My Approach to Test Driven Development Part 1 - Application Structure and Apache
2008 August 27
As I delve deeper into Test Driven Development (TDD), I have refined my development setup in order to feel confident that my tests are relevant and that they provide immediate feedback about the status of my working code. The two most important goals that I have tried to accomplish with my revisions are to follow the credo of never committing broken code and to isolate and reset the database to ensure the integrity of test data. The following examples are not solely related to TDD, but represent an accumulation of development "best practices" gathered from many sources. I'm going to admit straight up that I am not a TDD purist. I almost always write model components before tests. But I always test before running code on the client side. One of the biggest selling points about unit testing and for me is that I can debug faster should a problem arise and I can do it repeatedly and confidently. Working this way makes me feel somewhat pragmatic. I'm willing to spend a known amount of time setting up and running tests so that I can avoid spending an unknown amount of time debugging. First up, my application directory structure and Apache virtual host settings.Now that I'm using Coldfusion 8 exclusively, I use per application mappings for all my projects. I really like this approach because it allows me to keep configuration files, components and other related files organized within my project, but outside of the web root. Here's the basic setup.
That is a lot of folders, so I'll explain the why and wherefores. For MVC framework users, the config, controller, model and views folders are all self-explanatory. I have a bin folder for shell scripts, a lib folder for dependencies (at this time all .jar files), ansql folder to keep my database scripts and tests for mxunit test cases.
Here's my apache vhost setting for a fictitious project named "langerhans".
<VirtualHost 127.0.0.1:80>
DocumentRoot "/Users/paul/htdocs/langerhans/webroot"
Alias /mxunit "/Users/paul/htdocs/mxunit"
Alias /model "/Users/paul/htdocs/langerhans/model"
Alias /tests "/Users/paul/htdocs/langerhans/tests"
Alias /langerhans "/Users/paul/htdocs/langerhans"
ServerName www.langerhans.local
DirectoryIndex index.cfm
</VirtualHost>
When developing an app locally, I use ".local" to clearly identify the site from staging or production versions. The alias directives help to resolve component paths for themxunit HttpAntRunner and eclipse plugin. These alias directives are for local development or staging only. I would not include them on a production server.
Within Application.cfc I use a simple method to loop over a list of directories to setup the mappings I need. Here's what that method looks like.
<cffunction name="createMappings" access="private" output="false" returntype="struct">
<cfargument name="pathPrefix" type="string" required="false" default="../">
<cfset var mappings = StructNew()>
<cfset var i = "">
<cfloop index="i" list="config,controller,model,views,tests" delimiters=",">
<cfset mappings["/" & i] = expandPath(arguments.pathPrefix) & i />
</cfloop>
<cfreturn mappings>
</cffunction>
I use this code to create the mappings as a pseudoconstructor.
<cfset this.mappings = createMappings()>
That's the basic setup for my apps at this point in time. Next, I'll demo an mxunit test using Coldspring and Coldmock.