Skip to content

Instantly share code, notes, and snippets.

@mycargus
Last active January 20, 2017 23:14
Show Gist options
  • Save mycargus/a46c483e55dc1998b77a2b8bd4f33661 to your computer and use it in GitHub Desktop.
Save mycargus/a46c483e55dc1998b77a2b8bd4f33661 to your computer and use it in GitHub Desktop.
Testing Rake Tasks with RSpec and FakeFS
# Rakefile

require_relative 'lib/task_helpers'

namespace :reset do
  desc 'Clean logs'
  task :logs do
    FileUtils.rm_rf 'log/'
  end

  desc 'Create a docker-compose override file'
  task :override do
    TaskHelpers.copy_example_file 'docker-compose.override.yml.example'
  end

  desc 'Create your own .env file from .env.example'
  task :env do
    TaskHelpers.copy_example_file '.env.example'
  end

  desc 'Create a local feature toggles override config'
  task :toggles do
    TaskHelpers.copy_example_file 'features/feature_toggles.json.example'
  end
end
# lib/task_helpers.rb

require 'fileutils'

module TaskHelpers
  class << self
    def copy_example_file(example_file)
      file = example_file.chomp '.example'
      FileUtils.cp file, "#{file}.orig" if File.exist? file
      FileUtils.cp example_file, file
    end
  end
end
# spec/spec_helper.rb

require 'fakefs/spec_helpers'
require 'fileutils'

Dir[__dir__ + '../lib/**/*.rb'].each { |f| require f }
Dir[__dir__ + '/support/**/*.rb'].each { |f| require f }

RSpec.configure do |config|
  config.include FakeFS::SpecHelpers, fakefs: true
end
# spec/support/shared_contexts/rake.rb

require 'rake'

shared_context 'rake', fakefs: true do
  # Sets task_name to the text passed to the given RSpec describe block. For
  # example: "RSpec.describe 'test:sauce' do" makes task_name == 'test:sauce'
  let(:task_name)     { self.class.top_level_description }
  let(:rake)          { Rake::Application.new }
  subject             { rake[task_name] }

  let!(:load_env) do
    Rake.application = rake
    rake.init
    rake.load_rakefile
  end
end
# spec/support/shared_examples/an_example_file_config.rb

shared_examples 'an example file config' do
  let(:config_file)                 { config_file_example.chomp '.example' }
  let(:config_file_orig)            { "#{config_file}.orig" }
  let!(:create_config_file_example) { FileUtils.touch config_file_example }

  context 'when the config file already exists' do
    let!(:setup) { FileUtils.touch config_file }

    it 'creates a .orig copy' do
      task.invoke
      expect(File).to exist config_file_orig
    end
  end

  context 'when a config file doesn\'t exist' do
    it 'doesn\'t create a .orig copy' do
      task.invoke
      expect(File).not_to exist config_file_orig
    end

    it 'creates the config file' do
      task.invoke
      expect(File).to exist config_file
    end
  end
end
# spec/rake_reset_spec.rb

require_relative 'spec_helper'

describe 'reset:logs', fakefs: true do
  include_context 'rake'

  let!(:create_dir) { FileUtils.mkdir_p 'log/' }

  it 'removes the log/ directory' do
    subject.invoke
    expect(File).not_to exist 'log/'
  end
end

describe 'reset:override', fakefs: true do
  include_context 'rake'

  let(:config_file_example) { 'docker-compose.override.yml.example' }
  let(:task) { subject }
  it_behaves_like 'an example file config'
end

describe 'reset:env', fakefs: true do
  include_context 'rake'

  let(:config_file_example) { '.env.example' }
  let(:task) { subject }
  it_behaves_like 'an example file config'
end

describe 'reset:toggles', fakefs: true do
  include_context 'rake'

  let(:path)        { 'features/' }
  let!(:create_dir) { FileUtils.mkdir_p path }

  let(:config_file_example) { "#{path}/feature_toggles.json.example" }
  let(:task) { subject }
  it_behaves_like 'an example file config'
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment