Why does this configuration seem to clean both my test and my development databases? It's pretty annoying to have to reseed development every time I run rspec.
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
database.yml
development:
adapter: postgresql
database: m_development
encoding: utf8
pool: 5
username: booltox
password:
test:
adapter: postgresql
database: m_test
encoding: utf8
pool: 5
username: booltox
password:
Pretty foolish of me but this might help someone else. Don't forget to define your environment in your spec_helper.rb (thanks #dgilperez):
ENV['RAILS_ENV'] ||= 'test'
Related
In an effort to move from distribute_reads to the native Rails 6 multiple databases support I came across a weird behavior, I'm still unsure if it's a bug or a configuration problem.
// database.yml
default: &default
adapter: postgresql
encoding: unicode
pool: 10
reaping_frequency: 10
timeout: 5000
username: my_username
password: my_password
database: my_database
schema_search_path: 'public,utils'
development: &development
primary:
<<: *default
database: my_database
host: 'localhost'
primary_replica:
<<: *default
database: my_database
host: 'localhost'
replica: true
third_replica:
<<: *default
database: my_database
host: 'localhost'
replica: true
test: &test
primary:
<<: *default
database: 'my_database_test'
host: 'localhost'
primary_replica:
<<: *default
database: 'my_database_test'
host:'localhost'
replica: true
third_replica:
<<: *default
database: 'my_database_test'
host: 'localhost'
replica: true
I also changed the ApplicationRecord that connects to all the records of this codebase
# application_record.rb
connects_to shards: {
default: { writing: :primary, reading: :primary_replica },
admin: { writing: :primary, reading: :third_replica }
}
Now when I'm in development it acts exactly as it should
> ActiveRecord::Base.connected_to(role: :reading, shard: :default, prevent_writes: true) do
EventType.count
end
(72.3ms) SELECT COUNT(*) FROM "event_types" /*line:(pry):2:in `block in <main>'*/
=> 2
This is the correct number of records. When I run a test and use the same lines, the EventType.count outside of the wrapper will count the correct number as well, but connected_to will result in 0 no matter what record I'm checking, in any model.
> EventType.count
=> 1
> ActiveRecord::Base.connected_to(role: :reading, shard: :default, prevent_writes: true) do
EventType.count
end
=> 0
The replica in development/test is actually the same database, so it shouldn't be possible to get 0 in my case.
When using the writing role it works though
> ActiveRecord::Base.connected_to(role: :writing, shard: :default) do
EventType.count
end
=> 1
Be aware the shards: part doesn't seem to matter because it also breaks with a simplified version through database: and no third_replica
Is there something I'm missing about this Rails functionality? Is there something related to tests that aren't compatible with this? I couldn't find any documentation related to this.
In the end, the problem came from the transaction we have throughout our tests setup
DatabaseCleaner.strategy = :transaction
And it put in evidence it's a much bigger problem throughout our codebase. When having queries wrapped into transactions and using connected_to you basically go out of the said transaction and it creates lots of consistency problems in our specific case. It's purely logical, but adding this into your stack may be incompatible with what was there in the first place.
The conclusion is to be careful when using transactions and dealing with read-replica.
I got a strange situation on RSpec when Rails testing.
Normaly by using spring RSpec file taken time is very fast.
But, when using another Rails DB RSpec file taken time is 2 or 3 seconds.
My Rails app use another Rails app database.yml to use the same db.
Why is RSpec so slow? and How do I make RSpec fast?
I confirmed this is happened at Rails4 and Rails5.
Environment
DB PostgreSQL 9.4.5
This is my code.
class Test
def self.test
'test'
end
end
This is my test code.
require 'rails_helper'
RSpec.describe Test do
describe "Test.test" do
it "test" do
expect(Test.test).to eq 'test'
end
end
end
This is my database.yml. Two rails app use same yml file.
default: &default
adapter: postgresql
encoding: unicode
pool: 5
development:
<<: *default
database: qserver_development
test:
<<: *default
database: qserver_test
When I run rake to run specific/all test(s), it corrupts development database.
I verified that db for each environment is different.
database.yml
postgre_common_config: &postgre_common_config
adapter: postgresql
encoding: unicode
pool: 5
username: postgres # if using default PostgreSQL user then the value should be: postgres
password: postgres
host: localhost
development:
database: mag_development
<<: *postgre_common_config
test:
database: mag_test
<<: *postgre_common_config
production:
database: mag_production
<<: *postgre_common_config
test_helper.rb
ENV['RAILS_ENV'] = 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
class ActiveSupport::TestCase
fixtures :all
end
This is really annoying as it takes lot of time to prepare data to test specific feature manually. Please help.
I am working on existing rails project and just finished writing some basic RSpec tests for that.
In our database.yml file we have connection to 3-4 different databases and all are either pointing to either production database or staging database.
For testing environment I created a different yml file called database.test.yml and then symlinked it to database.yml file, so that the correct testing databases connections are created.
My database.test.yml looks something like this:
abc:
adapter: mysql2
host: localhost
reconnect: true
username: monty
password: python
database: abc
pqr:
adapter: mysql2
host: localhost
reconnect: true
username: monty
password: python
database: pqr
test:
adapter: mysql2
host: localhost
reconnect: true
username: monty
password: python
pool: 50
database: testing
My problem now is that how can I enforce that other developers/testers use this database.test.yml and not accidentally run the main database.yml file which contains connections to staging and production databases.
EDIT:
To further clarify my question, I have establish_connection in various models that connect to different databases. So I am not sure the earlier suggestions will solve my problem.
Example:
class Abc < ActiveRecord::Base
establish_connection :abc
end
One way I can think of for solving my problem is doing something like this:
class Abc < ActiveRecord::Base
establish_connection "abc_#{Rails.env}"
end
and in the database.yml:
defaults: &defaults
adapter: mysql2
encoding: utf8
username: root
password: secret
abc_production:
database: abc
<<: *defaults
abc_development:
database: abc_devlopment
<<: *defaults
abc_test:
database: abc_test
<<: *defaults
But I am not sure if this the best practice and I really don't feel to change the application code to setup test environment is good practice.
This idea is based on: http://blog.nistu.de/2012/03/25/multi-database-setup-with-rails-and-rspec
Any nudge or pointers towards the correction direction will be greatly helpful.
You could have something, like:
default: &default
adapter: mysql2
encoding: utf8
database: my_db_name
username: root
password: my_password
host: 127.0.0.1
port: 3306
development:
<<: *default
database: xxxx_development
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: xxxx_test
production:
<<: *default
database: xxxx_production
I have a very strange problem and I don't know where I should look to find it. I am developing a rails 3 app using rspec and factory girl for testing. For some reason, whenever I run any rails commands (eg to rake the db, start the dev server etc) one factory user is created and stored in my development database. The worst part is, it always has the same email, which I am validating the uniqueness of in my app, so the commands won't run until I go in manually delete the record.
I have looked all through my factories file and I don't think I am doing anything strange there, and suggestions where else I might for the code that is doing this?
EDIT: HERE IS MY database.yml
# MySQL. Versions 4.1 and 5.0 are recommended.
#
# Install the MySQL driver:
# gem install mysql2
#
# And be sure to use new-style password hashing:
# http://dev.mysql.com/doc/refman/5.0/en/old-client.html
development:
adapter: mysql2
encoding: utf8
reconnect: false
database: ATBTracking_development
pool: 5
username: [NOT TELLING]
password: [NOT TELLING]
socket: /var/run/mysqld/mysqld.sock
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
adapter: mysql2
encoding: utf8
reconnect: false
database: ATBTracking_test
pool: 5
username: [NOT TELLING]
password: [NOT TELLING]
socket: /var/run/mysqld/mysqld.sock
production:
adapter: mysql2
encoding: utf8
reconnect: false
database: ATBTracking_production
pool: 5
username: [NOT TELLING]
password: [NOT TELLING]
socket: /var/run/mysqld/mysqld.sock
I figured it out. In my Gemfile, I had:
group :development, :test do
gem 'capybara'
gem "rspec-rails"
gem "guard-rspec"
gem "factory_girl_rails"
...
end
I moved factory girl out of this block onto its own line so it is in the test group only like this:
gem 'factory_girl_rails', :group => :test
No more problems
db/Seeds.rb maybe...but I think that only runs on db:reset and db:seed