OT: Our Second Car Is An '82 Prelude

I recently purchased and imported a first generation prelude as a gift for my wife. I haven't owned a car of this vintage since the mid 90's, so it took all of one drive from the border home to give me that "first car" love affair with this sweet little ride...

[More]

ColdSpring Reloaded

Coldspring was the first Coldfusion-based "framework" that I integrated into my application development process. I can't claim to be an expert, but today I'll step up and try evangelism. Based on the popular Java Spring framework, Coldspring provides a solid foundation for applications with features like dependecy injection, aspect-oriented programing, remote proxy generation and more. If you already use ColdSpring, or want to learn how to use it, I highly recommend the new Quickstart Guide and Examples written by ColdSpring guru Brian Kotek. In addition to a new look and documentation update, version 1.2 is now final! Get ye to the Springery...

For the Love of Chocolate, Style Your Optgroup!

If you haven't tried out the cfUniForm tag library by Matt Quackenbush, I highly recommend it. Version 2.3 includes some nice updates proposed by Bob Silverberg, including the addition of optgroup to select lists.

I don't like the default italic style for an optgroup label, so when I use it, I add a simple css selector to make them a little more visually appealing. For example:

optgroup {
   font-weight: bold;
   font-style:normal;
}

Don't let default optgroup styles drag you down. Make them great with a little CSS.

My Approach to Test Driven Development Part 3 - Testing Against a Database

Confidently unit testing code that relies on a database is troublesome. There are many different approaches and many opinions on the matter. I've previously written about using transactions to safely rollback the database after every test. This worked well for me at the time, but there are pitfalls in using that approach. Recently, I've done some more research on the subject and even attempted, without success, to integrate DBUnit into my database reliant unit tests. After some trial and error, I landed on the following approach that is a culmination of a few ideas I'd previously heard of, but never tried. The goal of this approach is to:

  1. Run tests against a known data set.
  2. Reset the entire database prior to each test.

The example code that follows requires a test database, test database user and a test datasource targeting the test database.

[More]

My Approach to Test Driven Development Part 2 - MXUnit, Coldspring and ColdMock

Like the title says, this post will include code samples for setting up an MXUnit test case using ColdSpring and ColdMock. The goal of any test case are to isolate the component under test as much as possible. I find ColdMock to be a simple and powerful tool for achieving test isolation. For this example, I created a test case for my ConfigFactory which I mentioned in a previous post. TheConfigFactory component has a constructor dependency on the Environment Config component developed by Rolando Lopez which makes this a good case for mocking.

Here's a snapshot of the files used in this sample test setup,

A common convention for test cases is to add the suffix "Test" to match the test case to the component being tested. I have my own convention for setting up tests withColdSpring bean definitions which I keep in a similarly named xml file. All test cases extend the BaseTestCase which contains a couple of methods to simplify test configuration with ColdSpring. The full code of the of the BaseTestCase follows.

<cfcomponent displayname="tests.BaseTestCase" extends="mxunit.framework.TestCase" output="false">

<cfset variables.beansXML = "">

<cffunction name="setBeanFactory" access="private" output="false" returntype="void">
<cfargument name="beansXML" type="string" required="true">
<cfargument name="params" type="struct" required="false" default="#structnew()#">
<cfscript>

if ((not structkeyExists(request,"beanFactory")) or (comparenocase(variables.beansXML,arguments.beansXML) neq 0))
{
variables.beansXML = arguments.beansXML;
request.beanFactory = createObject("component" ,"coldspring.beans.DefaultXmlBeanFactory").init(StructNew(),arguments.params);
request.beanFactory.loadBeans(variables.beansXML);
}
</cfscript>
</cffunction>

<cffunction name="getBeanFactory" access="private" output="false" returntype="any">
<cfreturn request.beanFactory>
</cffunction>

</cfcomponent>

In the past I kept my ColdSpring reference in variables scope, but I found that when testing components based that rely on Transfer ORM, I can shave the time of tests considerably when I have multiple tests in the same test case. Whether you run the MXUnit HttpAntRunner, the eclipse plugin or a manually configured test suite within a browser they all run as a single request, so as you define more tests it helps to speed things up.

Here's what the ConfigFactoryTest.xml looks like.

<beans>
<bean id="mockFactory" class="tests.MockFactory" singleton="true" />

<bean id="EnvironmentConfig" factory-bean="MockFactory" factory-method="createMock">
<constructor-arg name="objectToMock">
<value>model.Environment</value>
</constructor-arg>
</bean>

<bean id="ConfigFactory" class="model.ConfigFactory">
<constructor-arg name="hostName">
<value>${hostName}</value>
</constructor-arg>
<constructor-arg name="environmentConfig">
<ref bean="EnvironmentConfig" />
</constructor-arg>
</bean>

</beans>

You can see how easy it is to mock the dependency using the ColdMock MockFactory. Below is the full code for my ConfigFacotry test case. The important thing to note is that the component display name is used to resolve the path to the ColdSpring bean definitions used in the test suite.

<cfcomponent displayname="tests.ConfigFactoryTest" extends="tests.BaseTestCase">

<cffunction name="setUp" access="public" returntype="void">
<cfset var beanDefFileLocation = expandPath('/' & Replace(GetMetadata(this).displayname,'.','/','all') & '.xml')>
<cfset var params = Structnew()>
<cfset params.hostName = "www.somedomain.com">
<cfset setBeanFactory(beanDefFileLocation,params)>
</cffunction>

<!--- Begin Specific Test Cases --->

<cffunction name="testGetSetting" access="public" returntype="void">
<cfscript>
var configFactory = "";
var env = getBeanFactory().getBean("EnvironmentConfig");
var settings = structNew();
settings["MyString"] = "my string";
env.mockMethod('getEnvironmentByUrl').returns(settings);
configFactory = getBeanFactory().getBean("ConfigFactory");
assertTrue(configFactory.getSetting("MyString") eq settings["MyString"]);
</cfscript>
</cffunction>

<cffunction name="testGetAllSettings" access="public" returntype="void">
<cfscript>
var configFactory = "";
var env = getBeanFactory().getBean("EnvironmentConfig");
var settings = structNew();
settings["MyString"] = "my string";
env.mockMethod('getEnvironmentByUrl').returns(settings);
configFactory = getBeanFactory().getBean("ConfigFactory");
assertTrue(StructCount(configFactory.getAllSettings()) eq 1);
</cfscript>
</cffunction>

<cffunction name="testOnMissingMethod" access="public" returntype="void">
<cfscript>
var configFactory = "";
var env = getBeanFactory().getBean("EnvironmentConfig");
var settings = structNew();
settings["MyString"] = "my string";
env.mockMethod('getEnvironmentByUrl').returns(settings);
configFactory = getBeanFactory().getBean("ConfigFactory");
assertTrue(configFactory.getMyString() eq settings["MyString"]);
</cfscript>
</cffunction>

<!--- End Specific Test Cases --->

</cfcomponent>

Most of my tests aren't this involved. Since my ConfigFactory has a constructor dependency on EnvironmentConfig, I pull it out of ColdSpring first, mock the getEnvironmentByUrl method to return a known structure before requesting the ConfigFactory. Truly powerful stuff!

I have attached a zip file of this sample test bed as an enclosure for folks to try out.

My Approach to Test Driven Development Part 1 - Application Structure and Apache

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.

[More]

School's Out...Forever!

Today, I wrote the final exam for the final course I need for my BComm. It was fitting that I wrote it at my home town University in Windsor, Ontario. I live in BC now, but circumstance brought me to Windsor this week, so I made arrangements to write my exam in town. Before the exam, I had that "full circle" feeling walking around the campus I had not set foot on for nearly 20 years. For a little history, I started university in September 1985 and left school in February 1989 to pursue personal interests (of the rock and roll variety). After many joe jobs and many bands, I made the decision to return to school in 1998 as a distance education student. Now ten years later, I've completed the requisites for my degree. It's been a long strange trip and now that it's over I just have to crank up the Alice Cooper...

Jon Messer Writes! Check out Amcom Technology Blog's Newest Author

Amcom Technology is chock full of serious Coldfusion and Flex talent. Not the least of which is Jon Messer who has long contributed to the many of the popular CF lists. Jon is starting a new series on building an object oriented application with multiple MVC clients including Flex. The first installment introduces the series and describes modeling business objects. If you are interested in OO application design for Coldfusion, I highly recommend this series as a reference.

Dynamic Configuration with Environment Config And a Coldspring Config Factory

When developing web application, it is very likely that at some point you will need to create dynamic configuration for your application in terms of development, staging and production environments. I recently discovered the excellent Environment Config project by Rolando Lopez. Rolando has created a very interesting package with lots of robust features for configuring your application dynamically. There are portions of the package that I must admit, I'm not using (yet). What follows is my current setup for integrating the environment config with a custom factory.

[More]

Model Glue Event Security Using Broadcasts and Results

When building web applications, you will inevitably need to provide secure pages or an entire area of your application for users and administrators. For my most recent Model Glue project I wanted to define a common approach to securing all access to the admin area with the exception of login pages. After several failed attempts at universal security, I decided that securing events is best achieved through explicit broadcasts and results, with a minimal amount of logic handled within the controller. Here's a simple example.

Let's presume that the default event for my admin sub-application is "admin.home", here is my event listener declaration.

<event-handler name="admin.home">
<broadcasts>
<message name="loginRequired" />
</broadcasts>
<results>
<result name="noValidLogin" do="login.go" redirect="true" />
<result do="layout" />
</results>
<views>
<include name="content" template="home.cfm" />
</views>
</event-handler>

The loginRequired has a listener defined by the following.

<controller name="SecurityController" type="admin.controller.SecurityController">
<message-listener message="loginRequired" function="verifyLogin" />
</controller>

Finally, in my SecurityController, the verifyLogin method looks like this.

<cffunction name="verifyLogin" access="public" returnType="void" output="false">
<cfargument name="event" type="any">
<cfif not getSecurityService().adminLoggedIn()>
<cfset arguments.event.addresult("noValidLogin")>
</cfif>
</cffunction>

In a previous application I chose to use event.forward() within my controller to redirect the request to the login event. Although this works, it is, in my opinion, better to use addResult and have Model Glue handle the redirection. Although the xml is more verbose, I really like that the intent of each event is clearly defined. Which provides a nice roadmap for any other developers that may take over the project.

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.9. Contact Blog Owner