3

I've attempted test first in Ruby on Rails using Test Unit and RSpec.

I'm wondering how to do test first in situations that are more closely tied to the OS/filesystem.

Problem: Building a USB stick of MP4 files.

Inputs:

  1. List of mp4 file name, destination directory pairs.
  2. List of source directories
  3. List of destination directories

Output:

  1. USB stick with a directory structure of mp4 files.

Here is some code that does what I want. Written using puts debugging:

#!/bin/env ruby
# encoding: utf-8

require 'fileutils'

files = [
    [ 'Keynote_ Architecture the Lost Years by Robert Martin.mp4', 'dev' ],
    [ 'The Oak Beams of New College, Oxford.mp4', 'arch' ],
    [ '1. How Buildings Learn - Stewart Brand - 1 of 6 - “Flow”.mp4', 'arch/how_buildings_learn' ],
    [ 'Hexagonal Rails by Matt Wynne.mp4', 'dev' ]
]

dirs = [
    'arch',
    'arch/how_buildings_learn',
    'dev'
]

sources = [
    '/home/gnoll110/dwhelper',
    '/home/gnoll110/Downloads',
    '/home/gnoll110/GNUstep/Downloads',
    '/home/gnoll110'
]

dest = '/media/Lexar'

dirs.each do | dir |
    if !File.exist?( dest+'/'+dir )
        system( 'mkdir '+dest+'/'+dir )
    end
end

files.each do | file |
    actual_source = false
    sources.each do | source |
        res = File.exist? source+'/'+file[0]
        actual_source = source if res
    end

    if actual_source
        FileUtils.cp(actual_source+'/'+file[0], dest+'/'+file[1] )
    end
end.

What the best approach?

  • Junk the existing code. After all, I'm trying to do test first.

  • Write a test(s) that invokes a Command Pattern object. Dependence inject the data arrays in the constructor.

  • Then inject the 'file exist' and 'fileutils copy' as stub/mocks, to get separation from the OS/filesystem.

  • Build, assert and refactor the run method within an inch of its life.

All suggestions and ideas welcome.

  • 1
    You almost never want to junk existing code. If you are modifying an existing codebase without unit tests, the first thing you need to do is get the functionality you want to modify into a test harness. That being said, it sounds like you already know what to do. – mortalapeman Jul 14 '13 at 16:10
  • 1
    Thanks for taking the time to reply. Had watched this youtube.com/watch?v=yTkzNHF6rMs Was pondering my situation, in light of Gary's comments in the first 8 minutes. – gnoll110 Sep 2 '13 at 7:42
2

You have asked two questions:

  1. How to test drive code which touches the filesystem
  2. Should you junk your existing untested code.

Re: How to test drive code which touches the file system:

The best way to do this is to put the filesystem calls behind an interface which will be mocked out for unit testing of the rest of the system. Only your applications 'main' function will instantiate the real versions of these methods.

The code that contains the real filesystem calls should be very thin so that you can either not bother testing it (since you can verify it by inspection or by quick smoke-test of the entire system) or test it with a few integration tests which use the real filesystem.

Re: Junking existing code:

This is a judgement call on your part.

You could consider your existing code as a prototype which helped you learn the sort of thing you need to do. If that is the case then you should delete it and write it again now that you have better knowledge.

Or you could consider it legacy code and get it under test. To do that write some full system tests to keep you from breaking it as you refactor it. See "Working Effectively with Legacy Code" by Michael Feathers for techniques to do this safely.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.