I am using a memory sqlite database to run rspec tests. This functions very well. Only when running selenium driven tests (describe "does something", :js => true do) the starting webbrowser gets the error SQLite3::SQLException: no such table: users: SELECT "users".* FROM "users" WHERE ...
WEBrick/1.3.1 (Ruby/2.0.0/2013-02-24) at 127.0.0.1:57827
I am looking for a solution to run selenium driven test while using a in memory database.
Details:
I use ruby on rails 4.0 and the following gems (excerpt)
gem 'sqlite3', '1.3.7'
gem 'rspec-rails', '2.13.0'
gem 'capybara', '~> 2.1.0.beta1'
gem 'selenium-webdriver', '2.35.1'
database.yml
test:
adapter: sqlite3
database: ":memory:"
pool: 5
timeout: 5000
spec_helper.rb
require 'rubygems'
require 'spork'
Spork.prefork do
# snip
load "#{Rails.root.to_s}/db/schema.rb" # set up memory db
RSpec.configure do |config|
config.use_transactional_fixtures = false #using database cleaner
#snip
config.before :suite do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.before type: :request do
DatabaseCleaner.strategy = :truncation
end
# Reset so other non-request specs don't have to deal with slow truncation.
config.after type: :request do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, :js => true) do
DatabaseCleaner.strategy = :truncation
end
config.before do
DatabaseCleaner.start
ActionMailer::Base.deliveries.clear
end
config.after do
DatabaseCleaner.clean
end
end
end
The problem seems to have something to do that the capybara web server uses its own database connections (as opposed to the connection used by the tests itself), but the in memory database is only available for the one connection which created it.
This question already provided some insights:
(DatabaseError: no such table: django_session) ERROR during Django 1.3 selenium testing
So, how can I make selenium tests memory db compatible?
Thank you very much in advance.
The capybara Readme itself suggests to monkeypatch the ActiveRecord::Basein the spec_helper.rb
class ActiveRecord::Base
mattr_accessor :shared_connection
##shared_connection = nil
def self.connection
##shared_connection || retrieve_connection
end
end
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
If you use spork, the last line belongs to the Spork.each_run section.
In this case, you also have to load the schema.rb in Spork.each_run.
This actually works but is advised to use with caution.
Further information see Why not use shared ActiveRecord connections for Rspec + Selenium?
Related
We have a project that is using the AR-Octopus gem using sharded databases. The problem we are running into is that the gem 'database_cleaner' is not cleaning records when using this setup, as we are consistently having leftover records in our test database that cause issues with our test suite.
I found this GitHub gist - https://gist.github.com/nowlinuxing/22ea0ab673a5622eb48d
Here is my database_cleaner config file
# spec/support/database_cleaner.rb
require 'database_cleaner'
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
["master", *Octopus.config[Rails.env].keys].each do |shard|
DatabaseCleaner[:active_record, model: ActiveRecord::Base.using(shard)]
end
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
end
Has anyone ever encountered this issue? If so, what did you do to resolve the issue? Just looking for some helpful insight.
When I run my rspec tests, many fail due to stale data in my mongodb database. AFAIK it is far better to test with a clean database.
How can I clean and/or re-seed the database before each test?
You can use database_cleaner gem to accomplish this task.
From their documentation:
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do |example|
DatabaseCleaner.strategy= :truncation
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
As you are using Mongoid ORM, you may also need to specify it explicitly:
# How to setup your ORM explicitly
DatabaseCleaner[:mongoid].strategy = :truncation
Update:
I see an open issue for MongoID 5
To make it work, you can monkey patch the Mongo Ruby driver class as mentioned in the issue.
module Mongo
class Collection
class View
def remove_all
remove(0)
end
end
end
end
Athough it's not a great solution!
The fix to the problem is there in the master branch of database_cleaner(1.4.1) gem. Install the gem from master to fix the problem (until there is the version bump). Expected to get fixed in next version.
gem 'database_cleaner', :git => 'https://github.com/DatabaseCleaner/database_cleaner.git'
I set up cucumber/rails for my rails project and populated the test database with data, to run tests against it. When I run "rake cucumber" the database gets truncated. I tried to set DatabaseCleaner.strategy to :transaction and nil, but it still gets truncated. I'd prefer not to use database_cleaner at all for now, but its presence is required by cucumber. Here is my "./features/support/env.rb" file:
require 'cucumber/rails'
require 'capybara/cucumber'
Capybara.default_driver = :selenium
ActionController::Base.allow_rescue = false
begin
DatabaseCleaner.strategy = nil
rescue NameError
raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
end
Cucumber::Rails::Database.javascript_strategy = :truncation
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, :browser => :chrome)
end
I don't believe there is a strategy that does nothing, but cucumber doesn't need it to run. Possibly you may have to remove it from your env.rb file and any db cleaning in your hooks file.
EDIT:
I was wrong, there is a null strategy. Try:
DatabaseCleaner.strategy = DatabaseCleaner::NullStrategy
or
DatabaseCleaner::Base.new
You need to set both the DatabaseCleaner.strategy and the Cucumber::Rails::Database.javascript_strategy.
Cucumber-rails does not come with a null strategy so you have to make one. This works for me, in env.rb:
DatabaseCleaner.strategy = DatabaseCleaner::NullStrategy
class NullStrategy < Cucumber::Rails::Database::Strategy
def before_js
super DatabaseCleaner::NullStrategy
end
end
Cucumber::Rails::Database.javascript_strategy = NullStrategy
I believe this is the simplest and documented approach.
Cucumber::Rails::Database.autorun_database_cleaner = false
I included database_cleaner gem in my rails app. Followed the example given on the git repo and included the following code in spec_helper :
Approach 1
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
When i run the rspec i get error as NoMethodError:undefined method 'cleaning' for DatabaseCleaner:Module.
So i did some research and found that i could replace the config.around block above with something like this :
Approach 2
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
OR
Approach 3
config.around(:each) do |example|
DatabaseCleaner.start
example.run
DatabaseCleaner.clean
end
Both Approach 2 and 3 work well.
I also looked in the git repo of database_cleaner and found that cleaning method actually exists and with the following code :
def cleaning(&block)
start
yield
clean
end
which is exactly same as what i did in example 3. If it does exists then why is it not accessible? Am i missing something here. Any more setup?
Or is Approach 2 or 3 preferable?
Finally found the answer,
database_cleaner gem added the cleaning method just last week and also updated the documentation for the same. BUT this change is not available in latest gem version 1.2.0 which I sourced from rubygems.org. Approach 1 works perfectly when i source the gem from github as below:
gem 'database_cleaner', git: 'git#github.com:DatabaseCleaner/database_cleaner.git'
You can use the approach in the documentation if you pull the gem from Github
gem 'database_cleaner', git: 'git#github.com:bmabey/database_cleaner.git'
If you have this same issue using mongoid you can add this to Gemfile, change version to suit you, and run bundle install.
gem 'database_cleaner', '~> 1.4.1'
Then create a support folder in
spec/support/database_cleaner.rb
Require database_cleaner.rb in your spec_helper file, I use gem 'require_all' like so:
# spec/spec_helper.rb
require 'require_all'
require_rel 'support'
Add the following cleaners to database_cleaner.rb
RSpec.configure do |config|
# Cleanup the DB in between test runs
config.before(:suite) do
DatabaseCleaner[:mongoid].strategy = :truncation
DatabaseCleaner[:mongoid].clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
Your tests should now tear down properly.
I'd like to use zeus (0.13.3) to preload my rails environment for an rails (3.2.11) app on ruby 2.0.0 and use database_cleaner (0.9.1) to clean the databases.
This is working fine if as long as I use only one mysql database.
In the app we have to use two different mysql databases.
Edit: What needs to be mentioned is, that I use the shared connection hack, which is described here.
Running my specs without using zeus is working like expected. But if I use it, every test is failing in the moment when a record is created with the error:
undefined method `query_options' for nil:NilClass
How can this be solved?
The setup is like that:
config/database.yml
test:
database: app_test
...
test_second_db:
database: other_test
...
In an abstract base class for all the models using the second connection we do
models/second_db/base.rb
module SecondDB
class Base < ActiveRecord::Base
establish_connection "#{Rails.env}_second_db"
self.abstract_class = true
end
end
In my spec_helper.rb file I setup the database_cleaner:
spec/spec_helper.rb
require 'database_cleaner'
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner[:active_record,{:connection => :test_second_db}].strategy = :transaction
end
config.before(:each) do
DatabaseCleaner.start
DatabaseCleaner[:active_record,{:connection => :test_second_db}].start
end
config.after(:each) do
DatabaseCleaner.clean
DatabaseCleaner[:active_record,{:connection => :test_second_db}].clean
end
end
edit:
spec/support/shared_connection.rb
class ActiveRecord::Base
mattr_accessor :shared_connection
##shared_connection = nil
def self.connection
##shared_connection || retrieve_connection
end
end
spec/support/shared_connection.rb
Not sure if this will fix your issue as I am not able to test it but you may want to try adding this to your spec_helper file.
ActiveRecord::ConnectionAdapters::ConnectionPool.class_eval do
def current_connection_id
# Thread.current.object_id
Thread.main.object_id
end
end
This is used for Selenium when running the browser in tests. Tests use transactions and the browser is a seperate process so it cant see the DB. This may not be the problem/solution but its worth a try.