unit_record 0.4.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/CHANGELOG +14 -0
  2. data/LICENSE +20 -0
  3. data/README.markdown +137 -0
  4. data/Rakefile +63 -56
  5. data/lib/active_record/connection_adapters/unit_record_adapter.rb +97 -0
  6. data/lib/unit_record.rb +8 -1
  7. data/lib/unit_record/association_stubbing.rb +39 -0
  8. data/lib/unit_record/column_extension.rb +11 -0
  9. data/lib/unit_record/disconnected_active_record.rb +10 -32
  10. data/lib/unit_record/disconnected_test_case.rb +6 -0
  11. data/test/active_record/connection_adapters/unit_record_adapter_test.rb +103 -0
  12. data/test/db/schema.rb +9 -0
  13. data/test/sample_spec.rb +40 -0
  14. data/test/test_helper.rb +28 -4
  15. data/test/unit_record/association_stubbing_test.rb +37 -0
  16. data/test/unit_record/column_cacher_test.rb +26 -0
  17. data/test/{unit → unit_record}/column_extension_test.rb +1 -1
  18. data/test/{functional → unit_record}/column_test.rb +1 -1
  19. data/test/{functional → unit_record}/controller_test.rb +1 -1
  20. data/test/unit_record/disconnected_active_record_test.rb +52 -0
  21. data/test/{functional → unit_record}/disconnected_fixtures_test.rb +1 -1
  22. data/test/unit_record/disconnected_test_case_test.rb +19 -0
  23. data/vendor/dust-0.1.6/lib/array_extension.rb +5 -0
  24. data/vendor/dust-0.1.6/lib/definition_error.rb +20 -0
  25. data/vendor/dust-0.1.6/lib/dust.rb +8 -0
  26. data/vendor/dust-0.1.6/lib/nil_extension.rb +5 -0
  27. data/vendor/dust-0.1.6/lib/object_extension.rb +62 -0
  28. data/vendor/dust-0.1.6/lib/string_extension.rb +5 -0
  29. data/vendor/dust-0.1.6/lib/symbol_extension.rb +5 -0
  30. data/vendor/dust-0.1.6/lib/test_case_extension.rb +76 -0
  31. data/vendor/dust-0.1.6/rakefile.rb +50 -0
  32. data/vendor/dust-0.1.6/test/all_tests.rb +1 -0
  33. data/vendor/dust-0.1.6/test/failing_with_helper_unit_test.rb +16 -0
  34. data/vendor/dust-0.1.6/test/failing_with_setup_unit_test.rb +16 -0
  35. data/vendor/dust-0.1.6/test/functional_test.rb +12 -0
  36. data/vendor/dust-0.1.6/test/passing_unit_test.rb +11 -0
  37. data/vendor/dust-0.1.6/test/passing_with_helper_unit_test.rb +10 -0
  38. data/vendor/dust-0.1.6/test/passing_with_helpers_unit_test.rb +13 -0
  39. data/vendor/dust-0.1.6/test/passing_with_setup_unit_test.rb +10 -0
  40. data/vendor/dust-0.1.6/test/test_helper.rb +1 -0
  41. metadata +75 -52
  42. data/README +0 -60
  43. data/lib/unit_record/column_cacher.rb +0 -45
  44. data/test/functional/column_cacher_test.rb +0 -19
  45. data/test/functional/disconnected_active_record_test.rb +0 -33
  46. data/test/functional/disconnected_test_case_test.rb +0 -7
  47. data/test/functional/functional_test_helper.rb +0 -4
  48. data/test/unit/unit_test_helper.rb +0 -5
@@ -0,0 +1,39 @@
1
+ module UnitRecord
2
+ module AssociationStubbing
3
+
4
+ private
5
+
6
+ def initialize_with_association_stubbing(attributes = {})
7
+ attributes ||= {}
8
+ associations = extract_associations attributes
9
+ initialize_without_association_stubbing attributes
10
+ stub_associations associations
11
+ end
12
+
13
+ protected
14
+
15
+ def extract_associations(attributes = {})
16
+ attributes.inject({}) do |associations,(attr,value)|
17
+ next associations unless self.class.reflections.keys.include? attr
18
+ unless value.is_a?(self.class.reflections[attr].klass)
19
+ associations[attr] = attributes.delete attr
20
+ end
21
+ associations
22
+ end
23
+ end
24
+
25
+ def stub_associations(associations = {})
26
+ associations.each do |attr,value|
27
+ self.stubs(attr).returns(value)
28
+ end
29
+ end
30
+
31
+ def self.included(klass)
32
+ klass.class_eval do
33
+ unless (instance_methods + private_instance_methods).include?("initialize_without_association_stubbing")
34
+ alias_method_chain :initialize, :association_stubbing
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,5 +1,16 @@
1
1
  module UnitRecord
2
2
  module ColumnExtension
3
+ def self.included(base)
4
+ base.class_eval do
5
+ alias_method_chain :simplified_type, :boolean
6
+ end
7
+ end
8
+
9
+ def simplified_type_with_boolean(field_type)
10
+ return :boolean if field_type.to_s.downcase.index("tinyint(1)")
11
+ simplified_type_without_boolean field_type
12
+ end
13
+
3
14
  def ==(other)
4
15
  other && instance_variables.all? { |ivar| instance_variable_get(ivar) == other.instance_variable_get(ivar) }
5
16
  end
@@ -1,43 +1,21 @@
1
1
  module UnitRecord
2
2
  module DisconnectedActiveRecord
3
3
  def disconnected?
4
- false
4
+ connected? && connection.is_a?(ActiveRecord::ConnectionAdapters::UnitRecordAdapter)
5
5
  end
6
- def disconnect!
6
+
7
+ def disconnect!(options = {})
7
8
  return if disconnected?
8
- (class << self; self; end).class_eval do
9
- def cache
10
- yield
11
- end
12
-
13
- def cached_columns
14
- @@_cached_columns ||= {}
15
- end
16
-
17
- def columns
18
- cached_columns[table_name] ||
19
- raise("Columns are not cached for '#{table_name}' - check schema.rb")
20
- end
21
-
22
- def connection
23
- raise "(from #{to_s}): ActiveRecord is disconnected; database access is unavailable in unit tests."
24
- end
25
-
26
- def connected?
27
- false
28
- end
29
-
30
- def disconnected?
31
- true
32
- end
33
-
34
- def table_exists?
35
- true
36
- end
9
+ establish_connection options.merge(:adapter => "unit_record")
10
+ if options[:stub_associations]
11
+ ActiveRecord::Base.send :include, UnitRecord::AssociationStubbing
37
12
  end
38
13
  Fixtures.disconnect!
39
14
  Test::Unit::TestCase.disconnect!
40
- ColumnCacher.cache(RAILS_ROOT + "/db/schema.rb")
15
+ ActiveRecord::Migration.verbose = false
16
+ ActiveRecord::Base.connection.change_strategy(:noop) do
17
+ load(RAILS_ROOT + "/db/schema.rb")
18
+ end
41
19
  end
42
20
  end
43
21
  end
@@ -2,6 +2,12 @@ module UnitRecord
2
2
  module DisconnectedTestCase
3
3
  def disconnect!
4
4
  self.use_transactional_fixtures = false
5
+
6
+ class_eval do
7
+ def self.fixtures(*args)
8
+ raise "Fixtures cannot be used with UnitRecord. ActiveRecord is disconnected; database access is unavailable in unit tests."
9
+ end
10
+ end
5
11
  end
6
12
  end
7
13
  end
@@ -0,0 +1,103 @@
1
+ require File.dirname(__FILE__) + "/../../test_helper"
2
+
3
+ functional_tests do
4
+
5
+ test "reconnect works" do
6
+ ActiveRecord::Base.connection.reconnect!
7
+ assert_kind_of ActiveRecord::ConnectionAdapters::UnitRecordAdapter,
8
+ ActiveRecord::Base.connection
9
+ end
10
+
11
+ test "find(:all)" do
12
+ ActiveRecord::Base.connection.change_strategy(:raise) do
13
+ assert_raises(RuntimeError) { Person.find(:all) }
14
+ end
15
+ ActiveRecord::Base.connection.change_strategy(:noop) do
16
+ assert_equal [], Person.find(:all)
17
+ end
18
+ end
19
+
20
+ test "execute raises an exception" do
21
+ assert_raises_disconnected_exception do
22
+ ActiveRecord::Base.connection.execute "SELECT 1"
23
+ end
24
+ end
25
+
26
+ test "select_rows raises an exception" do
27
+ assert_raises_disconnected_exception do
28
+ ActiveRecord::Base.connection.select_rows "SELECT * FROM people"
29
+ end
30
+ end
31
+
32
+ test "select raises an exception" do
33
+ assert_raises_disconnected_exception do
34
+ ActiveRecord::Base.connection.send :select, "SELECT * FROM people"
35
+ end
36
+ end
37
+
38
+ test "rename_table raises an exception" do
39
+ assert_raises_disconnected_exception do
40
+ ActiveRecord::Base.connection.rename_table "people", "persons"
41
+ end
42
+ end
43
+
44
+ test "change_column raises an exception" do
45
+ assert_raises_disconnected_exception do
46
+ ActiveRecord::Base.connection.change_column "people", "first_name", :string, :null => false
47
+ end
48
+ end
49
+
50
+ test "change_column_default raises an exception" do
51
+ assert_raises_disconnected_exception do
52
+ ActiveRecord::Base.connection.change_column_default "people", "first_person", "george"
53
+ end
54
+ end
55
+
56
+ test "rename_column raises an exception" do
57
+ assert_raises_disconnected_exception do
58
+ ActiveRecord::Base.connection.rename_column "people", "first_name", "name_first"
59
+ end
60
+ end
61
+
62
+ test "insert raises an exception" do
63
+ assert_raises_disconnected_exception do
64
+ ActiveRecord::Base.connection.rename_column "people", "first_name", "name_first"
65
+ end
66
+ end
67
+
68
+ test "initialize can set strategy" do
69
+ ActiveRecord::Base.establish_connection :adapter => "unit_record", :strategy => :noop
70
+ assert_nil ActiveRecord::Base.connection.execute("SELECT 1")
71
+ ActiveRecord::Base.establish_connection :adapter => "unit_record", :strategy => :raise
72
+ assert_raises(RuntimeError) { ActiveRecord::Base.connection.execute("SELECT 1") }
73
+ end
74
+
75
+ test "noop" do
76
+ ActiveRecord::Base.connection.change_strategy(:noop) do
77
+ assert_nil ActiveRecord::Base.connection.execute("SELECT 1")
78
+ assert_nil ActiveRecord::Base.connection.insert("INSERT INTO ...")
79
+ assert_equal [], ActiveRecord::Base.connection.select_rows("SELECT * FROM people")
80
+ assert_equal [], ActiveRecord::Base.connection.send(:select, "SELECT * FROM people")
81
+ assert_nil ActiveRecord::Base.connection.rename_table("people", "persons")
82
+ assert_nil ActiveRecord::Base.connection.change_column("people", "first_name", :string, :null => false)
83
+ assert_nil ActiveRecord::Base.connection.change_column_default("people", "first_person", "george")
84
+ assert_nil ActiveRecord::Base.connection.rename_column("people", "first_name", "name_first")
85
+ end
86
+ end
87
+
88
+ test "change_strategy raises if invalid strategy" do
89
+ assert_nothing_raised { ActiveRecord::Base.connection.change_strategy(:noop) {} }
90
+ assert_nothing_raised { ActiveRecord::Base.connection.change_strategy(:raise) {} }
91
+ assert_raises(ArgumentError) { ActiveRecord::Base.connection.change_strategy(:bogus) {} }
92
+ end
93
+
94
+ def assert_raises_disconnected_exception(&block)
95
+ exception = nil
96
+ begin
97
+ yield
98
+ rescue Exception => exception
99
+ end
100
+ assert_not_nil exception
101
+ assert_equal "ActiveRecord is disconnected; database access is unavailable in unit tests.", exception.message
102
+ end
103
+ end
data/test/db/schema.rb CHANGED
@@ -9,6 +9,15 @@ ActiveRecord::Schema.define(:version => 0) do
9
9
  t.column :last_name, :string
10
10
  end
11
11
 
12
+ create_table "profiles", :force => true do |t|
13
+ t.column "description", :string
14
+ t.column "person_id", :integer
15
+ end
16
+
17
+ create_table :pets, :force => true do |t|
18
+ t.column :name, :string
19
+ end
20
+
12
21
  create_table :foofoo, :force => true do |t|
13
22
  t.column :bar, :string
14
23
  end
@@ -0,0 +1,40 @@
1
+ require "rubygems"
2
+ gem "rspec", "1.1.11"
3
+ require "test/unit"
4
+ require "spec"
5
+
6
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
7
+
8
+ RAILS_ROOT = File.dirname(__FILE__)
9
+
10
+ if rails_version = ENV['RAILS_VERSION']
11
+ gem "rails", rails_version
12
+ end
13
+ require "rails/version"
14
+ puts "==== Testing with Rails #{Rails::VERSION::STRING} ===="
15
+ require 'active_record'
16
+ require 'active_record/fixtures'
17
+ require "action_controller"
18
+ require "action_controller/test_process"
19
+
20
+ require "unit_record"
21
+
22
+ # Needed because of this line in setup_with_fixtures and teardown_with_fixtures:
23
+ # return unless defined?(ActiveRecord::Base) && !ActiveRecord::Base.configurations.blank?
24
+ ActiveRecord::Base.configurations = {"irrelevant" => {:adapter => "stub"}}
25
+
26
+ ActiveRecord::Base.disconnect! :strategy => :raise, :stub_associations => true
27
+
28
+ describe UnitRecord do
29
+ it "disconnects tests from the database" do
30
+ lambda do
31
+ ActiveRecord::Base.connection.select_value("SELECT 1")
32
+ end.should raise_error
33
+ end
34
+
35
+ it "can change strategy to noop" do
36
+ ActiveRecord::Base.connection.change_strategy(:noop) do
37
+ ActiveRecord::Base.connection.select_value("SELECT 1").should == nil
38
+ end
39
+ end
40
+ end
data/test/test_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ unless defined?(TEST_HELPER_LOADED)
2
+ TEST_HELPER_LOADED = true
1
3
  $:.unshift(File.dirname(__FILE__) + '/../lib')
2
4
  RAILS_ROOT = File.dirname(__FILE__)
3
5
 
@@ -8,6 +10,7 @@ if rails_version = ENV['RAILS_VERSION']
8
10
  gem "rails", rails_version
9
11
  end
10
12
  require "rails/version"
13
+ puts "==== Testing with Rails #{Rails::VERSION::STRING} ===="
11
14
  require 'active_record'
12
15
  require 'active_record/fixtures'
13
16
  require "action_controller"
@@ -17,14 +20,17 @@ end
17
20
  require "action_controller/test_process"
18
21
 
19
22
  begin
23
+ gem "mocha"
20
24
  require 'mocha'
21
- require 'dust'
22
- rescue LoadError
23
- raise "Need Mocha and Dust gems to Test"
25
+ rescue LoadError, Gem::LoadError
26
+ raise "need mocha to test"
24
27
  end
28
+ $LOAD_PATH << File.dirname(__FILE__) + "/../vendor/dust-0.1.6/lib"
29
+ require 'dust'
25
30
  Test::Unit::TestCase.disallow_setup!
26
31
 
27
- require "#{File.dirname(__FILE__)}/../init"
32
+ $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
33
+ require "unit_record"
28
34
 
29
35
  Test::Unit::TestCase.use_transactional_fixtures = true
30
36
 
@@ -34,11 +40,29 @@ ActiveRecord::Base.configurations = {"irrelevant" => {:adapter => "stub"}}
34
40
 
35
41
  class Preference < ActiveRecord::Base
36
42
  end
43
+
37
44
  class Person < ActiveRecord::Base
45
+ has_many :pets
46
+ has_one :profile
47
+ end
48
+
49
+ class Profile < ActiveRecord::Base
50
+ belongs_to :person
51
+ end
52
+
53
+ class Pet < ActiveRecord::Base
54
+ belongs_to :person
38
55
  end
56
+
39
57
  class Foo < ActiveRecord::Base
40
58
  set_table_name :foofoo
41
59
  end
60
+
42
61
  class DoesNotExist < ActiveRecord::Base
43
62
  set_table_name "table_does_not_exist"
44
63
  end
64
+
65
+ ActiveRecord::Base.disconnect! :strategy => :raise, :stub_associations => true
66
+ # make sure calling disconnect multiple times does not cause problems
67
+ ActiveRecord::Base.disconnect! :strategy => :raise, :stub_associations => true
68
+ end
@@ -0,0 +1,37 @@
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
+
3
+ functional_tests do
4
+
5
+ test "stubbing a has_many" do
6
+ pets = [stub, stub]
7
+ person = Person.new :pets => pets
8
+ assert_equal pets, person.pets
9
+ end
10
+
11
+ test "stubbing a belongs_to" do
12
+ person = stub
13
+ pet = Pet.new :person => person
14
+ assert_equal person, pet.person
15
+ end
16
+
17
+ test "using correct classes does not stub" do
18
+ person = Person.new(:first_name => "Dan")
19
+ pet = Pet.new :person => person
20
+ pet.person = Person.new(:first_name => "Tom")
21
+ assert_equal "Tom", pet.person.first_name
22
+ end
23
+
24
+ test "using other than correct classes does stub" do
25
+ person = Object.new
26
+ def person.first_name; "Dan"; end
27
+ pet = Pet.new :person => person
28
+ pet.person = Person.new(:first_name => "Tom")
29
+ assert_equal "Dan", pet.person.first_name
30
+ end
31
+
32
+ test "multiple includes doesn't hurt" do
33
+ ActiveRecord::Base.send :include, UnitRecord::AssociationStubbing
34
+ Person.new
35
+ end
36
+
37
+ end
@@ -0,0 +1,26 @@
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
+
3
+ functional_tests do
4
+ test "caching columns with no defaults or not nulls" do
5
+ expected = [
6
+ ActiveRecord::ConnectionAdapters::Column.new("id", nil, "int(11) DEFAULT NULL auto_increment PRIMARY KEY", nil),
7
+ ActiveRecord::ConnectionAdapters::Column.new("first_name", nil, "varchar(255)", nil),
8
+ ActiveRecord::ConnectionAdapters::Column.new("last_name", nil, "varchar(255)", nil)
9
+ ]
10
+ expected[0].primary = true
11
+ expected[1..-1].each { |column| column.primary = false }
12
+ assert_equal expected, Person.columns
13
+ end
14
+
15
+ test "caching column with default" do
16
+ expected = ActiveRecord::ConnectionAdapters::Column.new("show_help", true, "tinyint(1)", nil)
17
+ expected.primary = false
18
+ assert_equal expected, Preference.columns.detect { |c| c.name == "show_help" }
19
+ end
20
+
21
+ test "boolean columns" do
22
+ expected = ActiveRecord::ConnectionAdapters::Column.new("show_help", true, "tinyint(1)", nil)
23
+ expected.primary = false
24
+ assert_equal :boolean, Preference.columns.detect { |c| c.name == "show_help" }.type
25
+ end
26
+ end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + "/unit_test_helper"
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
2
 
3
3
  unit_tests do
4
4
  test "equality" do
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + "/functional_test_helper"
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
2
 
3
3
  functional_tests do
4
4
  test "instantiating" do
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/functional_test_helper'
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
2
 
3
3
  class SampleController < ActionController::Base
4
4
  def sample_action
@@ -0,0 +1,52 @@
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
+
3
+ functional_tests do
4
+ test "find_by_sql gives disconnected exception message" do
5
+ exception = nil
6
+ begin
7
+ Person.find_by_sql "SELECT * FROM people"
8
+ rescue => exception
9
+ end
10
+ assert_not_nil exception
11
+ assert_equal "ActiveRecord is disconnected; database access is unavailable in unit tests.", exception.message
12
+ end
13
+
14
+ test "connected? is true" do
15
+ assert_equal true, ActiveRecord::Base.connected?
16
+ end
17
+
18
+ test "disconnected? is true" do
19
+ assert_equal true, ActiveRecord::Base.disconnected?
20
+ end
21
+
22
+ test "inspect does not blow up" do
23
+ assert_nothing_raised { Person.inspect }
24
+ end
25
+
26
+ test "table_exists?" do
27
+ assert_equal true, Person.table_exists?
28
+ if ActiveRecord::Base.connection.respond_to?(:table_exists?)
29
+ assert_equal false, ActiveRecord::Base.connection.table_exists?("bogus_table")
30
+ end
31
+ end
32
+
33
+ test "setting a has_one association" do
34
+ person = Person.new
35
+ person.profile = Profile.new
36
+ end
37
+
38
+ test "boolean columns do type casting" do
39
+ pref = Preference.new
40
+ pref.show_help = "0"
41
+ assert_equal false, pref.send(:read_attribute, :show_help)
42
+ assert_equal false, pref.show_help
43
+ assert_equal false, pref.show_help?
44
+ pref.show_help = "1"
45
+ assert_equal true, pref.show_help
46
+ assert_equal true, pref.show_help?
47
+ end
48
+
49
+ test "migrations are not verbose" do
50
+ assert_equal false, ActiveRecord::Migration.verbose
51
+ end
52
+ end