/testftpd

Simple FTP server written in pure Ruby, allowing integration testing of FTP client code without mocks and stubs

Primary LanguageRubyMIT LicenseMIT

TestFtpd

Gem Version Build Status

Simple FTP server written in pure Ruby.

The primary use case is for integration testing FTP client code in a Rails 3.1 codebase using RSpec 2.

Enough FTP commands are implemented to be useful, including:

portpasvuserpassquitsysttype
listretrstordelesizemdtmrnfr/rnto
pwdcdupcwdmkdrmdnlst

Usage

Update your Gemfile

group :test do
  gem 'testftpd', :require => false
end

Write some specs...

require 'spec_helper'
require 'testftpd'

describe 'Test all the things!' do
  let(:ftp_port) { 21212 }
  let(:ftp_root) { Rails.root.to_s }

  before do
    @ftp_server = TestFtpd::Server.new(port: ftp_port, root_dir: ftp_root)
    @ftp_server.start
  end

  after do
    @ftp_server.shutdown
  end

  it 'lists remote files' do
    ftp = Net::FTP.new
    ftp.connect('127.0.0.1', ftp_port)
    ftp.login('username', 'password')
    ftp.list.any? { |file| file ~= /Gemfile/ }.should be_true
  end
end

You can change the list command format by monkey-patching or stubbing. Heres a stubbing technique I've used:

require 'spec_helper'
require 'testftpd'

describe 'Test all the things!' do
  let(:ftp_port) { 21212 }
  let(:ftp_root) { Rails.root.to_s }

  before do
    @ftp_server = TestFtpd::Server.new(port: ftp_port, root_dir: ftp_root)
    @ftp_server.start
  end

  after do
    @ftp_server.shutdown
  end

  before :each do
    TestFtpd::FileSystemProvider.stub(:format_list_entry) do |entry|
      raw =  entry.ftp_date.strftime('%m-%d-%g  %I:%M%p') + ' '
      if entry.directory?
        raw += '    <DIR>            '
      else
        raw += entry.ftp_size.to_s.rjust(20, ' ') + ' '
      end
      raw += entry.ftp_name
      raw += "\r\n"
      raw
    end
  end

  it 'lists remote files' do
    ftp = Net::FTP.new
    ftp.connect('127.0.0.1', ftp_port)
    ftp.login('username', 'password')
    ftp.list.any? { |file| file ~= /Gemfile/ }.should be_true
  end

This will most likely make it into the TestFtpd code base as a configurable option, stay tuned.

Todo

  • more tests
  • add simple authentication provider
  • implement more FTP commands

Acknowledgements

This code builds upon Rubtsov Vitaly' excellent project dyn-ftp-serv created in late 2007.

Also Francis Hwang who originally adapted dyn-ftp-serv, and gave me a head start for this project.

Contributers

  • Christian Schulze

License

Released under the MIT license. Please see the LICENSE file for more information.