transactional-factories 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,41 @@
1
+ = Transactional-factories
2
+
3
+ transactional-factories uses nested-transactions to allow efficient, programmatic initialization of test data.
4
+
5
+ Typical setup/teardown TestCase callbacks are called prior to every test method. Ruby's Test::Unit::TestCase wraps each test method in a transaction. If your test data must be created programmatically, the data creation code must be run prior to every test method. When the data creation code is slow, this will greatly increase the time it takes to run tests.
6
+
7
+ transactional-factories provides self.setup and self.teardown callbacks that are run only once for the entire testsuite. A file-level transaction is used to unwind any changes made in self.setup. Then any test methods are called in nested transactions (per normal TestCase behavior). This relies on database transactions so that we only have to run our data creation code once.
8
+
9
+ require 'transactional_factories'
10
+
11
+ class MyTest < Test::Unit::TestCase
12
+ def self.setup
13
+ 100.times { MyModel.create }
14
+ end
15
+
16
+ def test_my_model_1
17
+ assert_equal 100, MyModel.create
18
+ MyModel.create
19
+ assert_equal 101, MyModel.create
20
+ end
21
+
22
+ def test_my_model_2
23
+ assert_equal 100, MyModel.create
24
+ MyModel.create
25
+ assert_equal 101, MyModel.create
26
+ end
27
+ end
28
+
29
+ === Dependencies
30
+
31
+ <b>nested transactional db</b> - You must be using a database that supports nested transactions or savepoints. I've only tested on MySQL. Would be nice to have someone confirm this on PostgreSQL.
32
+
33
+ <b>>= ActiveRecord 2.3.x</b> - I don't think ActiveRecord supported nested transactions until 2.3.x.
34
+
35
+ <b>use_transactional_fixtures = false</b> - Your test cases can not use transactional fixtures. They're doing about the same thing that the transactional-factories gem is doing and they stomp on each other.
36
+
37
+ If you get this: TransactionalFactories::TransactionalFixturesEnabled, it's time to disable transactional fixtures doing something like this:
38
+
39
+ class ActiveSupport::TestCase
40
+ self.use_transactional_fixtures = false
41
+ end
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "transactional-factories"
8
+ gem.summary = "Using nested-transactions to initialize test data programmatically."
9
+ gem.description = "Transactional-factories uses nested-transactions (like transactional fixtures) to allow efficient initialization of test data programmatically (unlike transactional fixtures)."
10
+ gem.email = "tim.harrison@yahoo.com"
11
+ gem.homepage = "http://github.com/heedspin/transactional-factories"
12
+ gem.authors = ["Tim Harrison"]
13
+ gem.add_dependency('activerecord', '>= 2.3.2')
14
+ gem.files.exclude '.gitignore'
15
+ end
16
+ Jeweler::RubyforgeTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler gem is missing"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'test'
24
+ test.pattern = 'test/**/*_test.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ task :test => :check_dependencies
29
+
30
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,2 @@
1
+ require 'transactional_factories/test_suite'
2
+ require 'transactional_factories/test_case'
@@ -0,0 +1,21 @@
1
+ class Test::Unit::TestCase
2
+ class << self
3
+ def suite
4
+ method_names = public_instance_methods(true)
5
+ tests = method_names.delete_if {|method_name| method_name !~ /^test./}
6
+ suite = TransactionalFactories::TestSuite.new(name)
7
+ tests.sort.each do
8
+ |test|
9
+ catch(:invalid_test) do
10
+ suite << new(test)
11
+ end
12
+ end
13
+ if (suite.empty?)
14
+ catch(:invalid_test) do
15
+ suite << new("default_test")
16
+ end
17
+ end
18
+ return suite
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,36 @@
1
+ require 'test/unit'
2
+
3
+ module TransactionalFactories
4
+ class TransactionalFixturesEnabled < Exception
5
+ end
6
+ class TestSuite < Test::Unit::TestSuite
7
+ def run(result, &progress_block)
8
+ if testcase = @tests.find { |tc| tc.class.respond_to?(:setup) }
9
+ if testcase.class.respond_to?(:use_transactional_fixtures) and testcase.class.use_transactional_fixtures
10
+ raise TransactionalFixturesEnabled, 'transactional-factories does not work with transactional fixtures. Please set use_transactional_fixtures = false.'
11
+ end
12
+ end
13
+ if @tests.any? { |testcase| testcase.method_name != 'default_test' }
14
+ ActiveRecord::Base.transaction(:requires_new => true) do
15
+ testcase.class.setup if testcase
16
+ begin
17
+ yield(STARTED, name)
18
+ @tests.each do |test|
19
+ ActiveRecord::Base.transaction(:requires_new => true) do
20
+ test.run(result, &progress_block)
21
+ raise ActiveRecord::Rollback
22
+ end
23
+ end
24
+ yield(FINISHED, name)
25
+ rescue
26
+ raise $!
27
+ ensure
28
+ testcase.class.teardown if testcase.class.respond_to?(:teardown)
29
+ end
30
+ Timecop.return if defined?(Timecop)
31
+ raise ActiveRecord::Rollback
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
data/test/db/schema.rb ADDED
@@ -0,0 +1,5 @@
1
+ ActiveRecord::Schema.define do
2
+ create_table "blog_posts", :force => true do |t|
3
+ t.column "title", :string
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ class BlogPost < ActiveRecord::Base
2
+ end
@@ -0,0 +1,15 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'active_record'
4
+
5
+ ActiveRecord::Base.logger = Logger.new(STDOUT)
6
+ ActiveRecord::Base.colorize_logging = false
7
+
8
+ ActiveRecord::Base.establish_connection( { :adapter => 'mysql', :database => 'test' } )
9
+ ActiveRecord::Base.connection.recreate_database('transactional_factories_test')
10
+ ActiveRecord::Base.clear_active_connections!
11
+ ActiveRecord::Base.establish_connection( { :adapter => 'mysql', :database => 'transactional_factories_test' } )
12
+
13
+ load File.dirname(__FILE__) + '/db/schema.rb'
14
+ $:.push File.dirname(__FILE__) + '/lib'
15
+ $:.push File.dirname(__FILE__) + '/../lib'
@@ -0,0 +1,35 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ require 'blog_post'
4
+ require 'transactional_factories'
5
+
6
+ class TestBlogPost < Test::Unit::TestCase
7
+ @@initial_blog_post = nil
8
+ def self.setup
9
+ @@initial_blog_post = BlogPost.create(:title => 'initial blog post')
10
+ end
11
+
12
+ def self.teardown
13
+ raise 'Teardown unhappy' if @@initial_blog_post.nil?
14
+ # Hard to assert on teardown since it's the last step. How would you know it *didn't* happen?
15
+ end
16
+
17
+ def setup
18
+ assert @@initial_blog_post
19
+ assert_equal @@initial_blog_post, BlogPost.first
20
+ BlogPost.create(:title => 'setup blog post')
21
+ end
22
+
23
+ def test_blog_post1
24
+ assert_equal 2, BlogPost.count
25
+ BlogPost.create(:title => 'blog post 1')
26
+ assert_equal 3, BlogPost.count
27
+ end
28
+
29
+ def test_blog_post2
30
+ assert_equal 2, BlogPost.count
31
+ BlogPost.create(:title => 'blog post 2')
32
+ assert_equal 3, BlogPost.count
33
+ end
34
+
35
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: transactional-factories
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Tim Harrison
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-31 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activerecord
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.3.2
24
+ version:
25
+ description: Transactional-factories uses nested-transactions (like transactional fixtures) to allow efficient initialization of test data programmatically (unlike transactional fixtures).
26
+ email: tim.harrison@yahoo.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.rdoc
33
+ files:
34
+ - README.rdoc
35
+ - Rakefile
36
+ - VERSION
37
+ - lib/transactional_factories.rb
38
+ - lib/transactional_factories/test_case.rb
39
+ - lib/transactional_factories/test_suite.rb
40
+ - test/db/schema.rb
41
+ - test/lib/blog_post.rb
42
+ - test/test_helper.rb
43
+ - test/unit/blog_post_test.rb
44
+ has_rdoc: true
45
+ homepage: http://github.com/heedspin/transactional-factories
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options:
50
+ - --charset=UTF-8
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.3.5
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Using nested-transactions to initialize test data programmatically.
72
+ test_files:
73
+ - test/db/schema.rb
74
+ - test/lib/blog_post.rb
75
+ - test/test_helper.rb
76
+ - test/unit/blog_post_test.rb