Flipper 1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,77 @@
1
+
2
+ = Flipper
3
+
4
+ "Switch your database on the fly"
5
+
6
+
7
+ == Introduction
8
+
9
+ When doing integration and acceptance testing you typically need to:
10
+
11
+ * Change and manage application state.
12
+ * Guarantee test case isolation, even for those that change the application state.
13
+
14
+ 9 times out of 10, all you need to do to achieve this for a Rails application is:
15
+
16
+ * Have direct access to the database.
17
+ * Ensure that tests running in parallel access a different database schema.
18
+
19
+ So if you are driving your tests at the HTTP layer (e.g. Selenium tests) you could use a
20
+ single Mongrel cluster to run a lot of tests in parallel, a long as you can change your
21
+ database on the fly for each HTTP requests. This is what Flipper does.
22
+
23
+ == Status
24
+
25
+ The current status is quite good. Flipper is currently used on a daily basis on commercial projects.
26
+
27
+
28
+ == Installation
29
+
30
+ The easiest way to install is via RubyGems. On the command line enter:
31
+
32
+ > gem install flipper
33
+
34
+ == Usage
35
+
36
+ To use flipper just include the <code>Flipper</code> module and add a before filter in <code>application.rb</code>:
37
+
38
+ class ApplicationController < ActionController::Base
39
+ include Flipper
40
+
41
+ before_filter :switch_database
42
+
43
+ ...
44
+ end
45
+
46
+ == License
47
+
48
+ The collection PER COLLECTION is licensed as follows:
49
+
50
+ Ruby Facets
51
+ Copyright (c) 2004-2006 Thomas Sawyer
52
+
53
+ Distributed under the terms of the Ruby license.
54
+
55
+ The Ruby license is a dual license that also provides for use of the GPL.
56
+ Complete texts of both licenses accompany this document (see doc/COPYING).
57
+
58
+ This program is free software; you can redistribute it and/or modify
59
+ it under the terms of the GNU General Public License as published by
60
+ the Free Software Foundation; either version 2 of the License, or
61
+ (at your option) any later version.
62
+
63
+ This program is distributed in the hope that it will be useful,
64
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
65
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66
+ GNU General Public License for more details.
67
+
68
+ You should have received a copy of the GNU General Public License
69
+ along with this program; if not, write to the Free Software
70
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
71
+
72
+ Acknowledgments and Copyrights for particular snippets of borrowed code
73
+ are given in their respective source. All licenses are either compatible
74
+ with the Ruby license (namely the GPL) or the original author has given
75
+ permission for inclusion of their code under such lincense.
76
+
77
+
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'rake/gempackagetask'
5
+ require 'rake/contrib/sshpublisher'
6
+
7
+
8
+ desc 'Default: run unit tests.'
9
+ task :default => :test
10
+
11
+ desc 'Test the flipper plugin.'
12
+ Rake::TestTask.new(:test) do |t|
13
+ t.libs << 'lib'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = true
16
+ end
17
+
18
+ desc 'Generate documentation for the flipper plugin.'
19
+ Rake::RDocTask.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'Flipper'
22
+ rdoc.options << '--line-numbers' << '--inline-source'
23
+ rdoc.rdoc_files.include('README')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
26
+
27
+ Gem::manage_gems
28
+
29
+ specification = Gem::Specification.new do |s|
30
+ s.name = "Flipper"
31
+ s.summary = "Switch your Rails database on the fly for each HTTP request. Useful for integration and acceptance testing (test isolation & state management)."
32
+ s.version = "1.0"
33
+ s.author = 'Philippe Hanrigou & Dan Manges'
34
+ s.description = s.summary
35
+ s.email = 'flipper-developer@rubyforge.org'
36
+ s.homepage = 'http://flipper.rubyforge.org'
37
+ s.rubyforge_project = 'flipper'
38
+
39
+ s.has_rdoc = true
40
+ s.extra_rdoc_files = ['README']
41
+ s.rdoc_options << '--title' << 'Flipper' << '--main' << 'README' << '--line-numbers'
42
+
43
+ s.autorequire = 'flipper'
44
+ s.files = FileList['{lib,test}/**/*.rb', '[A-Z]*$', 'Rakefile'].to_a
45
+ s.test_file = "test/all_tests.rb"
46
+ end
47
+
48
+ Rake::GemPackageTask.new(specification) do |package|
49
+ package.need_zip = false
50
+ package.need_tar = false
51
+ end
data/lib/flipper.rb ADDED
@@ -0,0 +1,37 @@
1
+ #
2
+ # Include this module in your Rails controller to change database schema on each HTTP request:
3
+ #
4
+ # class ApplicationController < ActionController::Base
5
+ # include Flipper
6
+ #
7
+ # before_filter :switch_database # if RAILS_ENV == "selenium"
8
+ #
9
+ # ...
10
+ # end
11
+ module Flipper
12
+
13
+ #
14
+ # Switch current database based on <code>flipper_db_config</code> HTTP parameter, if any,
15
+ # and store database configuration in session.
16
+ #
17
+ # If there is no <code>flipper_db_config</code> parameter, switch to the database configuration
18
+ # stored in session.
19
+ #
20
+ # If anything goes wrong while switching database, attempts to rollback to the previous database configuration
21
+ # before raising an exception.
22
+ def switch_database
23
+ database_configuration = params[:flipper_db_config] || session[:flipper_db_config]
24
+ return unless database_configuration
25
+
26
+ prior_configuration = ActiveRecord::Base.connection.instance_variable_get(:@config)
27
+ ActiveRecord::Base.clear_active_connections!
28
+ begin
29
+ ActiveRecord::Base.establish_connection database_configuration
30
+ session[:flipper_db_config] = database_configuration
31
+ rescue => ex
32
+ ActiveRecord::Base.establish_connection prior_configuration
33
+ raise
34
+ end
35
+ end
36
+
37
+ end
data/test/all_tests.rb ADDED
@@ -0,0 +1 @@
1
+ Dir["#{File.dirname __FILE__}/*_test.rb"].each { |test_case| require test_case }
@@ -0,0 +1,78 @@
1
+ require "rubygems"
2
+ require "dust"
3
+ require "mocha"
4
+ require 'test/unit'
5
+
6
+ unless defined?(ActiveRecord)
7
+ module ActiveRecord
8
+ class Base; end
9
+ end
10
+ end
11
+
12
+ require File.dirname(__FILE__) + "/../lib/flipper"
13
+
14
+ unit_tests do
15
+
16
+ def setup
17
+ @controller = Class.new { include Flipper }.new
18
+ end
19
+
20
+ test "controller establishes new db connection and clears active connection when receiving database_connection from params" do
21
+ @controller.stubs(:session).returns({})
22
+ @controller.stubs(:params).returns(:flipper_db_config => :connection_hash)
23
+ ActiveRecord::Base.stubs(:connection).returns(stub_everything)
24
+ ActiveRecord::Base.expects(:clear_active_connections!)
25
+ ActiveRecord::Base.expects(:establish_connection).with(:connection_hash)
26
+ @controller.send(:switch_database)
27
+ end
28
+
29
+ test "controller establishes new db connection and clears active connection when receiving database_connection from session" do
30
+ @controller.stubs(:session).returns(:flipper_db_config => :connection_hash)
31
+ @controller.stubs(:params).returns(:flipper_db_config => nil)
32
+ ActiveRecord::Base.stubs(:connection).returns(stub_everything)
33
+ ActiveRecord::Base.expects(:clear_active_connections!)
34
+ ActiveRecord::Base.expects(:establish_connection).with(:connection_hash)
35
+ @controller.send(:switch_database)
36
+ end
37
+
38
+ test "controller checks for database configuration in params before session" do
39
+ @controller.stubs(:session).returns(:flipper_db_config => :session_connection_hash)
40
+ @controller.stubs(:params).returns(:flipper_db_config => :params_connection_hash)
41
+ ActiveRecord::Base.stubs(:connection).returns(stub_everything)
42
+ ActiveRecord::Base.expects(:clear_active_connections!)
43
+ ActiveRecord::Base.expects(:establish_connection).with(:params_connection_hash)
44
+ @controller.send(:switch_database)
45
+ end
46
+
47
+ test "controller does not establish a new db connection nor clears active connection when there is no database_connection neither in params nor in session" do
48
+ @controller.stubs(:session).returns({})
49
+ @controller.stubs(:params).returns(:flipper_db_config => nil)
50
+ ActiveRecord::Base.stubs(:connection).returns(stub_everything)
51
+ ActiveRecord::Base.expects(:clear_active_connections!).never
52
+ ActiveRecord::Base.expects(:establish_connection).never
53
+ @controller.send(:switch_database)
54
+ end
55
+
56
+ test "database configuration is stored in session after passed in through params" do
57
+ @controller.stubs(:session).returns(session = {})
58
+ @controller.stubs(:params).returns(:flipper_db_config => :connection_hash)
59
+ ActiveRecord::Base.stubs(:connection).returns(stub_everything)
60
+ ActiveRecord::Base.stubs(:clear_active_connections!)
61
+ ActiveRecord::Base.stubs(:establish_connection)
62
+ @controller.send(:switch_database)
63
+ assert_equal :connection_hash, session[:flipper_db_config]
64
+ end
65
+
66
+ test "controller restores original db connection and raises exception when establishing a new database_connection fails" do
67
+ @controller.stubs(:session).returns({})
68
+ @controller.stubs(:params).returns(:flipper_db_config => :connection_hash)
69
+ ActiveRecord::Base.stubs(:connection).returns(connection = stub)
70
+ connection.instance_variable_set "@config", :old_configuration
71
+ ActiveRecord::Base.expects(:clear_active_connections!)
72
+ exception = RuntimeError.new("will be raised if new connection cannot be established")
73
+ ActiveRecord::Base.expects(:establish_connection).with(:connection_hash).raises(exception)
74
+ ActiveRecord::Base.expects(:establish_connection).with(:old_configuration)
75
+ assert_raises(RuntimeError) { @controller.send(:switch_database) }
76
+ end
77
+
78
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: Flipper
5
+ version: !ruby/object:Gem::Version
6
+ version: "1.0"
7
+ date: 2007-09-15 00:00:00 -04:00
8
+ summary: Switch your Rails database on the fly for each HTTP request. Useful for integration and acceptance testing (test isolation & state management).
9
+ require_paths:
10
+ - lib
11
+ email: flipper-developer@rubyforge.org
12
+ homepage: http://flipper.rubyforge.org
13
+ rubyforge_project: flipper
14
+ description: Switch your Rails database on the fly for each HTTP request. Useful for integration and acceptance testing (test isolation & state management).
15
+ autorequire: flipper
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Philippe Hanrigou & Dan Manges
31
+ files:
32
+ - lib/flipper.rb
33
+ - test/flipper_test.rb
34
+ - test/all_tests.rb
35
+ - Rakefile
36
+ - README
37
+ test_files:
38
+ - test/all_tests.rb
39
+ rdoc_options:
40
+ - --title
41
+ - Flipper
42
+ - --main
43
+ - README
44
+ - --line-numbers
45
+ extra_rdoc_files:
46
+ - README
47
+ executables: []
48
+
49
+ extensions: []
50
+
51
+ requirements: []
52
+
53
+ dependencies: []
54
+