CFUnit Primer
CFUnit can be used to unit test any type of ColdFusion element including standard CFML Templates, CF Modules, UDF Libraries, and CFCs.
By building unit tests around each element of your application, you will build a framework that will insure the ongoing stability of your code. This document is designed to help you get started using CFUnit. Though it will not cover the full power of CFUnit, it will hopefully get you started and wet you appetite for more.
To begin this primary, create a directory off the root of you web server titled "CFUnitExample". This is were we will be placing all out example code.
Step 1 - Create a Simple CFC
The first thing we need to do is create a ColdFusion element for us to test.
CFCs are one of the more natural fits into the unit testing world because, through methods, its behavior is encapsulated and easy to recognize. Therefore, we will use a CFC for our example.
Create a new CFC in the "CFUnitExample" direcotory and name it "MyCFC.cfc", and paste in this code:
MyCFC.cfc
<cfcomponent displayname="MyCFC">
<cfproperty name="temp1" type="string">
<cfproperty name="temp2" type="string">
<cffunction name="init" returntype="MyCFC">
<cfset VARIABLES.temp1 = 3>
<cfset VARIABLES.temp2 = 2>
<cfreturn THIS>
</cffunction>
<cffunction name="add" returntype="numeric">
<cfreturn (VARIABLES.temp1 + VARIABLES.temp2)>
</cffunction>
<cffunction name="sub" returntype="numeric">
<cfreturn (VARIABLES.temp1 - VARIABLES.temp2)>
</cffunction>
</cfcomponent>
This CFC has two methods, "add" and "sub", we will want a unit test for both.
Step 2 - Create a CFUnit test case
Create a new directory in the "CFUnitExample" directory named "test". We will place our CFUnit tests in this new directory. We could place the CFUnit test anywhere accessible by the ColdFusion server, but placing them in a "test" subdirectory keeps the tests grouped together and easier to maintain.
Add a CFC in your new "test" directory named "MyCFCTest.cfc". Here is the code for that file:
MyCFCTest.cfc
<cfcomponent displayname="MyCFCTest" extends="net.sourceforge.cfunit.framework.TestCase">
<cfproperty name="tempCFC" type="MyCFC">
<cffunction name="setUp" returntype="void" access="public">
<cfset VARIABLES.tempCFC = CreateObject("component", "CFUnitExample.MyCFC").init()>
</cffunction>
<cffunction name="testAdd" returntype="void" access="public">
<cfset result = VARIABLES.tempCFC.add()>
<cfinvoke method="assertEquals">
<cfinvokeargument name="expected" value="#numberFormat(5.0)#">
<cfinvokeargument name="actual" value="#numberFormat(result)#">
</cfinvoke>
</cffunction>
<cffunction name="testSub" returntype="void" access="public">
<cfset result = VARIABLES.tempCFC.sub()>
<cfinvoke method="assertEquals">
<cfinvokeargument name="expected" value="#numberFormat(1.0)#">
<cfinvokeargument name="actual" value="#numberFormat(result)#">
</cfinvoke>
</cffunction>
</cfcomponent>
All CFUnit tests must extend the "TestCase" CFC from the CFUnit framework. This CFC tests the "add" and "sub" methods of our "MyCFC" component. All these tests do is run the method to be tested, and then asserts that the value returned was equal to what we expected. If it is not equal, then the test fails.
The assertEquals() method is a part of the TestCase class which we are extending. Along with the assertEquals() method, there is also assertTrue(), assertFalse(), assertOutputs(), and fail().
Step 3 - Create a Page to Run the Tests
Now that we have our CFC, and our test case, we just need to create a way to run those tests and view the results. We will create a normal CFML template for this called "mytest.cfml", also located in our "CFUnitExample" folder.
mytest.cfml
<cfinvoke component="net.sourceforge.cfunit.framework.TestSuite"
method="init"
classes="CFUnitExample.test.MyCFCTest"
returnvariable="testSuite" />
<cfinvoke component="net.sourceforge.cfunit.framework.TestRunner" method="run">
<cfinvokeargument name="test" value="#testSuite#">
<cfinvokeargument name="name" value="">
</cfinvoke>
This is just a standard CFML template. All it does is creates a TestSuite, providing it with the test CFC we want to run. Then we invoke the "run" method of the TestRunner component. This component will run all tests in the TestSuite, and output the results.
Step 4 - Run the Tests
Now simply browse to your test page using any browser (http://localhost/CFUnitExample/mytest.cfml). You will see a report, and you should see that two tests were ran (testAdd and testSub), with no errors or failures.
Now that you have your test set up, you can continue to update your CFC and refresh this page to rerun the unit tests.
As a final measure, just to see what a failure looks like, change the "sub" method of the "MyCFC" component to:
...
<cffunction name="sub" returntype="numeric">
<cfreturn (VARIABLES.temp1 + VARIABLES.temp2)>
</cffunction>
...
And run the test again. You will notice that you now get a failure.
Summary
This is just an example of one way CFUnit can be used. There are many other way you could go about setting up these test up. In fact, most of the methods that you can use in JUnit are supported in CFUnit.
To recap, here are the three elements to a CFUnit test:
- The CFML application files and components
- A unit test for each CFML file or component, extending TestCase
- One or more pages which call TestRunner to run the tests
As a last note, it's actually suggested that you build your unit tests before you begin writing any CFML code, making it a part of designing your application:
- First design the application or specific CFML files/components
- Write unit tests for each file/component. The tests will of course all fail or error initially.
- Begin the development, frequently running the CFUnit tests. The failures and errors should gradually disappear as the code matures.
- Once the development if finished, run the CFUnit tests a final time verifing the final product behaves as expected.