{toc}
h1. Core Built-in Assertions
This document outlines the core of unit testing, i.e. Assertions. Assertions are simple: You assert something, and if that assertion does not result in your expectation, the test fails. All code AFTER a failed assertion will NOT execute. Repeat: A failed assertion means the end of that test.
This is why it's best practice to not load your test functions with lots of assertions. A single failed assertion means that any subsequent assertions in a test will not execute and thus you won't know if those assertions indicate further problems in your code.
Need an assertion you don't see here? [Roll your own ...|Custom Assertions]
Without further delay, our players, The Assertions:
h2. assertTrue(boolean condition \[,String message\])
assertTrue is one of the two "bread and butter" assertions in any testing framework. The philosophy is simple: you assert something to be true; if it's not, the test fails
{code:title=assertTrue()}<cffunction name="clearPrivilegesShouldClearPrivilegesFromObject">
<cfset obj = createObject("component","myObject")>
<cfset obj.addPrivilege("EditUsers")>
<cfset assertTrue( StructCount(obj.getPrivileges()), "Guard assertion: Ensure we're starting out with privileges before testing clearPrivileges()")>
<cfset result = obj.clearPrivileges()>
<cfset assertTrue( StructIsEmpty(obj.getPrivileges()), "clearPrivileges Should Have Emptied The Structure of privileges but didn't" )>
</cffunction>
{code}assertTrue has an opposite, assertFalse:
h2. assertFalse(boolean condition \[, String message\])\*
{code:title=assertFalse}<cffunction name="clearPrivilegesShouldClearPrivilegesFromObject">
<cfset obj = createObject("component","myObject")>
<cfset obj.addPrivilege("EditUsers")>
<cfset assertFalse( StructIsEmpty(obj.getPrivileges()), "Guard assertion: Ensure we're starting out with privileges before testing clearPrivileges()")>
<cfset result = obj.clearPrivileges()>
<cfset assertTrue( StructIsEmpty(obj.getPrivileges()), "clearPrivileges Should Have Emptied The Structure of privileges but didn't" )>
</cffunction>
{code}
h2. assert(boolean condition \[,String message\])
assert is semantically equivalent to assertTrue, providing a shorter form :
{code:title=assert()}<cffunction name="testAssert">
<cfset assert( 1 eq 1, "Testing a true expression")>
<cfset assert( not 1 eq 2, "Testing negated expression")>
</cffunction>
{code}
h2. assertEquals*(any expected, any actual \[, String message\])
assertEquals is the other core assertion. Here, you're asserting that some result equals some expected result. This could be two numbers, two strings, two structs, whatever. For now, MXUnit follows the JUnit pattern of using a single assertEquals to compare any type of data.
{code:title=assertEquals()}<cffunction name="clearPrivilegesShouldClearPrivilegesFromObject">
<cfset obj = createObject("component","myObject")>
<cfset obj.addPrivilege("EditUsers")>
<cfset assertEquals(1, StructCount(obj.getPrivileges()), "Guard assertion: Ensure we're starting out with privileges before testing clearPrivileges()")>
<cfset result = obj.clearPrivileges()>
<cfset assertEquals(0, StructCount(obj.getPrivileges()), "clearPrivileges Should Have Emptied The Structure of privileges but didn't" )>
</cffunction>
{code}
h3. Comparing Arrays, Queries, and Structures
MXUnit will do a deep compare for arrays, queries, and structures. It is *not* fail-fast, meaning that an assertEquals( struct1, struct2 ) will compare every key in the struct, including any nested structures or arrays, accumulating mismatches. Once every key is visited, the existence of mismatches will signal an assertion failure. Array, Query, and Struct comparisons will add a Structure result into the debug output if the assertion fails, and you can view the full set of differences from there.
In addition, when using the Eclipse plugin, you can toggle the "Compare Dialog" to pop up Eclipse's comparison tool, which enables you to step through all the differences.
Here's an example
!CompareDialog.PNG|thumbnail!
h2. fail*(String message)
fail() is used to actively fail a test. It's useful when you're stubbing a test and you want to ensure it fails, like so:
{code:title=fail()}<cffunction name="addPrivilegeShouldHaveNoEffectIfPrivilegeExists">
<cfset fail("test not yet implemented")>
</cffunction>
{code}
It's also useful when you're testing an "error path", like so:
{code:title=fail() to test Error Paths}<cffunction name="addPrivilegesWithPunctuationShouldThrowError">
<cfset var obj = createObject("component","myObject")>
<cftry>
<cfset obj.addPrivilege("Edit.User")>
<cfset fail("Should not get here. Function under test should've thrown an error")>
<cfcatch type="mxunit.exception.AssertionFailedError">
<cfrethrow>
</cfcatch>
<cfcatch type="any"><!--- expect to get here ---></cfcatch>
</cftry>
</cffunction>
{code}
h2. failNotEquals*(any value, any value2 \[,String message\])
Used to fail when two values do not equal. This doesn't perform any assertion... it's simply a convenience method for providing a specific type of failure message
{code:title=failNotEquals()}<cffunction name="demoFailNotEquals">
<cfset failNotEquals(myObject1,myOtherObject, "These should not have the same value")>
</cffunction>
{code}
h2. assertSame*(any obj1, any obj2 \[,String message\])
Used to determine if the obj1 and obj2 refer to the same instance.
Note that arrays in Adobe ColdFusion are passed by value, so, this will always fail for arrays.
{code:title=assertSame()}<cffunction name="initShouldReturnSelf">
<cfset var obj = createObject("component","myObject")>
<cfset assertSame(obj,obj.init(), "These should be the same thang since init should return 'this'")>
</cffunction>
{code}
h2. assertNotSame*(any obj1, any obj2 \[,String message\])
Used to determine if the obj1 and obj2 _do not_ refer to the same instance.
Note that arrays in Adobe ColdFusion are passed by value, so, this will always pass for arrays.
{code:title=assertNotSame()}<cffunction name="newInstanceShouldNotReturnSelf">
<cfset var obj = createObject("component","myObjectFactory")>
<cfset assertNotSame(obj,obj.newInstance(), "These should not be the same thang since newInstance should return a new instance from the factory")>
</cffunction>
{code}
h1. MXUnit Assertion Extensions
These are extensions to the base set of assertions and are specific to ColdFusion.Note, that these are quite simple, can be easily implemented using the base assertions above, but are provided for convenience.
*Note:* These extensions can be disabled at runtime by editing the mxunit-config.xml located in /mxunit/framework/ directory. Simply remove or comment out these line:
{code:title=assertionExtension config-extension in mxunit-config.xml} <config-element type="assertionExtension" path="MXUnitAssertionExtensions" autoload="true" override="false" />
<config-element type="assertionExtension" path="HamcrestAssert" autoload="true" override="false" />
<config-element type="assertionExtension" path="XPathAssert" autoload="true" override="false" />
{code}
h2. assertXPath*(String xpath, any data, \[String text\], \[String message\])
Searches data using xpath. If text is specified, it tries to match the exact text to the xpath expression. Otherwise ,it returns true if any nodes are found that match the xpath expression. Note that, unlike most assertions, assertXPath returns an xml dom representation of any nodes found. This can be useful for further inspection.
*Parameters* String xpath: string representing an xpath expression
any data: String or URL to search; e.g., ..., [http://google.com], [file://c:/path/to/my.html]
\[string text\]: The text to match against the xpath expression. If omitted, this assertion returns true if any elements of the xpath expression are found. Not required. Defaults to ""
\[string message\]: The message to display when this assertion fails Not required. Defaults to The XPath expression, #arguments.xpath#, did not match the data.
{code:title=assertXPath()}<cffunction name="testFindGoogleInTitle">
<cfscript>
nodes = assertXpath('/html/head/title', "http://google.com", "Google");
debug(nodes);
nodes = assertXPath("/html/head/title", "file:///coldfusion8/wwwroot/mxunit/tests/framework/fixture/xpath/mxunit.org.html");
nodes = assertXPath("/root/foo/bar[@id='123abc']", someXmlOrHtml);
</cfscript>
</cffunction>
{code}The above parses the results from urls and strings and searches the parsed results for the XPath expression.
Try it. Really, it works\!
h2. assertIsTypeOf*(component obj, String type)
Determines if obj is of type. type needs to be fully qualified.
{code:title=assertIsTypeOf()}<cffunction name="demoAssertIsTypeOf">
<cfset assertIsTypeOf(obj,"my.type.Of.Object")>
</cffunction>
{code}
h2. assertIsXMLDoc*(any xml \[, String message\])
Determines if xml is a valid XML DOM object.
{code:title=assertIsXMLDoc()}<cffunction name="demoAssertIsXMLDoc">
<cfset assertIsXMLDoc(xml)>
</cffunction>
{code}
h2. assertIsArray*(any obj1)
Determines if the obj1 is a valid array.
{code:title=assertIsArray()}<cffunction name="demoAssertIsArray">
<cfset assertIsArray(myObject1)>
</cffunction>
{code}
h2. assertIsDefined*(any obj1)
Determines if the obj1 has been defined in the available scope.
{code:title=assertIsDefined()}<cffunction name="demoAssertIsDefined">
<cfset assertIsDefined("myObject1")>
</cffunction>
{code}
h2. assertIsEmpty*(any obj1)
Determines if the obj1 is a 0 length string or NULL equivalent.
{code:title=assertIsEmpty()}<cffunction name="demoAssertIsEmpty">
<cfset assertIsEmpty(myObject1)>
</cffunction>
{code}
h2. assertIsEmptyArray*(any obj1,\[String message\])
Determines if the obj1 is an array with no elements.
{code:title=assertIsEmptyArray()}<cffunction name="demoAssertIsEmptyArray">
<cfset assertIsEmptyArray(myObject1)>
</cffunction>
{code}
h2. assertIsEmptyQuery*(any obj1,\[String message\])
Determines if the obj1 is a query with no rows.
{code:title=assertIsEmptyQuery()}<cffunction name="demoAssertIsEmptyQuery">
<cfset assertIsEmptyQuery(myObject1)>
</cffunction>
{code}
h2. assertIsEmptyStruct*(any obj1,\[String message\])
Determines if the obj1 is a struct with no keys or values.
{code:title=assertIsEmptyStruct()}<cffunction name="demoAssertIsEmptyStruct">
<cfset assertIsEmptyStruct(myObject1)>
</cffunction>
{code}
h2. assertIsQuery*(any q)
Determines if q is a valid ColdFusion query.
{code:title=assertIsQuery()}<cffunction name="demoAssertIsQuery">
<cfset assertIsQuery(q)>
</cffunction>
{code}
h2. assertIsStruct*(any obj)
Determines if obj is a valid ColdFusion structure.
{code:title=assertIsStruct()}<cffunction name="demoAssertIsStruct">
<cfset assertIsStruct(obj)>
</cffunction>
{code}
----
Need more? [Build your own ...|Custom Assertions]
h1. Core Built-in Assertions
This document outlines the core of unit testing, i.e. Assertions. Assertions are simple: You assert something, and if that assertion does not result in your expectation, the test fails. All code AFTER a failed assertion will NOT execute. Repeat: A failed assertion means the end of that test.
This is why it's best practice to not load your test functions with lots of assertions. A single failed assertion means that any subsequent assertions in a test will not execute and thus you won't know if those assertions indicate further problems in your code.
Need an assertion you don't see here? [Roll your own ...|Custom Assertions]
Without further delay, our players, The Assertions:
h2. assertTrue(boolean condition \[,String message\])
assertTrue is one of the two "bread and butter" assertions in any testing framework. The philosophy is simple: you assert something to be true; if it's not, the test fails
{code:title=assertTrue()}<cffunction name="clearPrivilegesShouldClearPrivilegesFromObject">
<cfset obj = createObject("component","myObject")>
<cfset obj.addPrivilege("EditUsers")>
<cfset assertTrue( StructCount(obj.getPrivileges()), "Guard assertion: Ensure we're starting out with privileges before testing clearPrivileges()")>
<cfset result = obj.clearPrivileges()>
<cfset assertTrue( StructIsEmpty(obj.getPrivileges()), "clearPrivileges Should Have Emptied The Structure of privileges but didn't" )>
</cffunction>
{code}assertTrue has an opposite, assertFalse:
h2. assertFalse(boolean condition \[, String message\])\*
{code:title=assertFalse}<cffunction name="clearPrivilegesShouldClearPrivilegesFromObject">
<cfset obj = createObject("component","myObject")>
<cfset obj.addPrivilege("EditUsers")>
<cfset assertFalse( StructIsEmpty(obj.getPrivileges()), "Guard assertion: Ensure we're starting out with privileges before testing clearPrivileges()")>
<cfset result = obj.clearPrivileges()>
<cfset assertTrue( StructIsEmpty(obj.getPrivileges()), "clearPrivileges Should Have Emptied The Structure of privileges but didn't" )>
</cffunction>
{code}
h2. assert(boolean condition \[,String message\])
assert is semantically equivalent to assertTrue, providing a shorter form :
{code:title=assert()}<cffunction name="testAssert">
<cfset assert( 1 eq 1, "Testing a true expression")>
<cfset assert( not 1 eq 2, "Testing negated expression")>
</cffunction>
{code}
h2. assertEquals*(any expected, any actual \[, String message\])
assertEquals is the other core assertion. Here, you're asserting that some result equals some expected result. This could be two numbers, two strings, two structs, whatever. For now, MXUnit follows the JUnit pattern of using a single assertEquals to compare any type of data.
{code:title=assertEquals()}<cffunction name="clearPrivilegesShouldClearPrivilegesFromObject">
<cfset obj = createObject("component","myObject")>
<cfset obj.addPrivilege("EditUsers")>
<cfset assertEquals(1, StructCount(obj.getPrivileges()), "Guard assertion: Ensure we're starting out with privileges before testing clearPrivileges()")>
<cfset result = obj.clearPrivileges()>
<cfset assertEquals(0, StructCount(obj.getPrivileges()), "clearPrivileges Should Have Emptied The Structure of privileges but didn't" )>
</cffunction>
{code}
h3. Comparing Arrays, Queries, and Structures
MXUnit will do a deep compare for arrays, queries, and structures. It is *not* fail-fast, meaning that an assertEquals( struct1, struct2 ) will compare every key in the struct, including any nested structures or arrays, accumulating mismatches. Once every key is visited, the existence of mismatches will signal an assertion failure. Array, Query, and Struct comparisons will add a Structure result into the debug output if the assertion fails, and you can view the full set of differences from there.
In addition, when using the Eclipse plugin, you can toggle the "Compare Dialog" to pop up Eclipse's comparison tool, which enables you to step through all the differences.
Here's an example
!CompareDialog.PNG|thumbnail!
h2. fail*(String message)
fail() is used to actively fail a test. It's useful when you're stubbing a test and you want to ensure it fails, like so:
{code:title=fail()}<cffunction name="addPrivilegeShouldHaveNoEffectIfPrivilegeExists">
<cfset fail("test not yet implemented")>
</cffunction>
{code}
It's also useful when you're testing an "error path", like so:
{code:title=fail() to test Error Paths}<cffunction name="addPrivilegesWithPunctuationShouldThrowError">
<cfset var obj = createObject("component","myObject")>
<cftry>
<cfset obj.addPrivilege("Edit.User")>
<cfset fail("Should not get here. Function under test should've thrown an error")>
<cfcatch type="mxunit.exception.AssertionFailedError">
<cfrethrow>
</cfcatch>
<cfcatch type="any"><!--- expect to get here ---></cfcatch>
</cftry>
</cffunction>
{code}
h2. failNotEquals*(any value, any value2 \[,String message\])
Used to fail when two values do not equal. This doesn't perform any assertion... it's simply a convenience method for providing a specific type of failure message
{code:title=failNotEquals()}<cffunction name="demoFailNotEquals">
<cfset failNotEquals(myObject1,myOtherObject, "These should not have the same value")>
</cffunction>
{code}
h2. assertSame*(any obj1, any obj2 \[,String message\])
Used to determine if the obj1 and obj2 refer to the same instance.
Note that arrays in Adobe ColdFusion are passed by value, so, this will always fail for arrays.
{code:title=assertSame()}<cffunction name="initShouldReturnSelf">
<cfset var obj = createObject("component","myObject")>
<cfset assertSame(obj,obj.init(), "These should be the same thang since init should return 'this'")>
</cffunction>
{code}
h2. assertNotSame*(any obj1, any obj2 \[,String message\])
Used to determine if the obj1 and obj2 _do not_ refer to the same instance.
Note that arrays in Adobe ColdFusion are passed by value, so, this will always pass for arrays.
{code:title=assertNotSame()}<cffunction name="newInstanceShouldNotReturnSelf">
<cfset var obj = createObject("component","myObjectFactory")>
<cfset assertNotSame(obj,obj.newInstance(), "These should not be the same thang since newInstance should return a new instance from the factory")>
</cffunction>
{code}
h1. MXUnit Assertion Extensions
These are extensions to the base set of assertions and are specific to ColdFusion.Note, that these are quite simple, can be easily implemented using the base assertions above, but are provided for convenience.
*Note:* These extensions can be disabled at runtime by editing the mxunit-config.xml located in /mxunit/framework/ directory. Simply remove or comment out these line:
{code:title=assertionExtension config-extension in mxunit-config.xml} <config-element type="assertionExtension" path="MXUnitAssertionExtensions" autoload="true" override="false" />
<config-element type="assertionExtension" path="HamcrestAssert" autoload="true" override="false" />
<config-element type="assertionExtension" path="XPathAssert" autoload="true" override="false" />
{code}
h2. assertXPath*(String xpath, any data, \[String text\], \[String message\])
Searches data using xpath. If text is specified, it tries to match the exact text to the xpath expression. Otherwise ,it returns true if any nodes are found that match the xpath expression. Note that, unlike most assertions, assertXPath returns an xml dom representation of any nodes found. This can be useful for further inspection.
*Parameters* String xpath: string representing an xpath expression
any data: String or URL to search; e.g., ..., [http://google.com], [file://c:/path/to/my.html]
\[string text\]: The text to match against the xpath expression. If omitted, this assertion returns true if any elements of the xpath expression are found. Not required. Defaults to ""
\[string message\]: The message to display when this assertion fails Not required. Defaults to The XPath expression, #arguments.xpath#, did not match the data.
{code:title=assertXPath()}<cffunction name="testFindGoogleInTitle">
<cfscript>
nodes = assertXpath('/html/head/title', "http://google.com", "Google");
debug(nodes);
nodes = assertXPath("/html/head/title", "file:///coldfusion8/wwwroot/mxunit/tests/framework/fixture/xpath/mxunit.org.html");
nodes = assertXPath("/root/foo/bar[@id='123abc']", someXmlOrHtml);
</cfscript>
</cffunction>
{code}The above parses the results from urls and strings and searches the parsed results for the XPath expression.
Try it. Really, it works\!
h2. assertIsTypeOf*(component obj, String type)
Determines if obj is of type. type needs to be fully qualified.
{code:title=assertIsTypeOf()}<cffunction name="demoAssertIsTypeOf">
<cfset assertIsTypeOf(obj,"my.type.Of.Object")>
</cffunction>
{code}
h2. assertIsXMLDoc*(any xml \[, String message\])
Determines if xml is a valid XML DOM object.
{code:title=assertIsXMLDoc()}<cffunction name="demoAssertIsXMLDoc">
<cfset assertIsXMLDoc(xml)>
</cffunction>
{code}
h2. assertIsArray*(any obj1)
Determines if the obj1 is a valid array.
{code:title=assertIsArray()}<cffunction name="demoAssertIsArray">
<cfset assertIsArray(myObject1)>
</cffunction>
{code}
h2. assertIsDefined*(any obj1)
Determines if the obj1 has been defined in the available scope.
{code:title=assertIsDefined()}<cffunction name="demoAssertIsDefined">
<cfset assertIsDefined("myObject1")>
</cffunction>
{code}
h2. assertIsEmpty*(any obj1)
Determines if the obj1 is a 0 length string or NULL equivalent.
{code:title=assertIsEmpty()}<cffunction name="demoAssertIsEmpty">
<cfset assertIsEmpty(myObject1)>
</cffunction>
{code}
h2. assertIsEmptyArray*(any obj1,\[String message\])
Determines if the obj1 is an array with no elements.
{code:title=assertIsEmptyArray()}<cffunction name="demoAssertIsEmptyArray">
<cfset assertIsEmptyArray(myObject1)>
</cffunction>
{code}
h2. assertIsEmptyQuery*(any obj1,\[String message\])
Determines if the obj1 is a query with no rows.
{code:title=assertIsEmptyQuery()}<cffunction name="demoAssertIsEmptyQuery">
<cfset assertIsEmptyQuery(myObject1)>
</cffunction>
{code}
h2. assertIsEmptyStruct*(any obj1,\[String message\])
Determines if the obj1 is a struct with no keys or values.
{code:title=assertIsEmptyStruct()}<cffunction name="demoAssertIsEmptyStruct">
<cfset assertIsEmptyStruct(myObject1)>
</cffunction>
{code}
h2. assertIsQuery*(any q)
Determines if q is a valid ColdFusion query.
{code:title=assertIsQuery()}<cffunction name="demoAssertIsQuery">
<cfset assertIsQuery(q)>
</cffunction>
{code}
h2. assertIsStruct*(any obj)
Determines if obj is a valid ColdFusion structure.
{code:title=assertIsStruct()}<cffunction name="demoAssertIsStruct">
<cfset assertIsStruct(obj)>
</cffunction>
{code}
----
Need more? [Build your own ...|Custom Assertions]