Back to Repositories

Testing Rake Task Thumbnail Processing in Paperclip

This test suite validates the Paperclip rake tasks functionality, particularly focusing on thumbnail refresh operations and error handling. It ensures robust error management during thumbnail processing and proper logging of exceptions.

Test Coverage Overview

The test suite comprehensively covers the ‘paperclip:refresh:thumbnails’ rake task functionality.

Key areas tested include:
  • Exception handling during thumbnail reprocessing
  • Error management for invalid instances
  • Continuation of processing after errors
  • Error logging and reporting mechanisms

Implementation Analysis

The testing approach utilizes RSpec’s context-based structure with extensive use of mocking and stubbing to isolate test scenarios. The implementation employs mock objects for error handling and uses multiple contexts to separate different error conditions.

Technical patterns include:
  • Stub chaining for complex object interactions
  • Mock expectations for verifying error logging
  • Before blocks for test setup and state management

Technical Details

Testing tools and configuration:
  • RSpec as the testing framework
  • Mock objects for error simulation
  • Rake task execution in test environment
  • Custom model rebuilding for test isolation
  • STDERR capture for logging verification

Best Practices Demonstrated

The test suite exemplifies several testing best practices in Ruby and RSpec.

Notable practices include:
  • Proper test isolation through mocking
  • Comprehensive error scenario coverage
  • Clear test organization using nested contexts
  • Explicit expectation setting
  • Thorough validation of error messages and logging

thoughtbot/paperclip

spec/paperclip/rake_spec.rb

            
require 'spec_helper'
require 'rake'
load './lib/tasks/paperclip.rake'

describe Rake do
  context "calling `rake paperclip:refresh:thumbnails`" do
    before do
      rebuild_model
      Paperclip::Task.stubs(:obtain_class).returns('Dummy')
      @bogus_instance = Dummy.new
      @bogus_instance.id = 'some_id'
      @bogus_instance.avatar.stubs(:reprocess!)
      @valid_instance = Dummy.new
      @valid_instance.avatar.stubs(:reprocess!)
      Paperclip::Task.stubs(:log_error)
      Paperclip.stubs(:each_instance_with_attachment).multiple_yields @bogus_instance, @valid_instance
    end
    context "when there is an exception in reprocess!" do
      before do
        @bogus_instance.avatar.stubs(:reprocess!).raises
      end

      it "catches the exception" do
        assert_nothing_raised do
          ::Rake::Task['paperclip:refresh:thumbnails'].execute
        end
      end

      it "continues to the next instance" do
        @valid_instance.avatar.expects(:reprocess!)
        ::Rake::Task['paperclip:refresh:thumbnails'].execute
      end

      it "prints the exception" do
        exception_msg = 'Some Exception'
        @bogus_instance.avatar.stubs(:reprocess!).raises(exception_msg)
        Paperclip::Task.expects(:log_error).with do |str|
          str.match exception_msg
        end
        ::Rake::Task['paperclip:refresh:thumbnails'].execute
      end

      it "prints the class name" do
        Paperclip::Task.expects(:log_error).with do |str|
          str.match 'Dummy'
        end
        ::Rake::Task['paperclip:refresh:thumbnails'].execute
      end

      it "prints the instance ID" do
        Paperclip::Task.expects(:log_error).with do |str|
          str.match "ID #{@bogus_instance.id}"
        end
        ::Rake::Task['paperclip:refresh:thumbnails'].execute
      end
    end

    context "when there is an error in reprocess!" do
      before do
        @errors = mock('errors')
        @errors.stubs(:full_messages).returns([''])
        @errors.stubs(:blank?).returns(false)
        @bogus_instance.stubs(:errors).returns(@errors)
      end

      it "continues to the next instance" do
        @valid_instance.avatar.expects(:reprocess!)
        ::Rake::Task['paperclip:refresh:thumbnails'].execute
      end

      it "prints the error" do
        error_msg = 'Some Error'
        @errors.stubs(:full_messages).returns([error_msg])
        Paperclip::Task.expects(:log_error).with do |str|
          str.match error_msg
        end
        ::Rake::Task['paperclip:refresh:thumbnails'].execute
      end

      it "prints the class name" do
        Paperclip::Task.expects(:log_error).with do |str|
          str.match 'Dummy'
        end
        ::Rake::Task['paperclip:refresh:thumbnails'].execute
      end

      it "prints the instance ID" do
        Paperclip::Task.expects(:log_error).with do |str|
          str.match "ID #{@bogus_instance.id}"
        end
        ::Rake::Task['paperclip:refresh:thumbnails'].execute
      end
    end
  end

  context "Paperclip::Task.log_error method" do
    it "prints its argument to STDERR" do
      msg = 'Some Message'
      $stderr.expects(:puts).with(msg)
      Paperclip::Task.log_error(msg)
    end
  end
end