58

I am building up an integration test suite and there is one bit of logic that I need to have a clean database for. How can I run the db:test:purge task inside of one of my tests?

I am using: ruby 1.9.2, rails 3.0.9, rspec 2.6

David
  • 3,510
  • 3
  • 21
  • 39
xentek
  • 2,555
  • 2
  • 20
  • 12

6 Answers6

62

You can invoke Rake tasks as following:

require 'rake'
Rake::Task[name].invoke

In this case this would result in the following code:

require 'rake'
Rake::Task['db:test:purge'].invoke
  • That did it. Thanks. I also had the name of the task wrong, which was throwing me off at first. In Rails 3, rake test:prepare seemed to do the trick – xentek Aug 03 '11 at 05:06
  • 1
    @jim good point. you can use Rake::Task[name].execute in those instances, but you will need to make sure that you satisfy any of it's dependencies (e.g. `:environment`) since those aren't run when calling the task with this method. – xentek Oct 09 '12 at 18:57
  • This was helpful. How does one pass parameters into the task give the examples above? – n8gard Dec 26 '12 at 20:29
  • 17
    I think loading the tasks would be necessary sometimes by calling `MyRailsApp::Application.load_tasks` – Erdem Gezer Mar 11 '13 at 23:48
  • 3
    @egezer Using `MyRailsApp::Application.load_tasks` led me to test pollution issues where my rake tasks would be invoked multiple times if `load_tasks` had already been called earlier in the test suite. Using `Rake.application.rake_require` along with `Rake::Task.define_task(:environment)` avoided this issue. – yuval Feb 08 '19 at 07:10
  • @egezer Very helpful. – s1mpl3 Apr 08 '19 at 20:31
  • 1
    Note that invoke will **only run the task once** (per `load_tasks`). Use `execute` to run more than once. – B Seven Aug 19 '22 at 01:20
38

Approved answer didn't work for me, when I needed to execute my own rake task

Here's my solution

Put in the top of the spec file

require 'rake'

Place these lines where you need to execute your custom rake task, e.g. rake update_data from the file example.rake

load File.expand_path("../../../lib/tasks/example.rake", __FILE__)
# make sure you set correct relative path 
Rake::Task.define_task(:environment)
Rake::Task["update_data"].invoke

My environment:

rails (4.0.0)
ruby (2.0.0p195)
rspec-core (2.14.7) 
rspec-expectations (2.14.3) 
rspec-mocks (2.14.4) 
rspec (2.14.1) 
rspec-rails (2.14.0) 
Sergiy Seletskyy
  • 16,236
  • 7
  • 69
  • 80
  • 2
    Hii, instead i have used _Rails.application.load_tasks_, below require 'rake'. Is this a good solution? – coderVishal Mar 08 '16 at 05:25
  • `Rake::Task.define_task(:environment)` for the win in avoiding `RuntimeError: Don't know how to build task 'environment' (see --tasks)` – s2t2 Jan 04 '17 at 21:49
  • 5
    I'm using: `Rake.application.rake_require "tasks/task-name"` to load the specific task being tested, instead of loading all of them with `Rails.application. load_tasks` (Rails 5, Rspec 3.5) – Steve Jul 06 '17 at 03:38
18

If we require to use multiple rake tasks we can add

require "rake"
Rails.application.load_tasks

Then simply call any task.

Rake::Task['sync:process_companies'].invoke

Though I cant confirm if its slower because it loads all the tasks

coderVishal
  • 8,369
  • 3
  • 35
  • 56
  • 4
    Using `Rails.application.load_tasks` led me to test pollution issues where my rake tasks would be invoked multiple times if `load_tasks` had already been called earlier in the same suite. Using the above solutions avoided this issue. – yuval Feb 08 '19 at 07:07
4

for me (rails-6)

Rails.application.load_tasks
Rake::Task['app:sync'].invoke

=> require not necnessary in my case

chmich
  • 834
  • 9
  • 20
3

Many of the above answers worked for me for running a single spec. However, I had to take an extra step when running multiple specs for a single rake task.

After each spec, I had to run Rake::Task.clear, as (for some reason) the task would not be run again if it was registered as being already_invoked (i.e. if Rake::Task['my_task'].already_invoked returned true.

I added the following line to my rake task spec:

after { Rake::Task.clear }

and everything worked as expected when running multiple tests for the same rake task.

ethaning
  • 386
  • 4
  • 12
2

We need to require the task also

require 'rake'
Rake.application.rake_require 'tasks/new_adapter'

After this, just call the task

Rake::Task['new:adapter'].invoke