Less Dependent Testing


If you're unfortunate enough to not be connected to the Internet on your computer, you're probably grousing about your inability to execute ServerTest at all. You will now rectify this situation by changing the search URLs to file URLs.[2] This also means you can write out test HTML files to control the content of the "web" pages searched.

[2] Another solution would involve installing a local web server, such as Tomcat.

 package sis.search; import junit.framework.TestCase; import java.io.*; import java.util.*; import sis.util.*; public class SearchTest extends TestCase {    public static final String[] TEST_HTML = {       "<html>",       "<body>",       "Book: Agile Java, by Jeff Langr<br />",       "Synopsis: Mr Langr teaches you<br />",       "Java via test-driven development.<br />",       "</body></html>"};    public static final String FILE = "/temp/testFileSearch.html";    public static final String URL = "file:" + FILE;    protected void setUp() throws IOException {       TestUtil.delete(FILE);       LineWriter.write(FILE, TEST_HTML);    }    protected void tearDown() throws IOException {       TestUtil.delete(FILE);    }    // ... 

You will need the LineWriter utility; here is the test and production source.

 // LineWriterTest.java package sis.util; import junit.framework.*; import java.io.*; public class LineWriterTest extends TestCase {    public void testMultipleRecords() throws IOException {       final String file = "LineWriterTest.testCreate.txt";       try {          LineWriter.write(file, new String[] {"a", "b"});          BufferedReader reader = null;          try {             reader = new BufferedReader(new FileReader(file));             assertEquals("a", reader.readLine());             assertEquals("b", reader.readLine());             assertNull(reader.readLine());          }          finally {             if (reader != null)                reader.close();          }       }       finally {          TestUtil.delete(file);       }    } } // LineWriter.java package sis.util; import java.io.*; public class LineWriter {    public static void write(String filename, String[] records)           throws IOException {       BufferedWriter writer = null;       try {          writer = new BufferedWriter(new FileWriter(filename));          for (int i = 0; i < records.length; i++) {             writer.write(records[i]);             writer.newLine();          }       }       finally {          if (writer != null)             writer.close();       }    } } 

The good part is that the changes to SearchTest are not very invasive. In fact, none of the test methods need change. You are adding setup and teardown methods to write HTML to a local file and subsequently delete that file each time a test completes. You are also changing the URL to use the file protocol instead of the http protocol.

Initialization Expressions

The method searchUrl contains the code:

 String line; while ((line = reader.readLine()) != null) 

The parentheses should help you understand this code. First, the result of reader.readLine() is assigned to the line reference variable. The value of the line reference is compared to null to determine whether or not the while loop should terminate.


The bad part is that the Search class must change. To obtain an InputStream from a URL with a file protocol, you must extract the path information from the URL and use it to open the stream as a FileInputStream. It's not a significant change. The minor downside is that you now have a bit of code in your production system that will probably only be used by the test.

 private void searchUrl() throws IOException {    InputStream input = getInputStream(url);    BufferedReader reader = null;    try {       reader = new BufferedReader(new InputStreamReader(input));       String line;       while ((line = reader.readLine()) != null)          matches += StringUtil.occurrences(line, searchString);    }    finally {       if (reader != null)          reader.close();    } } private InputStream getInputStream(URL url) throws IOException {    if (url.getProtocol().startsWith("http")) {       URLConnection connection = url.openConnection();       return connection.getInputStream();    }    else if (url.getProtocol().equals("file")) {       return new FileInputStream(url.getPath());    }    return null; } 

One other thing you want to consider is that you are no longer exercising the portion of of the code that deals with an http URL. The best approach is to ensure that you have adequate coverage at an acceptance test[3] level. Acceptance tests provide a level of testing above unit testingthey test the system from an end user's standpoint. They are executed against as live a system as possible and should not use mocks. For the search application, you would certainly execute acceptance tests that used live web URLs.

[3] There are many different nomenclatures for different types of testing. Acceptance tests are the tests that signify that the system meets the acceptance criteria of the customer to whom it's delivered. You may hear these tests referred to as customer tests.



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net