I'm trying to test a rake task and it uses an active record in it.
require 'spec_helper'
require 'rake'
load File.join(Rails.root, 'lib', 'tasks', 'survey.rake')
describe "survey rake tasks" do
describe "survey:send_report" do
it "should send a report" do
Rake::Task['survey:send_report'].invoke
end
end
end
When I run this spec rspec spec/lib/survey_spec.rb, I get this error "
RuntimeError:
Don't know how to build task 'environment'
How do I load the :enviroment task inside by example spec?
I think you should first load the tasks:
require 'rake'
MyRailsApp::Application.load_tasks
and then invoke your task:
Rake::Task['survey:send_report'].invoke
I suspect the problem is that your survey:send_report task depends on :environment but you haven't loaded the file that defines the :environment task. That'll be in rails somewhere, and your main Rakefile loads it.
So, I think if you change
load File.join(Rails.root, 'lib', 'tasks', 'survey.rake')
to
load File.join(Rails.root, 'Rakefile')
it'll work.
Sounds like your take task may need the Rails environment to be loaded. You can stub this out by adding this line to your before(:all) hook:
Rake::Task.define_task(:environment)
Is your task adding the :enviroment to do it before? In your .rake file you should have something like this:
namespace :survey do
# ...
task :send_report => :enviroment do
# ... stuff
end
This is because you need to load the full enviroment to do that task. You can check this railcast to get more information http://railscasts.com/episodes/66-custom-rake-tasks
Related
I'm trying to make a rake-task in a such way:
require 'open-uri'
namespace :news_parser do
desc 'Parsing news from 6 news sites'
task :parse_news do
load 'lib/news_parser.rb'
ProcherkParser.new.save_novelties
VikkaParser.new.save_novelties
InfomistParser.new.save_novelties
ZmiParser.new.save_novelties
VycherpnoParser.new.save_novelties
ProvceParser.new.save_novelties
end
end
In my lib/news_parser.rb I have classes and instance methods, which perfectly work in a rails console, by doing the following:
load 'lib/news_parser.rb'
ProcherkParser.new.save_novelties
It saves to my db all the information I need. But how can I do it in a rake-task? Any help would be appreciate. Thanks.
Does it work when you replace
task :parse_news do
with
task :parse_news => :environment do
?
It will load your Rails environment before your task, and your code should work just like in the rails console.
Also, you could DRY your code a bit :
require 'open-uri'
namespace :news_parser do
desc 'Parsing news from 6 news sites'
task :parse_news => :environment do
load 'lib/news_parser.rb'
[ProcherkParser, VikkaParser, InfomistParser, ZmiParser, VycherpnoParser, ProvceParser].each do |parser_klass|
parser_klass.new.save_novelties
end
end
end
This is how I am using in my app
namespace :raw_logs do
desc 'Download - Decrypt - Save raw logs'
task process: :environment do
LogItem.create(org_id: 12)
end
end
My rake task is rake raw_logs:process
namespace :fixtures do
namespace :load do
task :prepare => :environment do
ENV['FIXTURES_PATH'] = "spec/fixtures"
ENV['RAILS_ENV'] ||= "test"
puts ENV.inspect
Rake::Task["db:fixtures:load"].invoke
end
end
end
I have added this to a special.rake file in ./lib/tasks in order to cause the rake db:fixtures:load command to apply to fixtures in the spec/fixtures directory, and to apply to the test environment.
It's not working. Where have I gone wrong?
You need to reconnect to the database. Something like
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations["test"])
Changing ENV['RAILS_ENV'] after environment is already loaded doesn't do anything.
Perhaps it would also work if you load the environment task after you change ENV, but not sure about that:
task :prepare do
ENV['RAILS_ENV'] ||= "test"
Rake::Task["environment"].invoke
Rake::Task["db:fixtures:load"].invoke
end
I want to test a method defined in a rake task.
rake file
#lib/tasks/simple_task.rake
namespace :xyz do
task :simple_task => :environment do
begin
if task_needs_to_run?
puts "Lets run this..."
#some code which I don't wish to test
...
end
end
end
def task_needs_to_run?
# code that needs testing
return 2 > 1
end
end
Now, I want to test this method, task_needs_to_run? in a test file
How do I do this ?
Additional note: I would ideally want test another private method in the rake task as well... But I can worry about that later.
The usual way to do this is to move all actual code into a module and leave the task implementation to be only:
require 'that_new_module'
namespace :xyz do
task :simple_task => :environment do
ThatNewModule.doit!
end
end
If you use environmental variables or command argument, just pass them in:
ThatNewModule.doit!(ENV['SOMETHING'], ARGV[1])
This way you can test and refactor the implementation without touching the rake task at all.
You can just do this:
require 'rake'
load 'simple_task.rake'
task_needs_to_run?
=> true
I tried this myself... defining a method inside a Rake namespace is the same as defining it at the top level.
loading a Rakefile doesn't run any of the tasks... it just defines them. So there is no harm in loading your Rakefile inside a test script, so you can test associated methods.
When working within a project with a rake context (something like this) already defined:
describe 'my_method(my_method_argument)' do
include_context 'rake'
it 'calls my method' do
expect(described_class.send(:my_method, my_method_argument)).to eq(expected_results)
end
end
I'm using Sinatra, and I wanted to set up some of the convenience rake tasks that Rails has, specifically rake db:seed.
My first pass was this:
namespace :db do
desc 'Load the seed data from db/seeds.rb'
task :seed do
seed_file = File.join(File.dirname(__FILE__), 'db', 'seeds.rb')
system("racksh < #{seed_file}")
end
end
racksh is a gem that mimics Rails' console. So I was just feeding the code in the seed file directly into it. It works, but it's obviously not ideal. What I'd like to do is create an environment task that allows commands to be run under the Sinanta app/environment, like so:
task :environment do
# what goes here?
end
task :seed => :environment do
seed_file = File.join(File.dirname(__FILE__), 'db', 'seeds.rb')
load(seed_file) if File.exist?(seed_file)
end
But what I can't figure out is how to set up the environment so the rake tasks can run under it. Any help would be much appreciated.
I've set up a Rakefile for Sinatra using a kind of Rails-like environment:
task :environment do
require File.expand_path(File.join(*%w[ config environment ]), File.dirname(__FILE__))
end
You then have something in config/environment.rb that contains what you need to start up your app properly. It might be something like:
require "rubygems"
require "bundler"
Bundler.setup
require 'sinatra'
Putting this set-up in a separate file avoids cluttering your Rakefile and can be used to launch your Sinatra app through config.ru if you use that:
require File.expand_path(File.join(*%w[ config environment ]), File.dirname(__FILE__))
run Sinatra::Application
I'm attempting to use the new standard way of loading seed data in Rails 2.3.4+, the db:seed rake task.
I'm loading constant data, which is required for my application to really function correctly.
What's the best way to get the db:seed task to run before the tests, so the data is pre-populated?
The db:seed rake task primarily just loads the db/seeds.rb script. Therefore just execute that file to load the data.
load "#{Rails.root}/db/seeds.rb"
# or
Rails.application.load_seed
Where to place that depends on what testing framework you are using and whether you want it to be loaded before every test or just once at the beginning. You could put it in a setup call or in a test_helper.rb file.
I'd say it should be
namespace :db do
namespace :test do
task :prepare => :environment do
Rake::Task["db:seed"].invoke
end
end
end
Because db:test:load is not executed if you have config.active_record.schema_format = :sql (db:test:clone_structure is)
Putting something like this in lib/tasks/test_seed.rake should invoke the seed task after db:test:load:
namespace :db do
namespace :test do
task :load => :environment do
Rake::Task["db:seed"].invoke
end
end
end
I believe Steve's comment above should be the correct answer. You can use Rails.application.load_seed to load seed data into your test envoironment. However, when and how often this data is loaded depends on a few things:
Using Minitest
There is no convenient way to run this file once before all tests (see this Github issue). You'll need to load the data once before each test, likely in the setup method of your test files:
# test/models/my_model_test.rb
class LevelTest < ActiveSupport::TestCase
def setup
Rails.application.load_seed
end
# tests here...
end
Using RSpec
Use RSpec's before(:all) method to load seed data for all test for this model:
describe MyModel do
before(:all) do
Rails.application.load_seed
end
describe "my model..." do
# your tests here
end
Hope this helps.
Building on Matt's answer, if taking that sort of route, I recommend calling Rails.application.load_seed in a before(:suite) block in rspec_helper.rb rather than in a before(:all) block in any file. That way the seeding code is invoked only once for the entire test suite rather than once for each group of tests.
rspec_helper.rb:
RSpec.configure do |config|
...
config.before(:suite) do
Rails.application.load_seed
end
...
end
We're invoking db:seed as a part of db:test:prepare, with:
Rake::Task["db:seed"].invoke
That way, the seed data is loaded once for the entire test run, and not once per test class.
Adding Rake::Task["db:seed"].invoke to the db:test:prepare rake task did not work for me. If I prepared the database with rake db:test:prepare, and then entered the console within the test environment, all my seeds were there. However, the seeds did not persist between my tests.
Adding load "#{Rails.root}/db/seeds.rb" to my setup method worked fine, though.
I would love to get these seeds to load automatically and persist, but I haven't found a way to do that yet!
For those using seedbank, it changes how seeds are loaded, so you probably can't/don't want to use the load ... solution provided here.
And just putting Rake::Task['db:seed'].invoke into test_helper resulted in:
Don't know how to build task 'db:seed' (RuntimeError)
But when we added load_tasks before that, it worked:
MyApp::Application.load_tasks
Rake::Task['db:seed'].invoke