developer.com
Search EarthWeb
CodeGuru | Gamelan | Jars | Wireless | Discussions
Navigate developer.com
Architecture & Design  
Database  
Java
Languages & Tools
Microsoft & .NET
Open Source  
Project Management  
Security  
Techniques  
Voice  
Web Services  
Wireless/Mobile
XML  
New
 
Technology Jobs  

   Developer.com Webcasts:
  The Impact of Coding Standards and Code Reviews

  Project Management for the Developer

  Defining Your Own Software Development Methodology

  more Webcasts...




Vote for the Developer.com Product of the Year Winners!




Developer Jobs

Be a Commerce Partner














 


Developer News -
Red Hat Fedora Claims It's the Leader in Linux    November 21, 2008
Dos and Don'ts of SOA Data Access    November 20, 2008
Mandrake Linux Founder Back, Virtually    November 20, 2008
Amazon: We're a Technology Company    November 19, 2008
Free Tech Newsletter -

Considering Test-After Development
By Jeff Langr

Go to page: 1  2  3  Next  

In this article, I'll build a solution twice. First, I'll write the code for a "reverser" method, a simple bit of code that reverses the order of words in an input string. I'll then use the stricter technique known as test-driven development to re-build the solution.

Test-After Development

In test-after development (TAD), I use my skills as an experienced developer to write my code. I might sometimes write a test prior to development. Predominantly, however, I will first code a solution, and then look to refactor as necessary. I might code additional tests once my solution is in place, but that's my prerogative.

A first test, if I bother to code one, represents a shot at the whole ball of wax. For this example, my first test reverses a full sentence, a test case that will require the final, real logic to get it to pass. Or, at least what I think is the final required logic.

import static org.junit.Assert.*;
import org.junit.*;

public class ReverserTest {
   @Test
   public void reverse() {
      Reverser reverser = new Reverser();
      String text = "This is a short sentence";
      assertEquals("sentence short a is This",
                   reverser.reverse(text));
   }
}

The test takes me about 45 seconds to write. I have to think a bit about the reverse-order loop logic as I code a solution. My total time to get the test to pass is about 120 seconds.

public String reverse(String text) {
   StringBuilder buffer = new StringBuilder();
   String[] words = text.split(" ");
   for (int i = words.length - 1; i >= 0; i--) {
      buffer.append(words[i]);
      if (i > 0)
         buffer.append(' ');
   }
   return buffer.toString();
}

After coding, I reflect on my solution. I recognize that I should probably worry about the case where words are separated by more than a single space character. I code a solution without worrying about the tests. I'm confident that adding a call to the trim method, a small, simple change, will suffice.

public String reverse(String text) {
   StringBuilder buffer = new StringBuilder();
   String[] words = text.split(" ");
   for (int i = words.length - 1; i >= 0; i--) {
      buffer.append(words[i].trim());
      if (i > 0)
         buffer.append(' ');
   }
   return buffer.toString();
}

Ahh. Ready to ship, right? No. My experience tells me that something isn't quite right with the solution. My gut tells me to write an additional test. The test says that the string returned by the reverser method should have eliminated additional spaces.

import static org.junit.Assert.*;
import org.junit.*;

public class ReverserTest {
   private Reverser reverser;

   @Before
   public void initialize() {
      reverser = new Reverser();
   }

   @Test
   public void reverse() {
      String text = "This is a short sentence";
      assertEquals("sentence short a is This",
                   reverser.reverse(text));
   }

   @Test
   public void reverseWithExtraSpaces() {
      String text = "This is a  short sentence";
      assertEquals("sentence short a is This",
                   reverser.reverse(text));
   }
}

Time to write the test: about 30 seconds (including refactoring to a common setup method). The test fails. The actual response returns the extra space between "short" and "a."

Expected: sentence short a is This
Actual:   sentence short  a is This

Racking my brain for a few seconds, I remember that the split method takes a regular expression. I need to split on any grouping of one or more spaces, not just a single space:

public String reverse(String text) {
   StringBuilder buffer = new StringBuilder();
   String[] words = text.split("\\s+");    // <- change
   for (int i = words.length - 1; i >= 0; i--) {
      buffer.append(words[i].trim());
      if (i > 0)
         buffer.append(' ');
   }
   return buffer.toString();
}

Well, now that I think about it a bit harder, the call to trim is no longer necessary. I might not have noticed. And if I hadn't built a test, I probably wouldn't bother removing this redundancy even if I had noticed it.

Think time + solution time: 30 seconds.

Both tests pass. Ship it!

It was a good thing that I used my experience to remember to write a test for such a trivial change. Are there other tests that I need to write? Maybe I should look at the code a bit longer...

Go to page: 1  2  3  Next  

Next article: Testability and Design


Tools:
Add www.developer.com to your favorites
Add www.developer.com to your browser search box
IE 7 | Firefox 2.0 | Firefox 1.5.x
Receive news via our XML/RSS feed


Techniques Archives






internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info

Legal Notices, Licensing, Reprints, Permissions, Privacy Policy.
Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers