Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Testing Rake Tasks

Testing Rake Tasks

A talk on how and why to test Rake tasks given at Test Ruby PDX in March 2016. See more details at: http://bit.ly/testing-rake-tasks

Brett Chalupa

March 14, 2016
Tweet

More Decks by Brett Chalupa

Other Decks in Programming

Transcript

  1. Hi, my name is Brett. I develop software for a

    non-profit called charity: water. 2
  2. About Brett • Programming for 10 years • Using Ruby

    for the past 5 years • TDD-ing for the past 3 years • Primarily using RSpec, but MiniTest 3
  3. Talk Overview • Rake explained • Why test Rake tasks

    • How to test Rake tasks • Rails-specific examples • Live coding TDD flow 4
  4. –Martin Fowler “Rake is a build language, similar in purpose

    to make and ant.” 6 http://martinfowler.com/articles/rake.html
  5. Some Use Cases • Compiling an application (rake compile )

    • Deploying a web app (rake deploy ) • Running an entire test suite (rake test:all ) • Data migrations (rake data_migrations:split_full_names ) • Running recurring tasks (Heroku Scheduler) 9
  6. Rails Uses Rake • Managing the database (rake db:create, rake

    db:migrate ) • Outputting code stats (rake stats ) • Viewing routes (rake routes ) • Checking app details (rake about ) • So much more (run rake -T to see all tasks for a project) 10
  7. A Simple Rake Task 11 desc 'Outputs a greeting to

    stdout' task :hello do puts 'Hello!' end $ rake -T rake hello # Outputs a greeting to stdout $ rake hello Hello! Output Rakefile
  8. 18 I started testing Rake tasks, and it has led

    to more confidence in creating and changing them.
  9. 22 Here is what the test for the hello task

    from earlier could look like.
  10. Hello Task (Again) 23 desc 'Outputs a greeting to stdout'

    task :hello do puts 'Hello!' end $ rake -T rake hello # Outputs a greeting to stdout $ rake hello Hello! Output Rakefile
  11. 24 require ‘rake' load ‘Rakefile’ describe ‘Rake tasks' do describe

    'hello' do it 'outputs Hello! to stdout' do expect do Rake::Task['hello'].invoke end.to output("Hello!\n").to_stdout end end end
  12. Two Kinds of Tests • Feature level - what is

    the expected outcome of the task being run? • Unit level - what code is being called from the task? 25
  13. Feature Test Examples • Data changes • Output to stdout

    • Operating system changes (file, processes, etc.) 26
  14. 35 require ‘rake' require_relative ‘greeter' load ‘Rakefile’ describe 'Rakefile units'

    do describe 'hello' do it 'uses a Greeter to greet' do expect(Greeter).to receive_message_chain( :new, :greet ) Rake::Task['hello'].invoke end end end
  15. 36 describe 'hello' do it 'uses a Greeter to greet'

    do expect(Greeter).to receive_message_chain( :new, :greet ) Rake::Task['hello'].invoke end end
  16. 37 The unit test covers the implementation of the Rake

    task. The feature test covers the expected outcome of the Rake task.
  17. 38 This example is a bit trivial, but it lays

    the groundwork for how to test more complex Rake tasks.
  18. 40 Use the #load method to make different Rake tasks

    available. # at the top of the spec require ‘rake’ load ‘some_other_file.rake’
  19. 41 Use Rake::Task[‘task_name’].reenable to allow the Rake task to be

    invoked again. Rake::Task['hello'].invoke Rake::Task['hello'].reenable Rake::Task['hello'].invoke
  20. 43 Here is what it would look like to unit

    test an async ActiveJob job being queued.
  21. 44 require 'rails_helper' describe 'donors sync' do describe 'donors:sync_modified_between' do

    subject { Rake::Task['donors:sync_modified_between'] } before { subject.reenable } it 'triggers the sync job for the donors' do expect(DonorsSyncJob).to receive( :perform_later ).with('2015-09-17', '2015-09-18') subject.invoke('2015-09-17', '2015-09-18') end end end
  22. 45 it 'triggers the sync job for the donors' do

    expect(DonorsSyncJob).to receive( :perform_later ).with('2015-09-17', '2015-09-18') subject.invoke('2015-09-17', '2015-09-18') end
  23. 46 namespace :donors do desc 'Sync donors' task :sync_modified_between, [:start_at,

    :end_at] => [:environment] do |_t, args| DonorsSyncJob.perform_later( args[:start_at], args[:end_at] ) end end
  24. 49 There are not much differences with Rails vs. plain

    old Ruby when testing Rake tasks. There is no need to explicitly load the Rake files, which is nice.