<H2>TDD Example: Implementing new functionality</H2>
<P>This case study will demonstrate how I implemented new functionality into MXUnit itself using a test-driven approach. I took screenshots at virtually every step in the process. At the end of the case study, I'll explain the changes that took place between the first iteration of the code and a subsequent change a few days later, although I won't document that in pictures. To see the current implementation and the test case that tests the functionality, <A href="http://mxunit.org/download.cfm">download MXUnit</A> and open mxunit/framework/PublicProxyMaker.cfc and mxunit/tests/framework/PublicProxyMakerTest.cfc </P>
<P>The voice is in the present tense so that you can see what I was thinking as it was happening. </P>
<H3>The Functionality</H3>
<P>I wanted to add a way into MXUnit for more easily testing private methods. A discussion on this topic <A href="index.cfm?doc=testprivate" mce_href="index.cfm?doc=testprivate">is here</A> so I won't go into it again. My goal was to create testable private methods in a line of code, inside the test case itself, without the need for the person writing the tests to create any more components.</P>
<H3>How I intend to implement it</H3>
<P>I intend to make a new component named PublicProxyMaker.cfc. This will contain a function named makePublic(objectWithPrivateMethod, privateMethodUnderTest, optional name for new public method).</P>
<P>makePublic() will create a new throwaway component that contains a public function that will itself call the private function. it will then inject this new public function into the object with the private method. the new public method will be named either whatever it was the programmer passed in as the third arg OR it will be the same as the private function itself, but prefixed with a "_".</P>
<P>I will then add a passthrough call to makePublic() into TestCase itself as a convenience to the programmer so that the test programmer doesn't have to know about the PublicProxyMaker component. All they need to know is that there's a function named makePublic() that they can use. </P>
<P>Thus, the programmer should be able to call this new functionality like this:</P>
<P><CFSET component objwithprivate="createObject("></CFSET></P>
<P><CFSET makepublic></CFSET></P>
<P><CFSET objwithprivate.somepublicproxyfortheprivate></CFSET></P>
<P>OR </P>
<P><CFSET makepublic></CFSET></P>
<P><CFSET objwithprivate._someprivate></CFSET></P>
<P>My approach will be to implement the functionality in the PublicProxyMaker and then, finally, to add the passthrough into the TestCase.cfc component. Thus, the test case I myself write for this new functionality will call maker.makePublic(), but in the end the programmer using MXUnit would not have to work directly with PublicProxyMaker</P>
<P><BR></BR><BR></BR></P>
<H3>The case study, in Pictures </H3>
<P><B>Step 1:</B> Run all existing tests first</P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/1%20-%20run%20all%20tests%20first.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/1%20-%20run%20all%20tests%20first.png"><IMG border="0" height="261" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/1%20-%20run%20all%20tests%20first.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/1%20-%20run%20all%20tests%20first.jpg" width="325"></IMG></A></P>
<P><B>Step 2: </B>View problems-only mode for easier reading</P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/2%20-%20problems-only%20mode.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/2%20-%20problems-only%20mode.png"><IMG border="0" height="261" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/2%20-%20problems-only%20mode.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/2%20-%20problems-only%20mode.jpg" width="325"></IMG></A></P>
<P><B>Step 3</B>: FOR MYLYN USERS: Open the issue in the Eclipse mylyn browser and activate it (push the blue button). This filters out all the nonessential junk from the navigator view and adds only relevant files as I open them. In the navigator, the "filtering" can be turned on and off by toggling the 3-dot button in that view without needing to deactivate the issue </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/3%20-%20Issue%20in%20mylyn%20browser.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/3%20-%20Issue%20in%20mylyn%20browser.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/3%20-%20Issue%20in%20mylyn%20browser.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/3%20-%20Issue%20in%20mylyn%20browser.jpg" width="365"></IMG></A></P>
<P><B>Step 4: </B>Create new test case. I intend to name the component that contains my new functionality "PublicProxyMaker", so my test case will be named "PublicProxyMakerTest.cfc". Note that I haven't yet created PublicProxyMaker.cfc</P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/4%20-%20create%20new%20test%20case.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/4%20-%20create%20new%20test%20case.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/4%20-%20create%20new%20test%20case.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/4%20-%20create%20new%20test%20case.jpg" width="365"></IMG></A></P>
<P><B>Step 5:</B> Add new tests that better fail. Run them in the MXUnit view. What I expect here is a "component not found" error since I haven't built the components i'm testing yet. So... these should fail in setUp() and never even make it into the actual test. </P>
<P>NOTE: you'll notice that my Test Case name is PublicProxyMakerTest.cfc. And you'll notice that I'm creating an object called "sanity" on the component "PublicProxyMakerTest". WTF???? Basically this is my lazy way of creating an object that I know has a private function. I know it might seem weird to be creating another instance of itself. Ignore it. It's another instance ... it's not testing "this". So it's safe to do this. Also you'll see later on when I change the name "sanity" to something else because it kept tripping me up. </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/5%20-%20add%20some%20stuff%20sure%20to%20fail%20and%20run.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/5%20-%20add%20some%20stuff%20sure%20to%20fail%20and%20run.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/5%20-%20add%20some%20stuff%20sure%20to%20fail%20and%20run.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/5%20-%20add%20some%20stuff%20sure%20to%20fail%20and%20run.jpg" width="365"></IMG></A></P>
<P><B>Step 6:</B> Create component to test this on. this is just a stub so that I can get past setUp() and into my test functions. My new component is named "PublicProxyMaker". </P>
<P>Note that those test functions aren't actually implemented yet. So technically I'm not following strict TDD here. But that's OK. This is kind of how I work..... chip away at things. I find that I like the momentum that comes with tiny little incremental successes. </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/6%20-%20Create%20Component%20to%20test.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/6%20-%20Create%20Component%20to%20test.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/6%20-%20Create%20Component%20to%20test.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/6%20-%20Create%20Component%20to%20test.jpg" width="365"></IMG></A></P>
<P><B>Step 7: </B>Implement a sanity check test. this is the testSanity function in this test case. Basically, it just confirms that I can't test a private method directly. If that test were to not pass, that would mean either the function i'm trying to run isn't private or something else weird is going on. I like to start knowing that all is working as expected. In this case, what I expect is that trying to run a private function will fail. My expectation is proven correct, so I can proceed. </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/7%20-%20implement%20sanity%20check%20test.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/7%20-%20implement%20sanity%20check%20test.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/7%20-%20implement%20sanity%20check%20test.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/7%20-%20implement%20sanity%20check%20test.jpg" width="365"></IMG></A></P>
<P><B>Step 8:</B> Implement first test. this is the "testMakePublicNamedArgs" function. This new functionality needs to work both with passing in named args and also not naming the arguments. This one I suspect will be the easiest to confirm so that's where I start. NOTE: the test fails because the function under test doesn't exist yet! </P>
<P>Thus, I wrote my test first that tests the behavior I expect out of the function that I haven't even written yet. This is classic TDD: you test the behavior you want, and when the test passes, you're done. </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/8%20-%20implement%20first%20test.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/8%20-%20implement%20first%20test.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/8%20-%20implement%20first%20test.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/8%20-%20implement%20first%20test.jpg" width="365"></IMG></A></P>
<P><B>Step 9:</B> Stub the function under test. Confirm Failure</P>
<P>Here, I just get the function in place, but it doesn't do anything. I run my test again because if it passes, then my test is bad! It fails, which is a good thing. </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/9%20-%20stub%20the%20function%20under%20test;%20confirm%20failure.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/9%20-%20stub%20the%20function%20under%20test;%20confirm%20failure.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/9%20-%20stub%20the%20function%20under%20test;%20confirm%20failure.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/9%20-%20stub%20the%20function%20under%20test;%20confirm%20failure.jpg" width="365"></IMG></A></P>
<P><B>Step 10:</B> Implement the second test. Rather than work to get the first test passing, I'm going to implement the second test, which is to test what happens when arguments to my new function are not named, i.e. calling maker.makePublic(arg1, arg2, arg3) instead of maker.makePublic(arg1=blah, arg2=blah, arg3=blah) .</P>
<P>Again, it fails, as it should because I haven't actually implemented the functionality. </P>
<P><BR></BR><BR></BR><BR></BR><BR></BR></P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/10%20-%20implement%20second%20test.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/10%20-%20implement%20second%20test.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/10%20-%20implement%20second%20test.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/10%20-%20implement%20second%20test.jpg" width="365"></IMG></A></P>
<P><B>BREATHER</B>: Let's take a second to review where we're at right now:</P>
<P>We have a new component named PublicProxyMaker.cfc and a test case component named PublicProxyMakerTest.cfc. </P>
<P>PublicProxyMakerTest has 3 test functions: testSanity, testMakePublicNamedArgs, and testMakePublicNonNamedArgs.</P>
<P>testSanity passes. The other two do not because the functionality they test is not yet implemented.</P>
<P>If you look at those two test methods, you'll see that both will pass if they can run a function named "_aPrivateMethod" and that _aPrivateMethod() returns the expected result.<BR></BR><BR></BR><BR></BR><BR></BR>
</P>
<P>Now, back to the show: </P>
<P><BR></BR><BR></BR><BR></BR><BR></BR></P>
<P><B>Step 11</B>: Start implementing.</P>
<P> I do about 5 minutes of coding, and i'm at a point where I need to see my data. I need to find out what the data looks like returned from getMetadata() on my object in question. So, I turn off the failure... I need to see some cfdump. I add a cfdump into my new makePublic() function and then I comment out the failure in my test case so that I can view the output easily in the mxunit plugin view (highlight the test and hit "b" on the keyboard. this brings up the internal browser).</P>
<P>Note the cfdump in the code and the commented out stuff in the test function.</P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/11%20-%20turn%20off%20failure;%20need%20to%20see%20dump.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/11%20-%20turn%20off%20failure;%20need%20to%20see%20dump.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/11%20-%20turn%20off%20failure;%20need%20to%20see%20dump.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/11%20-%20turn%20off%20failure;%20need%20to%20see%20dump.jpg" width="365"></IMG></A></P>
<P><B>Step 12:</B> the CF Dump</P>
<P>Here's what the cfdump looks like from the code above.That's all i needed to see. Back to coding. </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/12%20-%20picture%20of%20dump.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/12%20-%20picture%20of%20dump.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/12%20-%20picture%20of%20dump.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/12%20-%20picture%20of%20dump.jpg" width="365"></IMG></A></P>
<P><B>Step 13: </B>Code implementation I think will work</P>
<P>I've got the stuff uncommented again in the test case, and I crank out some code I think will work in makePublic(). </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/13%20-%20code%20implementation%20i%20think%20will%20work.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/13%20-%20code%20implementation%20i%20think%20will%20work.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/13%20-%20code%20implementation%20i%20think%20will%20work.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/13%20-%20code%20implementation%20i%20think%20will%20work.jpg" width="365"></IMG></A></P>
<P><B>Step 14:</B> Dagnabbit. It didn't work</P>
<P>I thought I had it, but I guess I didn't. It's giving me function "_aPrivateMethod" not found. WTF? I need to see the data again. </P>
<P>This time, I just add <CFSET debug> into the test case itself. This yields nothing useful. </CFSET></P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/14%20-%20damn%20it%20didnt%20work.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/14%20-%20damn%20it%20didnt%20work.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/14%20-%20damn%20it%20didnt%20work.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/14%20-%20damn%20it%20didnt%20work.jpg" width="365"></IMG></A></P>
<P><B>Step 15:</B> Crap. my variable names caused my problems</P>
<P>An AHA moment. my test case was bad! It was calling <CFSET result="maker._aPrivateMethod(...)">, but it should've been calling <CFSET result="sanity._aPrivateMethod(...)"> because the whole point of the makePublic() code is to inject a new public function into the object that's passed to it, which in this case was the "sanity" object.</CFSET></CFSET></P>
<P><BR></BR><BR></BR><BR></BR><BR></BR></P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/15%20-%20CRAP%20-%20my%20dumb%20variable%20names%20caused%20my%20problem.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/15%20%20CRAP%20-%20my%20dumb%20variable%20names%20caused%20my%20problem.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/15%20%20CRAP%20-%20my%20dumb%20variable%20names%20caused%20my%20problem.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/15%20%20CRAP%20--%20my%20dumb%20variable%20names%20caused%20my%20problem.jpg" width="365"></IMG></A></P>
<P>This teaches me something: use really clear variable names. "sanity" was a dumb name to start with. First, I change the test case to be cfset result = sanity._aPrivateMethod.</P>
<P>Then I scrap "sanity" entirely and rename the object "objectWithPrivateMethod". That's much clearer. I do a search/replace in my test case and I'm back in action. In addition, I also fix the code in testMakePublicNonNamedArgs because it, too, was calling maker._aPrivateMethod instead of sanity._aPrivateMethod </P>
<P>This next screen shot will demonstrate the new variable names and such. </P>
<P><B>Step 16: </B>Finally, a good error. With my new variable names in place and me feeling good that things are finally clearer, I run the test again. And I get a new failure message. "PrivateMethodName" is not defined. Some code bug.</P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/16%20-%20good%20error%20-%20the%20function%20is%20being%20injected.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/16%20%20good%20error%20-%20the%20function%20is%20being%20injected.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/16%20%20good%20error%20-%20the%20function%20is%20being%20injected.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/16%20%20good%20error%20--%20the%20function%20is%20being%20injected.jpg" width="365"></IMG></A></P>
<P>So I fix the bug in the makePublic() code (it was something dumb... typo or something). </P>
<P><B>Step 17:</B> Works for one but not the other. This means the implementation isn't right </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/17%20-%20Works%20for%20one%20but%20not%20the%20other.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/17%20-%20Works%20for%20one%20but%20not%20the%20other.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/17%20-%20Works%20for%20one%20but%20not%20the%20other.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/17%20-%20Works%20for%20one%20but%20not%20the%20other.jpg" width="365"></IMG></A></P>
<P><B>Step 18: </B>Have to change implementation. It's busted. Back to being broken for both test cases. </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/18%20-%20Have%20to%20change%20implementation;%20Back%20to%20being%20broken.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/18%20-%20Have%20to%20change%20implementation;%20Back%20to%20being%20broken.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/18%20-%20Have%20to%20change%20implementation;%20Back%20to%20being%20broken.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/18%20-%20Have%20to%20change%20implementation;%20Back%20to%20being%20broken.jpg" width="365"></IMG></A></P>
<P>So back at it. I basically have to completely rewrite a private function inside PublicProxyMaker named "constructArgumentsString". At first shot, I was just creating a function that did this:</P>
<P><CFFUNCTION access="public" name="#whatever#"></CFFUNCTION></P>
<P><CFRETURN></CFRETURN></P>
<P><BR></BR></P>
<P>And that worked fine for the named args but not the unnamed args. </P>
<P>So this means I'm going to have to create a proper set of cfargument tags in this new public function that will be injected, and it means i'll have to have to properly call the privateMethod in question using those named args. </P>
<P>So... I do that, then rerun my tests. </P>
<P><B>Step 19:</B> All Green!</P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/19%20-%20All%20Green%21.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/19%20-%20All%20Green!.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/19%20-%20All%20Green!.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/19%20-%20All%20Green%21.jpg" width="365"></IMG></A></P>
<P><B>Step 20: </B>Works when adding a file delete (that's a good thing)</P>
<P>I want to be sure that this temp component being created gets cleaned up. so I add a cffile delete on it. I run the tests again, and all is still well. </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/20%20-%20Works%20when%20adding%20delete.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/20%20-%20Works%20when%20adding%20delete.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/20%20-%20Works%20when%20adding%20delete.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/20%20-%20Works%20when%20adding%20delete.jpg" width="365"></IMG></A></P>
<P>Step 21: Poor behavior for undefined method</P>
<P>I want to know how this thing will behave should a programmer try to create a public proxy for an undefined method. So I add a test for that. </P>
<P>But I don't like the error message I see. Completely unhelpful. </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/21%20-%20poor%20behavior%20for%20undefined%20mehtod.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/21%20-%20poor%20behavior%20for%20undefined%20mehtod.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/21%20-%20poor%20behavior%20for%20undefined%20mehtod.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/21%20-%20poor%20behavior%20for%20undefined%20mehtod.jpg" width="365"></IMG></A></P>
<P>So I add some additional code into makePublic(). </P>
<P>Step 22: I like this error better</P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/22%20-%20I%20like%20this%20error%20better.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/22%20-%20I%20like%20this%20error%20better.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/22%20-%20I%20like%20this%20error%20better.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/22%20-%20I%20like%20this%20error%20better.jpg" width="365"></IMG></A></P>
<P>Step 23: Make that test proper</P>
<P>Now that I know what the error is going to look like and I'm satisified with it, I write a proper test for the nonexistent method scenario. </P>
<P>Yes, this is backward from TDD. I don't care. Without seeing the actual failure behavior first, I couldn't tell what it was going to behave like. </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/23%20-%20make%20that%20test%20proper.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/23%20-%20make%20that%20test%20proper.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/23%20-%20make%20that%20test%20proper.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/23%20-%20make%20that%20test%20proper.jpg" width="365"></IMG></A></P>
<P>Step 24: Test method with no arguments. Make sure that if a private method doesn't have any arguments that the code doesn't gack. Just seems like a smart thing to do, that's all. </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/24%20-%20Test%20for%20method%20with%20no%20args.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/24%20-%20Test%20for%20method%20with%20no%20args.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/24%20-%20Test%20for%20method%20with%20no%20args.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/24%20-%20Test%20for%20method%20with%20no%20args.jpg" width="365"></IMG></A></P>
<P>Step 25: Almost done – run all tests again.</P>
<P>So far, everything is looking good. Now I want to run all tests again that I ran at the outset. This is all tests I have, not just the ones I just wrote. This is a habit of mine.</P>
<P>Also, as of right now, I still haven't added the passthrough into TestCase.cfc yet. </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/25%20-%20Almost%20done%20-%20run%20all%20tests%20again.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/25%20-%20Almost%20done%20-%20run%20all%20tests%20again.png"><IMG border="0" height="261" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/25%20-%20Almost%20done%20-%20run%20all%20tests%20again.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/25%20-%20Almost%20done%20-%20run%20all%20tests%20again.jpg" width="325"></IMG></A></P>
<P>Now I'm ready to add the passthrough into TestCase.cfc. As with before, start with the tests first.... I gotta see stuff fail so I know my tests are good. </P>
<P>Step 26: Add test for it in TestCaseTest. Start with a sanity check</P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/26%20-%20add%20test%20for%20it%20in%20TestCaseTest.%20start%20with%20a%20sanity%20check.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/26%20-%20add%20test%20for%20it%20in%20TestCaseTest.%20start%20with%20a%20sanity%20check.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/26%20-%20add%20test%20for%20it%20in%20TestCaseTest.%20start%20with%20a%20sanity%20check.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/26%20-%20add%20test%20for%20it%20in%20TestCaseTest.%20start%20with%20a%20sanity%20check.jpg" width="365"></IMG></A></P>
<P>Step 27: Add test first before adding makepublic method</P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/27%20-%20add%20test%20first%20before%20adding%20makepublic%20method.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/27%20-%20add%20test%20first%20before%20adding%20makepublic%20method.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/27%20-%20add%20test%20first%20before%20adding%20makepublic%20method.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/27%20-%20add%20test%20first%20before%20adding%20makepublic%20method.jpg" width="365"></IMG></A></P>
<P>Step 28: Add makePublic into TestCase</P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/28%20-%20add%20makePublic%20into%20testcase.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/28%20-%20add%20makePublic%20into%20testcase.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/28%20-%20add%20makePublic%20into%20testcase.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/28%20-%20add%20makePublic%20into%20testcase.jpg" width="365"></IMG></A></P>
<P>Step 29a: Run test again. All Green</P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/29%20-%20run%20test%20again%20-%20Green%20Bar.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/29%20-%20run%20test%20again%20-%20Green%20Bar.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/29%20-%20run%20test%20again%20-%20Green%20Bar.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/29%20-%20run%20test%20again%20-%20Green%20Bar.jpg" width="365"></IMG></A></P>
<P>Step 29b: Run all tests again </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/29b%20-%20run%20all%20tests%20again.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/29b%20-%20run%20all%20tests%20again.png"><IMG border="0" height="261" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/29b%20-%20run%20all%20tests%20again.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/29b%20-%20run%20all%20tests%20again.jpg" width="325"></IMG></A></P>
<P>Step 30: Commit changes. This is with the mylyn filter on which is why you only see 4 files to commit. </P>
<P><A href="http://mxunit.org/doc/images/TDDNewFunctionality/30%20-%20with%20mylyn%20filter%20on%20commit%20changes.png" mce_href="http://mxunit.org/doc/images/TDDNewFunctionality/30%20-%20with%20mylyn%20filter%20on%20commit%20changes.png"><IMG border="0" height="222" mce_src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/30%20-%20with%20mylyn%20filter%20on%20commit%20changes.jpg" src="http://mxunit.org/doc/images/TDDNewFunctionality/thumbs/30%20-%20with%20mylyn%20filter%20on%20commit%20changes.jpg" width="365"></IMG></A> </P>
Wrap Up
So, this was the initial implementation of the facility in MXUnit that makes it easier to test private methods. It did change slightly from this version, but not much. I added another "style" of working with the makePublic function. It now also returns a brand new object which extends the object you pass into it and overrides the private function you're trying to run. Essentially this is a take on the conventional method of testing private functions, just made easier. <a href="index.cfm?doc=testprivate">It's all documented here</a>.