saimonmoore / siringa

Remotely populate DB for Rails applications for pure client acceptance and manual testing.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Siringa 💉

This gem was born working on pure client acceptance testing in Redbooth.

WARNING ⚠️

Due to a conflict with reserved word load we are deprecating #load action in SiringaController in favour of #load_definition. This change is reflected by a warning in logs but will be dropped in version 0.1.0.

The problem

You have a Rails based API and you need to write some acceptance tests using your Javascript/iOS/Android/whatever client.

Probably you'll have three basic needs:

  1. Pre-populate the DB with some (maybe massive) data (a.k.a. seed data)
  2. Your seed data files have to be easily maintainable, you don't want to touch them too much when a model change and so on
  3. Populate your DB while executing some specific acceptance test and then clean up the DB restoring the initial situation

The solution

  1. Write your seed data and use Siringa's rake recipes to pre-populate the DB just after you deploy your API
  2. I suggest to use factories to create your seed data in order to take advantage of factories maybe you've already written for unit tests. But you could use whatever other way to keep your seed data maintainable and you still could use Siringa
  3. Use Siringa's extra API endpoints in order to dump your inital DB situation, load some factories and then restore the initial status when you're done

Why you don't just use your app's API to do the same thing, maybe storing JSON/XML objects in some fixture?

Well, because mantaining those huge JSON/XML fixture files will be a nightmare.

Install Siringa

Add the following to your Gemfile:

group :test do
  gem 'siringa'
end

For security reasons, I suggest to add it under the test group. In that way you'll have Siringa available only running the app in test environment.

Run the bundle command to install it.

Run the generator:

rails generate siringa:install

This will create an empty directory in tmp/dumps.

Add the following to your config/routes.rb:

mount Siringa::Engine, :at => '/siringa'

Make sure that you add it in the correct environment. For instance if you want it available only in test environment put it inside a condition statement like if Rails.env.test? .. end.

Create definitions

In order to create a new Siringa definition just create a new file in the test/siringa directory like the following:

# test/siringa/definitions.rb
require 'siringa'
require File.expand_path('../../factories', __FILE__)

Siringa.add_definition :initial do
  FactoryGirl.create :user,
    name: 'Jesse Pinkman'
end

Siringa.add_definition :specific do
  FactoryGirl.create :user,
    name: 'Hank Schrader'
  FactoryGirl.create :project,
    name: 'Pollos Hermanos'
end

I'm using FactoryGirl gem here but in a definition you could write whatever kind of Ruby code and Siringa will execute it when you call the definition.

Load definitions

Now that we've created our definitions we could use them in our two cases:

As seed data

You could just load the initial definition running the following rake recipe after your deploy:

rake siringa:load_definition

initial is the default definition this Rake task recipe will try to load, if you want to load another definition instead you could pass its name as argument:

rake 'siringa:load_definition[another_definition]'

This will load a definition named :another_definition. Please note that if you use Zsh shell you'll need to use quotes, more info here.

If you want to force a Rails environment you could just run the Sriringa recipe specifing the RAILS_ENV environmental variable:

RAILS_ENV=development rake siringa:load_definition

During an acceptance test

As you can see running rake routes, Siringa added 3 new routes to your API:

Routes for Siringa::Engine:
        POST /load_definition/:definition(.:format) siringa/siringa#load_definition
   dump POST /dump(.:format)             siringa/siringa#dump
restore POST /restore(.:format)          siringa/siringa#restore

The workflow I propose here is:

  1. Create a dump of your DB performing a POST request to YOURHOST/siringa/dump

    This will create a .dump file in the tmp/dumps directory created during the install process. You could create as many dump files as you want but Siringa will keep only the latest 5 dumps created.

  2. Load a Siringa definition performing a POST request to YOURHOST/siringa/load_definition/specific

    This will run the code defined in a definition named specific on the server.

  3. Go ahead with your acceptance test

  4. Restore the DB status performing a POST request to YOURHOST/siringa/restore

    This will bring back your DB at the initial status using the dump file you created in step 1.

    Please note that the Siringa::restore method only use the latest dump file created, older dump files in the tmp/dumps folder will be ignored.

Customize Siringa

You could customize Siringa changing the configuration in the environment where you load Siringa:

# config/environments/test.rb
Siringa.configure do |config|
  # customize the path where the definitions are stored
  config.definitions_path = 'test/siringa'
  # customize the path where the DB dumps are stored
  config.dumps_path = 'tmp/dumps'
end

Acceptance test example

Just to get the idea, the following script will show you how to use Siringa in a acceptance test using Selenium, rest-client and RSpec:

require 'selenium-webdriver'
require 'rspec'
require 'rest_client'

describe "Acceptance test using Siringa" do
  before(:all) do
    # Dump your DB
    RestClient.post 'YOURHOST/siringa/dump'
  end

  before(:each) do
    @driver = Selenium::WebDriver.for :firefox
  end

  after(:each) do
    @driver.quit
  end

  it "Loads a definition and test something" do
    # Loads a definition named 'specific'
    RestClient.post 'YOURHOST/siringa/load_definition', { definition: :specific }

    # Here goes your test

    # Restore your DB
    RestClient.post 'YOURHOST/siringa/restore'
  end
end

To Do

  • Write more tests
  • Add Postgres adaptor compatibility for dumps and restores
  • Add more customizations

How to collaborate

  • Fork the repo and send a pull request, thanks!

License

MIT-LICENSE 2013 Enrico Stano

About

Remotely populate DB for Rails applications for pure client acceptance and manual testing.

License:MIT License


Languages

Language:Ruby 90.9%Language:HTML 6.8%Language:JavaScript 1.3%Language:CSS 1.0%