birdbath 1.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.bundle/config ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_DISABLE_SHARED_GEMS: "1"
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.swp
2
+ *.swo
3
+ Gemfile.lock
4
+ pkg/*
5
+ *.gem
6
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in birdbath.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 Micah Alles, Patrick Bacon, David Crosby
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,125 @@
1
+ = Birdbath
2
+
3
+ Birdbath provides methods which let you assert the current state of the schema and run your migrations against the _test_ database.
4
+
5
+ == Install
6
+
7
+ gem install birdbath
8
+
9
+ If you're using it outside of a Rails environment (for whatever reason) include the Birdbath module in your tests:
10
+
11
+ require 'test/unit'
12
+ require 'birdbath'
13
+
14
+ class MyTest < Test::Unit::TestCase
15
+ include Birdbath
16
+
17
+ def test_something
18
+ ...
19
+ end
20
+ end
21
+
22
+ == Use
23
+
24
+ *assert_schema*: verifies the schema of the database exactly matches the one specified.
25
+
26
+ def test_the_schema
27
+ assert_schema do |s|
28
+ s.table :books do |t|
29
+ t.column :id, :integer
30
+ t.column :title, :string, :limit => 5
31
+ t.column :author, :string
32
+ end
33
+
34
+ s.table :reviews do |t|
35
+ t.column :id, :integer
36
+ t.column :book_id, :integer
37
+ t.column :body, :text
38
+ t.column :rating, :integer, :default => 0
39
+ t.index :book_id, :name => 'index_book_id_on_reviews'
40
+ end
41
+ end
42
+ end
43
+
44
+ This would verify there are only two tables defined in the test database: _books_ and _reviews_ (schema_info is ignored). It will also verify that the _book_ table has the three columns, _id_, _title_ and _author_, each with their respective types. Indexes are verified too.
45
+
46
+
47
+ *assert_table*: verify a table is found exactly as specified:
48
+
49
+ assert_table :books do |t|
50
+ t.column :id, :integer
51
+ t.column :title, :string, :limit => 5
52
+ t.column :author, :string
53
+ t.index :author, :name => 'index_author_on_books'
54
+ end
55
+
56
+
57
+ *drop_all_tables*: does just what it says to your _test_ database.
58
+
59
+
60
+ *migrate*: executes the migrations against the test database using the same mechanism as rake db:migrate.
61
+
62
+ def test_the_migrations
63
+ migrate
64
+ migrate :version => 0
65
+ migrate :version => 10
66
+ migrate
67
+ end
68
+
69
+
70
+ This would do the same thing as running the following rake commands, but within a test case:
71
+
72
+ rake db:migrate
73
+ rake db:migrate VERSION=0
74
+ rake db:migrate VERSION=10
75
+ rake db:migrate
76
+
77
+
78
+ By combining the two helpers you can write a test that shows you can run all your migrations and get the final schema:
79
+
80
+ def test_should_be_able_to_migrate_from_an_empty_schema
81
+ drop_all_tables
82
+
83
+ # we shouldn't have any tables
84
+ assert_schema do |s|
85
+ end
86
+
87
+ migrate
88
+
89
+ assert_schema do |s|
90
+ s.table :books do |t|
91
+ t.column :id, :integer
92
+ t.column :title, :string
93
+ t.column :author, :string
94
+ end
95
+
96
+ s.table :reviews do |t|
97
+ t.column :id, :integer
98
+ t.column :book_id, :integer
99
+ t.column :body, :text
100
+ t.column :rating, :integer
101
+ t.index :book_id, :name => 'index_book_id_on_reviews'
102
+ end
103
+ end
104
+ end
105
+
106
+
107
+ The *migrate* helper can also be useful for testing data tranformation migrations:
108
+
109
+ def test_should_get_rid_of_bad_data
110
+ drop_all_tables
111
+ migrate :version => 7
112
+ Book.reset_column_information
113
+ book = Book.create! :title => "bad title\nwith\todd spacing"
114
+ migrate :version => 8 # should cleanse spacing in book titles
115
+ book.reload
116
+ assert_equal "bad title with odd spacing", book.title
117
+ end
118
+
119
+ == Authors
120
+
121
+ * Micah Alles (alles@atomicobject.com)
122
+ * David Crosby (crosby@atomicobject.com)
123
+ * Patrick Bacon (bacon@atomicobject.com)
124
+ * © 2007-2011 {Atomic Object}[http://www.atomicobject.com]
125
+ * More Atomic Object {open source}[http://www.atomicobject.com/pages/Software+Commons] projects
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ # GEM_VERSION = '1.3.3'
5
+ #
6
+ # Hoe.new('birdbath', GEM_VERSION) do |p|
7
+ # p.author = "Micah Alles"
8
+ # p.email = "micah@atomicobject.com"
9
+ # p.url = "http://migrationtest.rubyforge.org"
10
+ # p.summary = "A Rails plugin for testing migrations"
11
+ # p.description = <<-EOS
12
+ # birdbath makes testing your migrations easier by
13
+ # adding helper methods to Test::Unit::TestCase for asserting the
14
+ # current state of the schema and executing migrations against the
15
+ # test database.
16
+ # EOS
17
+ #
18
+ # end
19
+ #
data/birdbath.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "birdbath/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "birdbath"
7
+ s.version = Birdbath::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Micah Alles"]
10
+ s.email = ["micah@atomicobject.com"]
11
+ s.homepage = "http://github.com/atomicobject/birdbath"
12
+ s.summary = %q{A Rails gem for testing migrations}
13
+ s.description = <<-EOS
14
+ birdbath makes testing your migrations easier by
15
+ adding helper methods to Test::Unit::TestCase for asserting the
16
+ current state of the schema and executing migrations against the
17
+ test database.
18
+ EOS
19
+
20
+ s.rubyforge_project = "birdbath"
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.require_paths = ["lib"]
24
+ end
@@ -0,0 +1,30 @@
1
+ Description:
2
+ The controller generator creates stubs for a new controller and its views.
3
+
4
+ The generator takes a controller name and a list of views as arguments.
5
+ The controller name may be given in CamelCase or under_score and should
6
+ not be suffixed with 'Controller'. To create a controller within a
7
+ module, specify the controller name as 'module/controller'.
8
+
9
+ The generator creates a controller class in app/controllers with view
10
+ templates in app/views/controller_name, a helper class in app/helpers,
11
+ and a functional test suite in test/functional.
12
+
13
+ Example:
14
+ ./script/generate controller CreditCard open debit credit close
15
+
16
+ Credit card controller with URLs like /credit_card/debit.
17
+ Controller: app/controllers/credit_card_controller.rb
18
+ Views: app/views/credit_card/debit.rhtml [...]
19
+ Helper: app/helpers/credit_card_helper.rb
20
+ Test: test/functional/credit_card_controller_test.rb
21
+
22
+ Modules Example:
23
+ ./script/generate controller 'admin/credit_card' suspend late_fee
24
+
25
+ Credit card admin controller with URLs /admin/credit_card/suspend.
26
+ Controller: app/controllers/admin/credit_card_controller.rb
27
+ Views: app/views/admin/credit_card/debit.rhtml [...]
28
+ Helper: app/helpers/admin/credit_card_helper.rb
29
+ Test: test/functional/admin/credit_card_controller_test.rb
30
+
@@ -0,0 +1,10 @@
1
+ class FullMigrationTestGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+
5
+ m.directory 'test/migration'
6
+ m.template 'full_migration_test.rb',
7
+ 'test/migration/full_migration_test.rb'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,89 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ #
4
+ # This excercises the full set of migrations for your Rails app.
5
+ # It proves:
6
+ # - After full migration, the database is in the expected state, including:
7
+ # - All table structure
8
+ # - Default data (if any)
9
+ # - Full downward (version 0) migration functions correctly.
10
+ #
11
+ # YOU NEED TO:
12
+ # - Update "see_full_schema"
13
+ # - Update "see_data"
14
+ #
15
+ class FullMigrationTest < ActionController::IntegrationTest
16
+
17
+ #
18
+ # Transactional fixtures can, on occasion, cause migration tests to hang.
19
+ # Applying this setting here will turn transactional fixtures off for THIS
20
+ # SUITE ONLY
21
+ #
22
+ # self.use_transactional_fixtures = false
23
+
24
+ def conn
25
+ ActiveRecord::Base.connection
26
+ end
27
+
28
+ def see_empty_schema
29
+ assert_schema do |s|
30
+ # is nothing
31
+ end
32
+ end
33
+
34
+ #
35
+ # Structure and Content assertions
36
+ #
37
+
38
+ # Fully assert db structure after full migration
39
+ def see_full_schema
40
+ # TODO: add assertions here to verify your schema was built
41
+ flunk "implement me"
42
+
43
+ #
44
+ # Something like this can be used to see the entire schema
45
+ # is as expeted.
46
+ #
47
+ # assert_schema do |s|
48
+ # s.table :cat_tails do |t|
49
+ # t.column :id, :integer
50
+ # t.column :name, :string
51
+ # end
52
+ #
53
+ # s.table :dogs do |t|
54
+ # t.column :id, :integer
55
+ # t.column :name, :string
56
+ # end
57
+ # end
58
+
59
+ #
60
+ # Alternatively individual tables can be checked.
61
+ #
62
+ # assert_table :cats_tails do |s|
63
+ # t.column :id, :integer
64
+ # t.column :name, :string
65
+ # end
66
+ end
67
+
68
+ # Make sure data you expect your migrations to load are in there:
69
+ def see_default_data
70
+ # TODO: add assertions here to verify any default data was loaded
71
+ end
72
+
73
+ #
74
+ # TESTS
75
+ #
76
+
77
+ def test_full_migration
78
+ drop_all_tables
79
+
80
+ see_empty_schema
81
+
82
+ migrate
83
+
84
+ see_full_schema
85
+
86
+ see_default_data
87
+ end
88
+
89
+ end
@@ -0,0 +1,33 @@
1
+ class MigrationTestGenerator < Rails::Generator::NamedBase
2
+ def manifest
3
+ schema_version = class_name.to_i
4
+ raise "Invalid schema version '#{class_name}'" unless schema_version > 0
5
+
6
+ schema_version_string = schema_version.to_s.rjust(3,'0')
7
+
8
+ migration = Dir["db/migrate/#{schema_version_string}*.rb"].first
9
+ raise "No migration found for schema version #{schema_version_string}" unless migration
10
+
11
+ migration_name = File.basename(migration,'.rb').sub(/^\d+_/,'')
12
+ test_class_name = migration_name.camelize + "Test"
13
+ test_file = "test/migration/#{schema_version_string}_#{migration_name}_test.rb"
14
+
15
+ record do |m|
16
+ m.directory 'test/migration'
17
+ m.template 'migration_test.rb', test_file, :assigns => {
18
+ :test_class_name => test_class_name,
19
+ :migration_name => migration_name,
20
+ :schema_version => schema_version,
21
+ :previous_schema_version => previous_schema_version(schema_version_string)
22
+ }
23
+ end
24
+ end
25
+
26
+ def previous_schema_version(current_version_string)
27
+ versions = Dir["db/migrate/*.rb"].map do |migration_file|
28
+ migration_file.match(/db\/migrate\/(\d+)_.*\.rb/)[1]
29
+ end.sort
30
+ prev_index = versions.index(current_version_string) - 1
31
+ prev_index < 0 ? -1 : versions[prev_index].to_i
32
+ end
33
+ end
@@ -0,0 +1,25 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class <%= test_class_name %> < Test::Unit::TestCase
4
+
5
+ def teardown
6
+ migrate
7
+ end
8
+
9
+ def test_migration_should_<%= migration_name %>
10
+ drop_all_tables
11
+
12
+ migrate :version => <%= previous_schema_version %>
13
+
14
+ flunk "TODO: setup test data"
15
+
16
+ migrate :version => <%= schema_version %>
17
+
18
+ flunk "TODO: examine results"
19
+
20
+ migrate :version => <%= previous_schema_version %>
21
+
22
+ flunk "TODO: examine results"
23
+ end
24
+
25
+ end
data/init.rb ADDED
@@ -0,0 +1,7 @@
1
+ if RAILS_ENV == 'test'
2
+ require 'birdbath'
3
+ require 'test/unit'
4
+ Test::Unit::TestCase.class_eval do
5
+ include Birdbath
6
+ end
7
+ end
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,3 @@
1
+ module Birdbath
2
+ VERSION = "1.3.4"
3
+ end
data/lib/birdbath.rb ADDED
@@ -0,0 +1,159 @@
1
+ #--
2
+ # Copyright (c) 2007 Micah Alles, Patrick Bacon, David Crosby
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ require 'test/unit/assertions'
25
+
26
+ module Birdbath
27
+ def self.migration_dir
28
+ @migration_dir || File.expand_path(RAILS_ROOT + '/db/migrate')
29
+ end
30
+
31
+ #
32
+ # sets the directory in which the migrations reside to be run with migrate
33
+ #
34
+ def self.migration_dir=(new_dir)
35
+ @migration_dir = new_dir
36
+ end
37
+
38
+ #
39
+ # verifies the schema exactly matches the one specified (schema_info does not have to be specified)
40
+ #
41
+ # assert_schema do |s|
42
+ # s.table :dogs do |t|
43
+ # t.column :id, :integer, :default => 2
44
+ # t.column :name, :string
45
+ # end
46
+ # end
47
+ #
48
+ def assert_schema
49
+ schema = Schema.new
50
+ yield schema
51
+ schema.verify
52
+ end
53
+
54
+ #
55
+ # verifies a single table exactly matches the one specified
56
+ #
57
+ # assert_table :dogs do |t|
58
+ # t.column :id, :integer, :default => 2
59
+ # t.column :name, :string
60
+ # end
61
+ #
62
+ def assert_table(name)
63
+ table = Table.new(name)
64
+ yield table
65
+ table.verify
66
+ end
67
+
68
+ #
69
+ # drops all tables in the database
70
+ #
71
+ def drop_all_tables
72
+ ActiveRecord::Base.connection.tables.each do |table|
73
+ ActiveRecord::Base.connection.drop_table(table)
74
+ end
75
+ end
76
+
77
+ #
78
+ # executes your migrations
79
+ #
80
+ # migrate # same as rake db:migrate
81
+ #
82
+ # Options are:
83
+ # * :version - version to migrate to (same as VERSION=.. option to rake db:migrate)
84
+ # * :verbose - print migration status messages to STDOUT, defaults to false
85
+ #
86
+ def migrate(opts={})
87
+ old_verbose = ActiveRecord::Migration.verbose
88
+ ActiveRecord::Migration.verbose = opts[:verbose].nil? ? false : opts[:verbose]
89
+ version = opts[:version] ? opts[:version].to_i : nil
90
+ ActiveRecord::Migrator.migrate(Birdbath.migration_dir, version)
91
+ ensure
92
+ ActiveRecord::Migration.verbose = old_verbose
93
+ end
94
+
95
+ module Connection #:nodoc:
96
+ def conn
97
+ ActiveRecord::Base.connection
98
+ end
99
+ end
100
+
101
+ class Schema
102
+ include Connection
103
+ include Test::Unit::Assertions
104
+
105
+ def initialize #:nodoc:
106
+ @tables = []
107
+ end
108
+
109
+ def table(name)
110
+ table = Table.new(name)
111
+ yield table
112
+ table.verify
113
+ @tables << table
114
+ end
115
+
116
+ def verify #:nodoc:
117
+ actual_tables = conn.tables.reject {|t| t == 'schema_info' || t == 'schema_migrations' }
118
+ expected_tables = @tables.map {|t| t.name }
119
+ assert_equal expected_tables.sort, actual_tables.sort, 'wrong tables in schema'
120
+ end
121
+ end
122
+
123
+ class Table
124
+ include Connection
125
+ include Test::Unit::Assertions
126
+ attr_reader :name
127
+
128
+ def initialize(name) #:nodoc:
129
+ @name = name.to_s
130
+ @columns = []
131
+ @indexes = []
132
+ assert conn.tables.include?(@name), "table <#{@name}> not found in schema"
133
+ end
134
+
135
+ def column(colname,type,options={})
136
+ colname = colname.to_s
137
+ @columns << colname
138
+ col = conn.columns(name).find {|c| c.name == colname }
139
+ assert_not_nil col, "column <#{colname}> not found in table <#{self.name}>"
140
+ assert_equal type, col.type, "wrong type for column <#{colname}> in table <#{name}>"
141
+ options.each do |k,v|
142
+ k = k.to_sym; actual = col.send(k); actual = actual.is_a?(String) ? actual.sub(/'$/,'').sub(/^'/,'') : actual
143
+ assert_equal v, actual, "column <#{colname}> in table <#{name}> has wrong :#{k}"
144
+ end
145
+ end
146
+
147
+ def index(column_name, options = {})
148
+ @indexes << "name <#{options[:name]}> columns <#{Array(column_name).join(",")}> unique <#{options[:unique] == true}>"
149
+ end
150
+
151
+ def verify #:nodoc:
152
+ actual_columns = conn.columns(name).map {|c| c.name }
153
+ assert_equal @columns.sort, actual_columns.sort, "wrong columns for table: <#{name}>"
154
+
155
+ actual_indexes = conn.indexes(@name).collect { |i| "name <#{i.name}> columns <#{i.columns.join(",")}> unique <#{i.unique}>" }
156
+ assert_equal @indexes.sort, actual_indexes.sort, "wrong indexes for table: <#{name}>"
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,17 @@
1
+
2
+ namespace :test do
3
+
4
+ Rake::TestTask.new(:migrations => "db:test:prepare") do |t|
5
+ t.libs << "test"
6
+ t.pattern = 'test/migration/**/*_test.rb'
7
+ t.verbose = true
8
+ end
9
+ Rake::Task['test:migrations'].comment = "Run the migration tests in test/migration"
10
+
11
+ task :migration => 'test:migrations'
12
+ end
13
+
14
+ task :test do
15
+ Rake::Task['test:migrations'].invoke rescue got_error = true
16
+ raise "Test failures" if got_error
17
+ end
@@ -0,0 +1,263 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+
3
+ class BirdbathTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ load_default_schema
7
+ Birdbath.migration_dir = plugin_path('test/db/migrate_good')
8
+ end
9
+
10
+ #
11
+ # HELPERS
12
+ #
13
+ def see_failure(pattern='')
14
+ err = assert_raise(Test::Unit::AssertionFailedError) do
15
+ yield
16
+ end
17
+ assert_match(/#{pattern}/mi, err.message)
18
+ end
19
+
20
+ def see_no_failure
21
+ assert_nothing_raised do
22
+ yield
23
+ end
24
+ end
25
+
26
+ def declare_columns_on_table(t)
27
+ t.column :id, :integer
28
+ t.column :tail, :string, :default => 'top dog', :limit => 187
29
+ end
30
+
31
+ #
32
+ # TESTS
33
+ #
34
+ def test_assert_schema_should_not_fail_if_schema_is_matched
35
+ see_no_failure do
36
+ assert_schema do |s|
37
+ s.table :dogs do |t|
38
+ declare_columns_on_table(t)
39
+ t.index :tail, :name => 'index_tail_on_dogs'
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+
46
+ def test_assert_schema_should_fail_if_a_table_is_not_specified
47
+ see_failure 'wrong tables in schema.*dogs' do
48
+ assert_schema do |s|
49
+ end
50
+ end
51
+ end
52
+
53
+ def test_assert_schema_should_fail_if_a_table_is_not_found
54
+ see_failure 'table <things> not found in schema' do
55
+ assert_schema do |s|
56
+ s.table :things do |t|
57
+ t.column :id, :integer
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ def test_assert_schema_should_fail_if_a_column_is_not_specified
64
+ see_failure 'wrong columns for table.*dogs.*tail' do
65
+ assert_schema do |s|
66
+ s.table :dogs do |t|
67
+ t.column :id, :integer
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ def test_assert_schema_should_fail_if_a_column_is_not_found
74
+ see_failure 'column <legs> not found in table <dogs>' do
75
+ assert_schema do |s|
76
+ s.table :dogs do |t|
77
+ t.column :id, :integer
78
+ t.column :tail, :string
79
+ t.column :legs, :integer
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ def test_assert_schema_should_fail_if_wrong_options_not_specified
86
+ see_failure 'column <tail> in table <dogs> has wrong :default' do
87
+ assert_table :dogs do |t|
88
+ t.column :id, :integer
89
+ t.column :tail, :string, :default => "blah"
90
+ end
91
+ end
92
+ end
93
+
94
+ def test_assert_table_should_not_fail_if_table_is_matched
95
+ see_no_failure do
96
+ assert_table :dogs do |t|
97
+ declare_columns_on_table(t)
98
+ t.index :tail, :name => 'index_tail_on_dogs'
99
+ end
100
+ end
101
+ end
102
+
103
+ def test_assert_table_should_fail_if_a_table_is_not_found
104
+ see_failure 'table <things> not found in schema' do
105
+ assert_table :things do |t|
106
+ t.column :id, :integer
107
+ end
108
+ end
109
+ end
110
+
111
+ def test_assert_table_should_fail_if_a_column_is_not_specified
112
+ see_failure 'wrong columns for table.*dogs.*tail' do
113
+ assert_table :dogs do |t|
114
+ t.column :id, :integer
115
+ end
116
+ end
117
+ end
118
+
119
+ def test_assert_table_should_fail_if_a_column_is_not_found
120
+ see_failure 'column <legs> not found in table <dogs>' do
121
+ assert_table :dogs do |t|
122
+ t.column :id, :integer
123
+ t.column :tail, :string
124
+ t.column :legs, :integer
125
+ end
126
+ end
127
+ end
128
+
129
+ def test_assert_table_should_fail_if_wrong_options_not_specified
130
+ see_failure 'column <tail> in table <dogs> has wrong :default' do
131
+ assert_table :dogs do |t|
132
+ t.column :id, :integer
133
+ t.column :tail, :string, :default => "blah"
134
+ end
135
+ end
136
+ end
137
+
138
+ def test_assert_table_should_fail_if_an_index_is_not_specified
139
+ see_failure 'wrong indexes for table: <dogs>' do
140
+ assert_table :dogs do |t|
141
+ declare_columns_on_table(t)
142
+ end
143
+ end
144
+ end
145
+
146
+ def test_assert_schema_should_fail_if_a_column_in_an_index_is_not_found
147
+ see_failure 'wrong indexes for table: <dogs>' do
148
+ assert_table :dogs do |t|
149
+ declare_columns_on_table(t)
150
+ t.index :legs, :name => 'index_legs_on_dogs'
151
+ end
152
+ end
153
+ end
154
+
155
+ def test_assert_schema_should_fail_if_wrong_options_on_an_index
156
+ see_failure 'wrong indexes for table: <dogs>' do
157
+ assert_table :dogs do |t|
158
+ declare_columns_on_table(t)
159
+ t.index :tail, :name => 'index_tail_on_dogs', :unique => true
160
+ end
161
+ end
162
+ end
163
+
164
+ def test_should_drop_all_tables
165
+ if Rails::VERSION::MAJOR >= 2 && Rails::VERSION::MINOR >= 1
166
+ schema_table = 'schema_migrations'
167
+ else
168
+ schema_table = 'schema_info'
169
+ end
170
+ assert_equal ['dogs', schema_table].sort, ActiveRecord::Base.connection.tables.sort
171
+ drop_all_tables
172
+ assert_equal [], ActiveRecord::Base.connection.tables
173
+ drop_all_tables
174
+ assert_equal [], ActiveRecord::Base.connection.tables
175
+ end
176
+
177
+ def test_should_migrate_to_highest_version
178
+ drop_all_tables
179
+ assert_schema do |s|
180
+ end
181
+
182
+ migrate :version => 1
183
+
184
+ assert_schema do |s|
185
+ s.table :top_dogs do |t|
186
+ t.column :id, :integer
187
+ t.column :name, :string
188
+ end
189
+ end
190
+
191
+ migrate :version => 2
192
+
193
+ assert_schema do |s|
194
+ s.table :top_dogs do |t|
195
+ t.column :id, :integer
196
+ t.column :name, :string
197
+ end
198
+ s.table :bottom_dogs do |t|
199
+ t.column :id, :integer
200
+ t.column :name, :string
201
+ t.column :sick, :boolean
202
+ end
203
+ end
204
+
205
+ migrate :version => 3
206
+
207
+ assert_schema do |s|
208
+ s.table :top_dogs do |t|
209
+ t.column :id, :integer
210
+ t.column :name, :string
211
+ end
212
+ s.table :bottom_dogs do |t|
213
+ t.column :id, :integer
214
+ t.column :name, :string
215
+ t.column :sick, :boolean
216
+ end
217
+ s.table :cats do |t|
218
+ t.column :id, :integer
219
+ t.column :lives, :integer
220
+ end
221
+ end
222
+
223
+ migrate :version => 0
224
+
225
+ assert_schema do |s|
226
+ end
227
+
228
+ migrate
229
+
230
+ assert_schema do |s|
231
+ s.table :top_dogs do |t|
232
+ t.column :id, :integer
233
+ t.column :name, :string
234
+ end
235
+ s.table :bottom_dogs do |t|
236
+ t.column :id, :integer
237
+ t.column :name, :string
238
+ t.column :sick, :boolean
239
+ end
240
+ s.table :cats do |t|
241
+ t.column :id, :integer
242
+ t.column :lives, :integer
243
+ end
244
+ end
245
+ end
246
+
247
+ def test_should_have_default_migration_dir_set
248
+ Birdbath.migration_dir = nil
249
+ assert_equal File.expand_path(RAILS_ROOT + '/db/migrate'), Birdbath.migration_dir,
250
+ "wrong default migration dir"
251
+
252
+ end
253
+
254
+ def test_should_raise_error_if_migration_fails
255
+ Birdbath.migration_dir = plugin_path('test/db/migrate_bad')
256
+ drop_all_tables
257
+ err = assert_raise RuntimeError do
258
+ migrate
259
+ end
260
+ assert_match(//i, err.message)
261
+ end
262
+ end
263
+
@@ -0,0 +1,3 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: vendor/plugins/birdbath/test/db/test.sqlite3.db
@@ -0,0 +1,8 @@
1
+ class CreateTopDogs < ActiveRecord::Migration
2
+ def self.up
3
+ raise 'boom'
4
+ end
5
+
6
+ def self.down
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ class CreateTopDogs < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :top_dogs do |t|
4
+ t.column :name, :string
5
+ end
6
+ end
7
+
8
+ def self.down
9
+ drop_table :top_dogs
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ class CreateBottomDogs < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :bottom_dogs do |t|
4
+ t.column :name, :string
5
+ t.column :sick, :boolean
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ drop_table :bottom_dogs
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ class CreateCats < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :cats do |t|
4
+ t.column :lives, :integer
5
+ end
6
+ end
7
+
8
+ def self.down
9
+ drop_table :cats
10
+ end
11
+ end
data/test/db/schema.rb ADDED
@@ -0,0 +1,6 @@
1
+ ActiveRecord::Schema.define(:version => 1) do
2
+ create_table "dogs", :force => true do |t|
3
+ t.column "tail", :string, :default => 'top dog', :limit => 187
4
+ end
5
+ add_index :dogs, :tail, :name => 'index_tail_on_dogs'
6
+ end
@@ -0,0 +1,15 @@
1
+ class Test::Unit::TestCase
2
+
3
+ def self.running_in_foundry
4
+ File.expand_path(File.dirname(__FILE__)) =~ /\/rails_plugin_foundry\//
5
+ end
6
+
7
+ def running_in_foundry
8
+ self.class.running_in_foundry
9
+ end
10
+
11
+ def self.in_foundry_should(behave,&block)
12
+ should(behave,&block) if running_in_foundry
13
+ end
14
+
15
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/foundry_only_helper')
3
+
4
+ class FullMigrationTestGeneratorTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ return unless running_in_foundry
8
+ rm_migration_test_path
9
+ end
10
+
11
+ def teardown
12
+ return unless running_in_foundry
13
+ rm_migration_test_path
14
+ end
15
+
16
+
17
+ #
18
+ # HELPERS
19
+ #
20
+
21
+ def migration_test_file
22
+ migration_test_path + "/full_migration_test.rb"
23
+ end
24
+
25
+ def run_generator
26
+ run_in_rails_root 'script/generate full_migration_test'
27
+ end
28
+
29
+ #
30
+ # TESTS
31
+ #
32
+
33
+ in_foundry_should "generate full migration test" do
34
+ run_generator
35
+ assert File.exists?(migration_test_file), "No test file made: #{migration_test_file}"
36
+ generated_code = File.read(migration_test_file)
37
+ source_code = File.read(plugin_path('generators/full_migration_test/templates/full_migration_test.rb'))
38
+ assert_equal source_code, generated_code, "Wrong code generated in #{migration_test_file}"
39
+ end
40
+
41
+ in_foundry_should "create a test that fails in expected fashion" do
42
+ run_generator
43
+ cd RAILS_ROOT do
44
+ @output = `ruby test/migration/full_migration_test.rb`
45
+ end
46
+
47
+ check_output '1 tests, 1 assertions, 1 failures, 0 errors'
48
+ check_output 'implement me'
49
+ check_output 'test_full_migration(FullMigrationTest)'
50
+ end
51
+
52
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,75 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../../../config/environment')
3
+ require 'logger'
4
+ require 'fileutils'
5
+ require 'test_help'
6
+
7
+ plugin_path = RAILS_ROOT + "/vendor/plugins/birdbath"
8
+
9
+ config_location = File.expand_path(plugin_path + "/test/config/database.yml")
10
+
11
+ config = YAML::load(ERB.new(IO.read(config_location)).result)
12
+ ActiveRecord::Base.logger = Logger.new(plugin_path + "/test/log/test.log")
13
+ ActiveRecord::Base.establish_connection(config['test'])
14
+
15
+ Test::Unit::TestCase.fixture_path = plugin_path + "/test/fixtures/"
16
+
17
+ $LOAD_PATH.unshift(Test::Unit::TestCase.fixture_path)
18
+
19
+ class Test::Unit::TestCase
20
+ include FileUtils
21
+ def plugin_path(path)
22
+ File.expand_path(File.dirname(__FILE__) + '/../' + path)
23
+ end
24
+
25
+ def load_default_schema
26
+ ActiveRecord::Migration.suppress_messages do
27
+ schema_file = plugin_path("/test/db/schema.rb")
28
+ load(schema_file) if File.exist?(schema_file)
29
+ end
30
+ end
31
+
32
+ def migration_test_path
33
+ File.expand_path(RAILS_ROOT + "/test/migration")
34
+ end
35
+
36
+ def run_in_rails_root(command)
37
+ cd RAILS_ROOT do
38
+ @output = `#{command}`
39
+ end
40
+ end
41
+
42
+ def check_output(string_or_regexp)
43
+ assert_not_nil @output, "No output collected"
44
+ case string_or_regexp
45
+ when String
46
+ assert_match(/#{Regexp.escape(string_or_regexp)}/, @output)
47
+ when Regexp
48
+ assert_match(string_or_regexp, @output)
49
+ else
50
+ raise "Can't check output using oddball object #{string_or_regexp.inspect}"
51
+ end
52
+ end
53
+
54
+ def rm_migration_test_path
55
+ rm_rf migration_test_path
56
+ end
57
+
58
+ def self.should(behave,&block)
59
+ return unless running_in_foundry
60
+ @context ||= nil
61
+ @context_setup ||= nil
62
+ context_string = @context.nil? ? '' : @context + ' '
63
+ mname = "test #{context_string}should #{behave}"
64
+ context_setup = @context_setup
65
+ if block_given?
66
+ define_method(mname) do
67
+ instance_eval(&context_setup) unless context_setup.nil?
68
+ instance_eval(&block)
69
+ end
70
+ else
71
+ puts ">>> UNIMPLEMENTED CASE: #{name.sub(/Test$/,'')} should #{behave}"
72
+ end
73
+ end
74
+
75
+ end
@@ -0,0 +1,91 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/foundry_only_helper')
3
+
4
+ class MigrationTestGeneratorTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ return unless running_in_foundry
8
+ rm_migration_test_path
9
+ rm_migrations
10
+ end
11
+
12
+ def teardown
13
+ return unless running_in_foundry
14
+ rm_migration_test_path
15
+ rm_migrations
16
+ end
17
+
18
+
19
+ #
20
+ # HELPERS
21
+ #
22
+
23
+ def generate_migration(name)
24
+ run_in_rails_root "script/generate migration #{name}"
25
+ @output =~ /create db\/migrate\/(\d+)_.*\.rb/
26
+ migration = $1
27
+ migration_file = "db/migrate/#{migration}_#{name}.rb"
28
+ assert File.exists?(migration_file), "Migration not there: #{migration_file}"
29
+ migration
30
+ end
31
+
32
+ def generate_migration_test(version)
33
+ run_in_rails_root "script/generate migration_test #{version}"
34
+ end
35
+
36
+ def rm_migrations
37
+ rm Dir["db/migrate/*.rb"]
38
+ end
39
+
40
+ #
41
+ # TESTS
42
+ #
43
+
44
+ in_foundry_should "generate a migration test for schema 1" do
45
+ migration = generate_migration 'create_the_dogs_table'
46
+
47
+ generate_migration_test migration
48
+
49
+ migration_test_file = "test/migration/#{migration}_create_the_dogs_table_test.rb"
50
+ assert File.exists?(migration_test_file), "Migration test not there: #{migration_test_file}"
51
+
52
+ run_in_rails_root "ruby #{migration_test_file}"
53
+ check_output 'test_migration_should_create_the_dogs_table(CreateTheDogsTableTest)'
54
+ check_output '1) Failure:'
55
+ check_output 'TODO: setup test data.'
56
+ check_output '1 tests, 1 assertions, 1 failures, 0 errors'
57
+ end
58
+
59
+ in_foundry_should "generate a migration test for schema 2" do
60
+ generate_migration 'create_the_dogs_table'
61
+ migration = generate_migration 'transfer_cats_data'
62
+ generate_migration_test migration
63
+ migration_test_file = "test/migration/#{migration}_transfer_cats_data_test.rb"
64
+ assert File.exists?(migration_test_file), "Migration test not there: #{migration_test_file}"
65
+
66
+ run_in_rails_root "ruby #{migration_test_file}"
67
+ check_output 'test_migration_should_transfer_cats_data(TransferCatsDataTest)'
68
+ check_output '1) Failure:'
69
+ check_output 'TODO: setup test data.'
70
+ check_output '1 tests, 1 assertions, 1 failures, 0 errors'
71
+ end
72
+
73
+ in_foundry_should "fail if no schema version is provided" do
74
+ generate_migration 'create_the_dogs_table'
75
+ generate_migration_test ''
76
+ check_output 'Usage: script/generate migration_test MigrationTestName [options]'
77
+ end
78
+
79
+ in_foundry_should "fail if bad schema version is provided" do
80
+ generate_migration 'create_the_dogs_table'
81
+ generate_migration_test 'oops'
82
+ check_output(/Invalid schema version 'oops'/i)
83
+ end
84
+
85
+ in_foundry_should "fail if schema version does not correspond to existing migration" do
86
+ migration = generate_migration 'create_the_dogs_table'
87
+ generate_migration_test '2'
88
+ check_output "No migration found for schema version 002"
89
+ end
90
+
91
+ end
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: birdbath
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Micah Alles
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-08-09 00:00:00.000000000 -04:00
13
+ default_executable:
14
+ dependencies: []
15
+ description: ! "birdbath makes testing your migrations easier by \nadding helper methods
16
+ to Test::Unit::TestCase for asserting the \ncurrent state of the schema and executing
17
+ migrations against the \ntest database.\n"
18
+ email:
19
+ - micah@atomicobject.com
20
+ executables: []
21
+ extensions: []
22
+ extra_rdoc_files: []
23
+ files:
24
+ - .bundle/config
25
+ - .gitignore
26
+ - Gemfile
27
+ - LICENSE
28
+ - README.rdoc
29
+ - Rakefile
30
+ - birdbath.gemspec
31
+ - generators/full_migration_test/USAGE
32
+ - generators/full_migration_test/full_migration_test_generator.rb
33
+ - generators/full_migration_test/templates/full_migration_test.rb
34
+ - generators/migration_test/migration_test_generator.rb
35
+ - generators/migration_test/templates/migration_test.rb
36
+ - init.rb
37
+ - install.rb
38
+ - lib/birdbath.rb
39
+ - lib/birdbath/version.rb
40
+ - tasks/birdbath_tasks.rake
41
+ - test/birdbath_test.rb
42
+ - test/config/database.yml
43
+ - test/db/migrate_bad/001_create_top_dogs.rb
44
+ - test/db/migrate_good/001_create_top_dogs.rb
45
+ - test/db/migrate_good/002_create_bottom_dogs.rb
46
+ - test/db/migrate_good/003_create_cats.rb
47
+ - test/db/schema.rb
48
+ - test/foundry_only_helper.rb
49
+ - test/full_migration_test_generator_test.rb
50
+ - test/helper.rb
51
+ - test/migration_test_generator_test.rb
52
+ - uninstall.rb
53
+ has_rdoc: true
54
+ homepage: http://github.com/atomicobject/birdbath
55
+ licenses: []
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubyforge_project: birdbath
74
+ rubygems_version: 1.6.2
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: A Rails gem for testing migrations
78
+ test_files: []