Ensuring Full Unit Test Coverage In Your CFWheels App

Ensuring that you have unit tested all (or most) of your code in your CFWheels app is an important part of any test suite. As you hopefully know by now, the CFWheels framework features an in-built unit test framework.

The code below is a test itself, that will scan your controllers, models and views folders and make sure that you have a corresponding “test” cfc for each. If it discovers that a test is missing, it will fail.. so your app will not pass unless it has full test coverage.

To get it working, just copy the code below and save it into a file in /tests/TestsExist.cfc (or anywhere under the tests folder actually). You can retro-fit it to any app, though you may need to re-organise your test files somewhat.

There are some conventions that you need to follow to have it work properly, but I consider this being well organised (and you should be used to conventions by now). Your folder structure under /myapp/tests/ should look like this... Say you have a Login.cfc controller, your controller test cfcs themselves should be named like this TestLogin.cfc.. but you could also have multiple test files for your Login.cfc, just as long as the file BEGINS with “TestLogin”, eg: TestLoginRedirects.cfc, TestLoginBusinessLogic.cfc.. you get the idea.

The same goes for models and views. There is much one could do to improve/re-factor/customise this code, but it will hopefully catch anything you may have forgotten to test. Feel free to contribute to this project on GitHub.

So to summarise:

  • Re-organise your folders as per the example above
  • Re-name your test cfc files using Test{YourControllerName}.cfc
  • Copy the code into a TestsExist.cfc file under the /tests/ folder
  • Run your unit tests
<cfcomponent extends="wheelsMapping.Test">
	
	<cffunction name="setup">
		<cfset testsPath = ExpandPath("tests")>
		<cfset controllersPath = ExpandPath("controllers")>
		<cfset modelsPath = ExpandPath("models")>
	</cffunction>
	
	<cffunction name="test_00_setup_and_teardown">
		<cfset assert("true")>
	</cffunction>

	<cffunction name="test_01_all_controller_tests_exist">
		<cfdirectory action="list" directory="#controllersPath#" filter="*.cfc" name="controllers" />
		<cfdirectory action="list" directory="#testsPath & '/' & 'controllers'#" filter="*.cfc" name="controllerTests" />
		<cfset assert("controllerTests.recordCount gt 0")>
		<cfloop query="controllers">
			<cfif ListFindNoCase("Controller.cfc,Wheels.cfc", controllers.name) eq 0>
				<cfset abbrev = ListFirst(controllers.name, ".")>
				<cfset isTestFileFound = false>
				<cfloop query="controllerTests">
					<cfif FindNoCase("Test" & abbrev, controllerTests.name) gt 0>
						<cfset isTestFileFound = true>
						<cfbreak>
					</cfif>
				</cfloop>
				<cfset assert("isTestFileFound", "controllers.name")>
			</cfif>
		</cfloop>
	</cffunction>
	
	<cffunction name="test_02_all_model_tests_exist">
		<cfdirectory action="list" directory="#modelsPath#" filter="*.cfc" name="models" />
		<cfdirectory action="list" directory="#testsPath & '/' & 'models'#" filter="*.cfc" name="modelTests" />
		<cfset assert("modelTests.recordCount gt 0")>
		<cfloop query="models">
			<cfif ListFindNoCase("Model.cfc,Wheels.cfc", models.name) eq 0>
				<cfset abbrev = ListFirst(models.name, ".")>
				<cfset isTestFileFound = false>
				<cfloop query="modelTests">
					<cfif FindNoCase("Test" & abbrev, modelTests.name) gt 0>
						<cfset isTestFileFound = true>
						<cfbreak>
					</cfif>
				</cfloop>
				<cfset assert("isTestFileFound", "models.name")>
			</cfif>
		</cfloop>
	</cffunction>

	<cffunction name="test_03_all_view_tests_exist">
		<cfdirectory action="list" directory="#controllersPath#" filter="*.cfc" name="controllers" />
		<cfdirectory action="list" directory="#testsPath & '/' & 'views'#" filter="*.cfm" name="viewTests" />
		<cfset assert("viewTests.recordCount gt 0")>
		<cfloop query="controllers">
			<cfif ListFindNoCase("Controller.cfc,Wheels.cfc", controllers.name) eq 0>
				<cfset abbrev = ListFirst(controllers.name, ".")>
				<cfset isTestFileFound = false>
				<cfloop query="viewTests">
					<cfif FindNoCase("Test" & abbrev, viewTests.name) gt 0>
						<cfset isTestFileFound = true>
						<cfbreak>
					</cfif>
				</cfloop>
				<cfset assert("isTestFileFound", "controllers.name")>
			</cfif>
		</cfloop>
	</cffunction>

	<cffunction name="teardown">
	</cffunction>

</cfcomponent>
Advertisements

One thought on “Ensuring Full Unit Test Coverage In Your CFWheels App

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s