Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>As you think about testing this program, keep in mind what unit testing is. From <a href="http://en.wikipedia.org/wiki/Unit_testing" rel="nofollow">Wikipedia</a>, "unit testing is a method by which individual units of source code... are tested to determine if they are fit for use". </p> <p>Keep in mind also that you're jumping in to the deep end a bit, because testing a multithreaded program is difficult. As much as possible, you should remove the complexity of the thread interaction from your testing of the functionality.</p> <p>Looking at your program, you've got pretty good encapsulation and separation of concerns already, so you're well on your way. My strategy here would be to test both of the <code>*Scan</code> objects independently of threading. To do so, fix in your mind what their roles are. I would say the following:</p> <ul> <li><code>FolderScan</code> walks a directory structure, finding files of a particular type, and puts files passing the filter in to a queue. When it exhausts the directory structure, it puts a specific file in the queue, counts down a latch, and exits.</li> <li><code>FileScan</code> consumes a queue of files, does an operation on them, and prints the output to the console. When it hits a specific file, it counts down a latch and exits.</li> </ul> <p>Since you already have presumably more or less working code, as you retrofit tests on to it (as opposed to writing them while writing the code, which is preferable) you want to change the source as little as possible in order to get to passing tests. After that you may wish to refactor the code, and your tests will give you confidence to do so.</p> <p><em><strong>FolderScan test</em></strong></p> <p>As a first step then, create a new JUnit test for <code>FolderScan</code>. You can write several tests, but from a high level each of them should populate a directory structure with some files. I'd test each of these cases at least:</p> <ol> <li>A single folder with a file that passes the filter.</li> <li>A single folder with a file that does NOT pass the filter.</li> <li>A nested folder with a file in each.</li> </ol> <p>The more granular the test, the better. Each test simply creates a new instance of <code>FolderScan</code>, gives it the arguments you've defined pointing at the given folder. Call run(), and make sure that:</p> <ol> <li>The queue contains the <code>File</code> objects you expect.</li> <li><code>CountDownLatch</code> has been decremented.</li> <li>The last element in queue is the 'trigger' <code>File</code>.</li> </ol> <p><em><strong>FileScan test</em></strong></p> <p>At a high level, the test for this should now be clear: create some textual <code>File</code> objects, populate a queue of with them and with a marker, and pass them in to a new FileScan objects. Again, more granular the better, so at least:</p> <ol> <li>A file with a matching string</li> <li>A file without a matching string</li> <li>Multiple files</li> </ol> <p>There is a problem with this class though, which is the classic 'how to test a Singleton' issue. The result of this object is actually piped to <code>System.out</code>, which you'd have to hook in to someway to check the result. As a first pass, I'd recommend refactoring the constructor to pass in a <code>PrintStream</code>. In production you'd pass in <code>System.out</code>, in test you'd pass in something that you can check: a <code>new PrintStream(new ByteArrayOutputStream())</code> that you can check the contents of or, even better, a mock.</p> <p>In the end, each test should check:</p> <ol> <li>The queue is emptied.</li> <li><code>CountDownLatch</code> has been decremented</li> <li>The specified <code>PrintStream</code> has had the expected content written to it.</li> </ol> <p>You should then have a great deal of confidence that both the <code>FileScan</code> and the <code>FolderScan</code> work as advertised.</p> <p><strong>* Testing askUserPathAndWord *</strong></p> <p>I don't see any straightforward way to test this function/class as written. It's violating the <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle" rel="nofollow">Single Responsibility Principle</a>, and simply doing too many things. I would extract the following responsibilities in to new methods or classes:</p> <ul> <li>Ask the user for word and path</li> <li>Given a word, create a <code>FileScan</code> with the correct parameters (a Factory)</li> <li>Given a path, create a <code>FolderScan</code> with the correct parameters (a Factory)</li> <li>Given two runnables and a latch, create a <code>ExecutorService</code>, queue them, and wait on the latch</li> </ul> <p>Then you can test them independently.</p> <p><strong>* Next steps *</strong></p> <p>One of the nice things about having these tests is that once you have them you can refactor freely, and be confident you haven't broken things. For example, you could look in to <code>Callable</code> instead of <code>Runnable</code>, which would let you deal with <code>Future</code> references, remove the output parameter from <code>FolderScan</code>, and remove the <code>CountDownLatch</code> entirely.</p> <p>Happy testing!</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload