ColdFusion TIPS PLUS
Issue 00108 http://www.cftipsplus.com
I. My CommentsII. ColdFusion In Context: Test First
By R. Martin Ladner
martin.ladner@knology.net
See our sponsors at the bottom of this e-mail.
I. Comments:
Hope things are going good for everyone. I want some side work so if you know of anyone who has some please send and email to: NathanS<at>nsnd.com I have resources other then myself to complete the project if it is a larger one. If you don't know what you want still let me know.
If you have an idea how to make this website make money and want to make some of the money too. Please email me with your idea and how we both could make some money without charging the readers. My Email: NathanS<at>nsnd.com
Keep Coding,
Nathan Stanford
http://www.cftipsplus.com
If you have suggestions for articles send them to us.
If you would like to write for cftipsplus.com
send us an email to:
NathanS<at>nsnd.com
IF YOU WANT TO BE AN AUTHOR SEND IN YOUR COLDFUSION TIPS.
Remember this is a great way to get your name known in the
ColdFusion Community.
II. ColdFusion in Context: Test First
By R. Martin Ladner
martin.ladner@knology.net
A tenet of eXtreme Programming is that you write the test first, automate it if possible, and then write the simplest application code that satisfies that test. This tip won't try to check client-side interaction through javascript, but it will suggest a way to test the behavior of server-side code: the cfhttp tag. Let's look at login.
Test Login
For the purpose of this demonstration, your login must meet a number of criteria. Recall that even though you will eventually test much of this behavior in javascript, you need to make the same (seemingly redundant) tests on the server. Clients may not have enabled javascript, or they may have gotten creative (using techniques similar to the ones you'll use for test).
Simple Criteria:
1. If the username is empty, inform the user it cannot be empty; return to the login screen after acknowledgment.
2. If the password is empty, inform the user it cannot be empty; return to the login screen after acknowledgment.
3. If both are missing, inform the user that the username and password cannot be empty; return to the login screen after acknowledgment.
4. If both are present, pass (for now). You'll add functionality outside this tip.
Assume the login screen is mysite.cfm and its action page is gate.cfm. Let gate.cfm include main.cfm if successful up to this point.
Write the Test
Put all your tests in logintest.cfm. (In real life, you might define them separately and use a common page to call them.)
To use the cfhttp tag, you must specify the entire url, not just the filename. A line like this at the beginning of your test sets can save you some typing:
<cfset homeurl="http://127.0.0.1/context/testfirst/">
To know if gate.cfm will reject an empty username, you need to post one to it. Specify the url. Indicate that the method is post. Let it resolve the URL of each link on the page in case you want to follow them later. Send the username as an empty form field. You aren't really submitting a form. You're just submitting form variables as if they had come from a form. Therefore, unless the action page needs the value of a submit button for some special purpose, don't code a value for submit buttons.
<p>
login handles...
missing Username
<cfhttp url="#HomeURL#/gate.cfm" method="post" resolveurl="true">
<cfhttpparam name="username" type="formfield" value="">
<cfhttpparam name="password" type="formfield" value="kjkj">
</cfhttp>
Now you need to look at what comes back. The cfhttp.FileContent variable contains what you would see if you performed a right-click on the page returned by the server. You can parse the page's raw HTML and javascript (but not ColdFusion code; the browser never sees this) to do whatever is necessary to determine if the code is performing acceptably.
In this case, it seemed sufficient to make sure that the word "username" (regardless of case) was displayed but not the word "password" (since the presence of this word might indicate that the page wasn't smart enough to tell the user exactly what was wrong).
<cfif findNoCase("username", cfhttp.filecontent)
and (not findNoCase("password", cfhttp.filecontent))>
OK
<cfelse>
badly
</cfif>
<p>
Repeat the process to ensure that the page knows what to do about a missing password. This time, reverse the conditions you send and the conditions you are looking for.
missing Password
<cfhttp url="#HomeURL#/gate.cfm" method="post" resolveurl="true">
<cfhttpparam name="username" type="formfield" value="qwer">
<cfhttpparam name="password" type="formfield" value="">
</cfhttp>
<cfif findNoCase("password", cfhttp.filecontent)
and (not findNoCase("username", cfhttp.filecontent))>
OK
<cfelse>
badly
</cfif>
<p>
Try again, this time leaving both fields empty and making sure both fields get mentioned to the user.
missing Username and Password
<cfhttp url="#HomeURL#/gate.cfm" method="post" resolveurl="true">
<cfhttpparam name="username" type="formfield" value="">
<cfhttpparam name="password" type="formfield" value="">
</cfhttp>
<cfif findNoCase("username", cfhttp.filecontent)
and findNoCase("password", cfhttp.filecontent)>
OK
<cfelse>
badly
</cfif>
<p>
You might be fortunate enough to have the customer enter both a Username and Password. Simulate that by filling in both fields. Then see if text comes back from the "success" page: main.cfm.
filled-in Username and Password
<cfhttp url="#HomeURL#/gate.cfm" method="post" resolveurl="true">
<cfhttpparam name="username" type="formfield" value="asdf">
<cfhttpparam name="password" type="formfield" value="qwer">
</cfhttp>
<cfif findNoCase("main", cfhttp.filecontent)>
OK
<cfelse>
badly
</cfif>
If you want more information - perhaps you're just starting off and you're not sure that you're even connecting to the page properly - examine the entire cfhttp structure by using cfdump, commented out for this example until you need it.
<!--- uncomment and copy if detail is needed
<cfdump var="#cfhttp#"> --->
Write the Application Code
After reviewing the test, writing the code is easy. Create main.cfm. Have it say "MAIN" so you know when you reach it. To build gate.cfm, there are many likely approaches. Here are three.
1. Copy this buggy code to gate.cfm, browse testlogin.cfm, and see what it says.
<!--- Buggy code --->
<cfparam name="form.username" default="">
<cfparam name="form.password" default="">
<cfif not len(form.username)>
The username cannot be empty.
<form><input type="submit" name="doit" value="OK"></form>
<cfelseif not len(form.password)>
The password cannot be empty.
<form><input type="submit" name="doit" value="OK"></form>
<cfelseif not len(form.username) and not len(form.password)>
The username and password cannot be empty.
<form><input type="submit" name="doit" value="OK"></form>
</cfif>
<cfinclude template="main.cfm">
2. Try this code instead.
<!--- Wasteful code --->
<cfparam name="form.username" default="">
<cfparam name="form.password" default="">
<cfif not len(form.username) and not len(form.password)>
The username and password cannot be empty.
<form><input type="submit" name="doit" value="OK"></form>
<cfelseif not len(form.username)>
The username cannot be empty.
<form><input type="submit" name="doit" value="OK"></form>
<cfelseif not len(form.password)>
The password cannot be empty.
<form><input type="submit" name="doit" value="OK"></form>
<cfelse>
<cfinclude template="main.cfm">
</cfif>
3. Try this approach.
<!--- Straightforward approach --->
<cfparam name="form.username" default="">
<cfparam name="form.password" default="">
<cfif not len(form.username) and not len(form.password)>
The username and password cannot be empty.
<cfelseif not len(form.username)>
The username cannot be empty.
<cfelseif not len(form.password)>
The password cannot be empty.
<cfelse>
<cfinclude template="main.cfm">
</cfif>
<form><input type="submit" name="doit" value="OK"></form>
Review
By now, you've noticed that having an automated test gives you the freedom to create the application code in any way that makes sense to you. The first attempt had a bug. The second was verbose. The third was OK. You can probably do better. The best code is the simplest code that passes the test.
=Marty=
SPONSOR ADS:
This e-mail is sponsored by the following ads.
Books For Sale
http://nsnd.vstorelibrary.com/
Advanced, Intensive ColdFusion Training!Visit this site. If you have plans to get training here is a company
that provides Advanced, Intensive ColdFusion Training. Check them out.
http://www.coldfusiontraining.com/index.cfm?ref=cftipsplus
Publisher and Creator:
Nathan Stanford,
NathanS<at>nsnd.com
http://www.cftipsplus.com
Macromedia and ColdFusion are U.S. registered trademarks.
Copyright (c) 2000 - 2002
CFTIPSPLUS.COM and NSND.COM
Permission is granted to circulate this publication via
MANUAL forwarding by email to friends provided that the text is
forwarded in its entirety and no fee is charged.