Missing the each_line method in FakeFS version 0.2.1? Add it!

Posted by: Scott Leberknight on 05/06/2010

Recently we have been using the excellent FakeFS (fake filesystem) gem in some specs to test code that reads and writes files on the filesystem. We are using the latest release version of this gem which is 0.2.1 as I am writing this. Some of the code under test uses the IO each_line method to iterate lines in relatively largish files. But we found out quickly that is a problem, since in version 0.2.1 the FakeFS::File class does not extend StringIO and so you don't get all its methods such as each_line. (The version on master in GitHub as I write this does extend StringIO, but it is not yet released as a formal version.) As an example suppose we have the following code that prints out the size of each line in a file as stars (asterisks):

def lines_to_stars(file_path)
  File.open(file_path, 'r').each_line { |line| puts '*' * line.size }
end

Let's say we use FakeFS to create a fake file like this:

require 'fakefs/safe'
require 'stringio'

FakeFS.activate!

File.open('/tmp/foo.txt', 'w') do |f|
  f.write "The quick brown fox jumped over the lazy dog\n"
  f.write "The quick red fox jumped over the sleepy cat\n"
  f.write "Jack be nimble, Jack be quick, Jack jumped over the candle stick\n"
  f.write "Twinkle, twinkle little star, how I wonder what you are\n"
  f.write "The End."
end

So far, so good. But now if we call lines_to_stars we get an error:

NoMethodError: undefined method `each_line' for #<FakeFS::File:0x000001012c22b8>

Oops. No each_line. If you don't want to use an unreleased version of the gem, you can add each_line onto FakeFS::File using the following code:

module FakeFS
  class File
    def each_line
      File.readlines(self.path).each { |line| yield line }
    end
  end
end

Basically all it does is define each_line so that it reads all the lines from a (fake) file on the (fake) filesystem and then yields them up one by one, so you can have code under test that iterates a file and work as expected. So now calling lines_to_stars gives a nice pretty bar chart containing the line sizes represented by stars:

********************************************
********************************************
***************************************************************
*******************************************************
********

Since we're using RSpec, to make this work nicely we added the above code that defines each_line into a file named fakefs.rb in the spec/support directory, since spec_helper requires supporting files in the spec/support directory and its subdirectories. So now all our specs automatically get the each_line behavior when using FakeFS.


About Scott Leberknight

Scott Leberknight

Scott is Chief Architect at Near Infinity Corporation, an enterprise software development and consulting services company based in Reston, Virginia. He has been developing enterprise and web applications for 14 years professionally, and has developed applications using Java, Ruby, Groovy, and even an iPhone application with Objective-C. His main areas of interest include alternative persistence technologies, object-oriented design, system architecture, testing, and frameworks like Spring, Hibernate, and Ruby on Rails. In addition, Scott enjoys learning new languages to make himself a better and more well-rounded developer a la The Pragmatic Programmers' advice to "learn one language per year."

Scott holds a B.S. in Engineering Science and Mechanics from Virginia Tech, and an M. Eng. in Systems Engineering from the University of Maryland. Scott speaks at the No Fluff Just Stuff Symposiums and various other conferences. In his (sparse) spare time, Scott enjoys spending time with his wife, three children, and cat. He also tries to find time to play soccer, go snowboarding, and mountain bike whenever he can.

More About Scott »

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 7
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 3
  • Automation Tools: Git, Hudson, Sonar
  • HTML5, Ajax, jQuery, Usability
  • Mobile Applications - iPhone and Android
  • More...
Learn More »

NFJS, the Magazine

December Issue Now Available
  • BDD and REST

    by Brian Sletten
  • Mocks and Stubs in Groovy Tests

    by Kenneth Kousen
  • Algorithms for Better Text Search Results

    by John Griffin
  • Knowns and Unknowns of Scrum and Agile

    by Brian Tarbox
Learn More »