Global setup in RSpec - ruby

I am currently planning on using RSpec to continuously monitor some of our services. The plan is to create some tests, run them periodically and automatically alert if (when) errors are found. As many products use the same server it would make seance to create then connection once and then use the same connection for all tests.
I am not using rail, just Ruby and RSpec:
-- spec_helper.rb # Setup server connections, handle errors.
-- test1_spec.rb # Specific tests for product one, uses server connection from spec_helper.
-- test2_spec.rb # Tests for product two, uses same connection as one.
-- test3_spec.rb
Basically, can I create a before :all and after :all that applies to all files in the test, or do I need to repeat my connection in each test file (or put all tests in one big file)?

So using #CDub's useful comment I got it working by adding
RSpec.configure do |config|
config.before(:suite) {$x = 'my_variable'}
end
to the spec_helper file.
Note that the variable must be global and each file that use the variable must import rspec_helper: require_relative 'spec_helper'

Related

Rails 5: Is there a way to run a single set of tests against the development database?

I would like to run a single set of tests against the development database. My seeds.rb file populates the databse from a CSV and I want to ensure that the data is stored in the database in the way I expect. I don't want to run all tests against the development database, just a particular set.
I created an integration test. I thought I could switch environments in #setup but it looks like Rails.env = 'development' has no effect.
require 'test_helper'
class DbTest < ActionDispatch::IntegrationTest
def setup
Rails.env = 'development'
end
def test_total_settlements
...
Is it possible to run tests in different environments? If so, how is this done?
I'd recommend to create a class to seed the information into a configurable database, and then run tests against that class. In that way, you don't need to run the tests to an operational database and run that tests the number of times you want, without having to manually modify your development database in case the seed failed (like removing leftover records).
Once you have that class, you could add a task to your Rakefile and use your class :)
In my opinion, the simplest solution would be to just seed your test database.
You can call Rails.application.load_seed before the tests you need seed data for.

Output SQL from an ActiveRecord migration without executing it (not rails!)

There's a bunch of questions out there similar to this one that talk about rails plugins as a solution - but I'm not using rails, read on for more
I have a Rakefile in a sinatra project which allows me to rake db:migrate. It'll do my migration perfectly, but I'd like to pass that a flag (or write a new rake task) which does the same thing, but outputs the SQL to STDOUT and doesn't commit the changes to the database. Does anyone know how to do this?
My first thought was to try ActiveRecord logging and see if I could get the SQL out at all, but that doesn't work! Any ideas?
namespace :db do
task :migrate_sql do
require 'logger'
ActiveRecord::Base.logger = Logger.new(STDOUT)
Rake::Task['db:migrate'].invoke
# This does the migration and doesn't output SQL - so no good!
end
end
I think there isn't any easy way to do it, for the following reasons:
up, down, and change are methods which execute other methods; there isn't a global migration query string that gets built and executed
neither the statements methods (add_column, etc) expose their statements as strings; as I understand, they are implemented as connection adapter methods, and for example the mysql adapter has a add_column_sql method, while the postgresql adapter does not, and its sql is a variable inside its add_column method
So, if you really need this functionality, I think your best option is to copy the sql from the log.

Repeat the test suite for different input parameters in Test::Unit ruby

We are building a QA automation setup with test::unit and selenium. Tests for each page in our web app lives in separate directory, and at the top level directory, we have this:
require 'rubygems'
require 'test/unit'
require 'test/unit/runner/html'
require 'test/unit/ui/html/html_runner.rb'
Dir["*/test_*.rb"].each do |file|
require file
end
This creates a dynamic test suite and executes it. Inside the test scripts, there is a configuration file, which has configurations for the selenium browser driver to be used, the base url to start with, etc. We have to run the tests with all the browsers. Currently, we have to manually edit the configuration and change the selenium driver name from say, 'chrome' to 'firefox' each time after the suite is executed, and manually run it again. Can we instead set at the top level script so that the whole test suite repeats some 'x' number of times for different configurations?
If you're using Hudson, you could go with wonky Selenium Server approach where for each job (running the tests under a given browser), you can start up Selenium Server with forcedBrowserMode set to whatever browser you want to test under.

How to use Datamapper in conjunction with Heroku Scheduler?

I have a Postgres database that I manipulate using Datamapper on my ruby web server. I am trying to incorporate Heroku Scheduler to update parts of the database every 10 minutes. However when it tries to execute the script it keeps giving this error:
/app/vendor/bundle/ruby/1.9.1/gems/dm-core-1.2.0/lib/dm-core/repository.rb:72:in `adapter': Adapter not set: default. Did you forget to setup? (DataMapper::RepositoryNotSetupError)
The database is initialized when the server starts up, so why can't this script update the database like I would normally do in the rest of the code.
For example the script being called by the scheduler will contain lines such as:
User.update(:user_x => "whatever")
Is there a certain require statement I absolutely need?
First, you need to point the scheduled process to your database, so include the Datamapper.setup, but don't migrate or initialize.
Then you need to read the database. You probably want datamapper to create object models, just like your app uses. I've been using dm-is-reflective for that.
require 'data_mapper'
require 'dm-is-reflective'
dm = DataMapper.setup(:default, ENV['DATABASE_URL'])
class User
include DataMapper::Resource
is :reflective
reflect
end
p User.fields

Preloading classes without Rails?

I am working on a big project, and I realized that several of the components were groups of classes that I could turn into services and strip from Rails. But now that I've done that I realize that the slowness of loading classes without Spork isn't a function of Rails being slow, but a function of Ruby being slow. Is there something like Spork that will work in non Rails projects?
Spork should work just fine for any ruby project, it just requires a bit more setup.
Assuming you're using rspec 2.x and spork 0.9, make a spec_helper.rb that looks something like:
require 'spork'
# the rspec require seems to be necessary,
# without it you get "Missing or uninitialized constant: Object::RSpec" errors
require 'rspec'
Spork.prefork do
# do expensive one-time setup here
require 'mylibrary'
MyLibrary.setup_lots_of_stuff
end
Spork.each_run do
# do setup that must be done on each test run here (setting up external state, etc):
MyLibrary.reset_db
end
Everything in the Spork.prefork block will only be run once (at spork startup), the rest will run on every test invocation.
If you have lots of framework-specific setup, you'd probably be better off making an AppFramework for your library. See the padrino AppFramework for an example.

Resources