minitest-sequel 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,10 +1,31 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
1
+ OSX = RUBY_PLATFORM.match(/darwin/)
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
3
5
 
4
6
  Rake::TestTask.new(:spec) do |t|
5
- t.libs << "spec"
6
- t.libs << "lib"
7
+ t.libs << 'spec'
8
+ t.libs << 'lib'
7
9
  t.test_files = FileList['spec/**/*_spec.rb']
8
10
  end
9
11
 
10
12
  task :default => :spec
13
+
14
+ desc "Run specs with coverage"
15
+ task :coverage do
16
+ ENV['COVERAGE'] = '1'
17
+ Rake::Task['spec'].invoke
18
+ `open coverage/index.html` if OSX
19
+ end
20
+
21
+
22
+ desc 'Run Rubocop report'
23
+ task :rubocop do
24
+ res = `which rubocop`
25
+ if res != ""
26
+ `rubocop -f html -o ./rubocop/report.html lib/`
27
+ `open rubocop/report.html` if OSX
28
+ else
29
+ puts "\nERROR: 'rubocop' gem is not installed or available. Please install with 'gem install rubocop'."
30
+ end
31
+ end
@@ -0,0 +1,183 @@
1
+ require 'minitest/sequel'
2
+
3
+ # reopening to add association functionality
4
+ module Minitest::Assertions
5
+
6
+ # Test for a :one_to_one association for the current model
7
+ #
8
+ # let(:m) { Post.first }
9
+ #
10
+ # it { assert_association_one_to_one(m, :first_comment, { class: :Comment, order: :id }) }
11
+ # it { m.must_have_one_to_one_association(:first_comment, { class: :Comment, order: :id }) }
12
+ #
13
+ def assert_association_one_to_one(obj, attribute, opts = {}, msg = nil)
14
+ assert_association(obj.class, :one_to_one, attribute, opts, msg)
15
+ end
16
+
17
+ # Test for a :one_to_many association for the current model
18
+ #
19
+ # let(:m) { Post.first }
20
+ #
21
+ # it { assert_association_one_to_many(m, :comments) }
22
+ # it { m.must_have_one_to_many_association(:comments) }
23
+ #
24
+ def assert_association_one_to_many(obj, attribute, opts = {}, msg = nil)
25
+ assert_association(obj.class, :one_to_many, attribute, opts, msg)
26
+ end
27
+
28
+ # Test for a :many_to_one association for the current model
29
+ #
30
+ # let(:m) { Post.first }
31
+ #
32
+ # it { assert_association_many_to_one(m, :author) }
33
+ # it { m.must_have_many_to_one_association(:author) }
34
+ #
35
+ def assert_association_many_to_one(obj, attribute, opts = {}, msg = nil)
36
+ assert_association(obj.class, :many_to_one, attribute, opts, msg)
37
+ end
38
+
39
+ # Test for a :many_to_many association for the current model
40
+ #
41
+ # let(:m) { Post.first }
42
+ #
43
+ # it { assert_association_many_to_many(m, :tags) }
44
+ # it { m.must_have_many_to_many_association(:tags) }
45
+ #
46
+ def assert_association_many_to_many(obj, attribute, opts = {}, msg = nil)
47
+ assert_association(obj.class, :many_to_many, attribute, opts, msg)
48
+ end
49
+
50
+ # Test for associations for the current model by passing the :association_type
51
+ #
52
+ # it { assert_association(Post, :many_to_many, :tags) }
53
+ #
54
+ def assert_association(klass, association_type, attribute, opts = {}, msg = nil)
55
+ msg = msg.nil? ? '' : "#{msg}\n"
56
+ msg << "Expected #{klass.inspect} to have a #{association_type.inspect}"
57
+ msg << " association #{attribute.inspect}"
58
+ assoc = klass.association_reflection(attribute) || {}
59
+ if assoc.empty?
60
+ msg << " but no association '#{attribute.inspect}' was found"
61
+ arr = []
62
+ klass.associations.each do |a|
63
+ o = klass.association_reflection(a)
64
+ if o[:type] == :many_to_many
65
+ arr << {
66
+ attribute: o[:name],
67
+ type: o[:type],
68
+ class: o[:class_name].to_sym,
69
+ join_table: o[:join_table],
70
+ left_keys: o[:left_keys],
71
+ right_keys: o[:right_keys]
72
+ }
73
+ else
74
+ arr << {
75
+ attribute: o[:name],
76
+ type: o[:type],
77
+ class: o[:class_name].to_sym,
78
+ keys: o[:keys]
79
+ }
80
+ end
81
+ end
82
+ msg << " - \navailable associations are: [ #{arr.join(', ')} ]\n"
83
+ assert(false, msg)
84
+ else
85
+ matching = assoc[:type] == association_type
86
+ err_msg = []
87
+ conf_msg = []
88
+ opts.each do |key, value|
89
+ conf_msg << { key => value }
90
+ if assoc[key] != value
91
+ err_msg << { key => assoc[key] }
92
+ matching = false
93
+ end
94
+ end
95
+ msg << " with given options: #{conf_msg.join(', ')} but should be #{err_msg.join(', ')}"
96
+ assert(matching, msg)
97
+ end
98
+ end
99
+
100
+
101
+ # Test to ensure there is no :one_to_one association for the current model
102
+ #
103
+ # let(:m) { Post.first }
104
+ #
105
+ # it { refute_association_one_to_one(m, :first_comment, { class: :Comment, order: :id }) }
106
+ # it { m.must_have_one_to_one_association(:first_comment, { class: :Comment, order: :id }) }
107
+ #
108
+ def refute_association_one_to_one(obj, attribute, opts = {}, msg = nil)
109
+ refute_association(obj.class, :one_to_one, attribute, opts, msg)
110
+ end
111
+
112
+ # Test to ensure there is no :one_to_many association for the current model
113
+ #
114
+ # let(:m) { Post.first }
115
+ #
116
+ # it { refute_association_one_to_many(m, :comments) }
117
+ # it { m.must_have_one_to_many_association(:comments) }
118
+ #
119
+ def refute_association_one_to_many(obj, attribute, opts = {}, msg = nil)
120
+ refute_association(obj.class, :one_to_many, attribute, opts, msg)
121
+ end
122
+
123
+ # Test to ensure there is no :many_to_one association for the current model
124
+ #
125
+ # let(:m) { Post.first }
126
+ #
127
+ # it { refute_association_many_to_one(m, :author) }
128
+ # it { m.must_have_many_to_one_association(:author) }
129
+ #
130
+ def refute_association_many_to_one(obj, attribute, opts = {}, msg = nil)
131
+ refute_association(obj.class, :many_to_one, attribute, opts, msg)
132
+ end
133
+
134
+ # Test to ensure there is no :many_to_many association for the current model
135
+ #
136
+ # let(:m) { Post.first }
137
+ #
138
+ # it { refute_association_many_to_many(m, :tags) }
139
+ # it { m.must_have_many_to_many_association(:tags) }
140
+ #
141
+ def refute_association_many_to_many(obj, attribute, opts = {}, msg = nil)
142
+ refute_association(obj.class, :many_to_many, attribute, opts, msg)
143
+ end
144
+
145
+ # Test to ensure the current model does NOT have an association by type :association_type
146
+ #
147
+ # it { refute_association(Post, :many_to_many, :tags) }
148
+ #
149
+ def refute_association(klass, association_type, attribute, opts = {}, msg = nil)
150
+ msg = msg.nil? ? '' : "#{msg}\n"
151
+ msg << "Expected #{klass.inspect} to NOT have a #{association_type.inspect}"
152
+ msg << " association #{attribute.inspect}"
153
+ assoc = klass.association_reflection(attribute) || {}
154
+
155
+ if assoc.empty?
156
+ assert(true, msg)
157
+ else
158
+ matching = false if assoc[:type] == association_type
159
+ msg << ", but such an association was found"
160
+ assert(matching, msg)
161
+ end
162
+
163
+ end
164
+
165
+ end
166
+
167
+
168
+ # add support for Spec syntax
169
+ module Minitest::Expectations
170
+
171
+ infect_an_assertion :assert_association, :must_have_association, :reverse
172
+ infect_an_assertion :assert_association_one_to_one, :must_have_one_to_one_association, :reverse
173
+ infect_an_assertion :assert_association_one_to_many, :must_have_one_to_many_association, :reverse
174
+ infect_an_assertion :assert_association_many_to_one, :must_have_many_to_one_association, :reverse
175
+ infect_an_assertion :assert_association_many_to_many, :must_have_many_to_many_association, :reverse
176
+
177
+ infect_an_assertion :refute_association, :wont_have_association, :reverse
178
+ infect_an_assertion :refute_association_one_to_one, :wont_have_one_to_one_association, :reverse
179
+ infect_an_assertion :refute_association_one_to_many, :wont_have_one_to_many_association, :reverse
180
+ infect_an_assertion :refute_association_many_to_one, :wont_have_many_to_one_association, :reverse
181
+ infect_an_assertion :refute_association_many_to_many, :wont_have_many_to_many_association, :reverse
182
+
183
+ end
@@ -0,0 +1,161 @@
1
+ require 'minitest/sequel'
2
+
3
+ # reopening to add schema validation functionality
4
+ module Minitest::Assertions
5
+
6
+ # Conveniently test your Model definitions as follows:
7
+ #
8
+ # let(:m) { Post.first }
9
+ #
10
+ # it { assert_have_column(m, :title, type: :string, db_type: 'varchar(250)') }
11
+ # it { m.must_have_column(:title, type: :string, db_type: 'varchar(250)') }
12
+ #
13
+ # # assert_have_column(<instance>, <column_name>, <options>, <custom_error_message>)
14
+ #
15
+ # # <instance>.must_have_column(<column_name>, <options>, <custom_error_message>)
16
+ #
17
+ #
18
+ # `assert_have_column()` first tests if the column name is defined in the Model and then checks
19
+ # all passed options. The following options are valid and checked:
20
+ #
21
+ # * :type
22
+ # * :db_type
23
+ # * :allow_null
24
+ # * :max_length
25
+ # * :default
26
+ # * :primary_key
27
+ # * :auto_increment
28
+ #
29
+ # In the event the specs differ from the actual database implementation an extensive error
30
+ # message with the differing option(s) is provided to help speed up debugging the issue:
31
+ #
32
+ # Expected Post model to have column: :title with: \
33
+ # { type: 'string', db_type: 'varchar(250)', allow_null: 'false' } \
34
+ # but found: { db_type: 'varchar(255)' }
35
+ #
36
+ #
37
+ # **Please NOTE!**
38
+ #
39
+ # To test options with a value that is either `nil`, `true` or `false`, please use `:nil`,
40
+ # `:false` or `:true` and provide numbers as 'strings' instead.
41
+ #
42
+ #
43
+ def assert_have_column(obj, attribute, opts = {}, msg = nil)
44
+ msg = msg.nil? ? '' : "#{msg}\n"
45
+ msg << "Expected #{obj.class} model to have column: :#{attribute}"
46
+ err_msg = []
47
+ conf_msg = []
48
+ # check if column exists
49
+ col = obj.db.schema(obj.class.table_name).detect { |c| c[0] == attribute }
50
+ matching = !col.nil?
51
+
52
+ # bail out if no matching column
53
+ unless matching
54
+ msg << ' but no such column exists'
55
+ assert(false, msg)
56
+ end
57
+
58
+ # bail out if options provided are invalid
59
+ val_opts = [:type, :db_type, :allow_null, :max_length, :default, :primary_key, :auto_increment]
60
+ invalid_opts = opts.keys.reject { |o| val_opts.include?(o) }
61
+ unless invalid_opts.empty?
62
+ msg << ', but the following invalid option(s) was found: { '
63
+ invalid_opts.each { |o| msg << "#{o.inspect}; " }
64
+ msg << " }. Valid options are: #{val_opts.inspect}"
65
+ assert(false, msg)
66
+ end
67
+
68
+ # TODO: simplify this mess. quick fix didn't work, so look at it again when time permits.
69
+
70
+ unless opts[:type].nil?
71
+ expected = (col[1][:type].to_s == opts[:type].to_s)
72
+ conf_msg << "type: '#{opts[:type]}'"
73
+ unless expected
74
+ err_msg << "type: '#{col[1][:type]}'"
75
+ end
76
+ matching &&= expected
77
+ end
78
+
79
+ unless opts[:db_type].nil?
80
+ expected = (col[1][:db_type].to_s == opts[:db_type].to_s)
81
+ conf_msg << "db_type: '#{opts[:db_type]}'"
82
+ unless expected
83
+ err_msg << "db_type: '#{col[1][:db_type]}'"
84
+ end
85
+ matching &&= expected
86
+ end
87
+
88
+ unless opts[:max_length].nil?
89
+ expected = (col[1][:max_length] === opts[:max_length])
90
+ conf_msg << "max_length: '#{opts[:max_length]}'"
91
+ unless expected
92
+ err_msg << "max_length: '#{col[1][:max_length]}'"
93
+ end
94
+ matching &&= expected
95
+ end
96
+
97
+ unless opts[:allow_null].nil?
98
+ v = _convert_value(opts[:allow_null])
99
+ expected = (opts[:allow_null] === v)
100
+ conf_msg << "allow_null: '#{opts[:allow_null]}'"
101
+ unless expected
102
+ err_msg << "allow_null: '#{col[1][:allow_null]}'"
103
+ end
104
+ matching &&= expected
105
+ end
106
+
107
+ unless opts[:default].nil?
108
+ v = _convert_value(opts[:default])
109
+ expected = (col[1][:default] === v)
110
+ conf_msg << "default: '#{opts[:default]}'"
111
+ unless expected
112
+ err_msg << "default: '#{col[1][:default].inspect}'"
113
+ end
114
+ matching &&= expected
115
+ end
116
+
117
+ unless opts[:primary_key].nil?
118
+ v = _convert_value(opts[:primary_key])
119
+ expected = (col[1][:primary_key] === v)
120
+ conf_msg << "primary_key: '#{opts[:primary_key]}'"
121
+ unless expected
122
+ err_msg << "primary_key: '#{col[1][:primary_key]}'"
123
+ end
124
+ matching &&= expected
125
+ end
126
+
127
+ unless opts[:auto_increment].nil?
128
+ v = _convert_value(opts[:auto_increment])
129
+ expected = (col[1][:auto_increment] === v)
130
+ conf_msg << "auto_increment: '#{opts[:auto_increment]}'"
131
+ unless expected
132
+ err_msg << "auto_increment: '#{col[1][:auto_increment]}'"
133
+ end
134
+ matching &&= expected
135
+ end
136
+
137
+ msg = msg << " with: { #{conf_msg.join(', ')} } but found: { #{err_msg.join(', ')} }"
138
+ assert(matching, msg)
139
+ end
140
+
141
+ #
142
+ def refute_have_column(obj, attribute, opts = {}, msg = nil)
143
+ msg = msg.nil? ? '' : "#{msg}\n"
144
+ msg << "Expected #{obj.class} model to NOT have column: :#{attribute}"
145
+ # check if column exists
146
+ col = obj.db.schema(obj.class.table_name).detect { |col| col[0] == attribute }
147
+ matching = col.nil?
148
+ unless matching
149
+ msg << ' but such a column was found'
150
+ assert(matching, msg)
151
+ end
152
+ end
153
+
154
+ end
155
+
156
+
157
+ # add support for Spec syntax
158
+ module Minitest::Expectations
159
+ infect_an_assertion :assert_have_column, :must_have_column, :reverse
160
+ infect_an_assertion :refute_have_column, :wont_have_column, :reverse
161
+ end