technicalpickles-shoulda 2.0.6 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/README.rdoc +61 -11
  2. data/Rakefile +7 -5
  3. data/lib/shoulda.rb +7 -15
  4. data/lib/shoulda/action_controller.rb +28 -0
  5. data/lib/shoulda/action_controller/helpers.rb +47 -0
  6. data/lib/shoulda/action_controller/macros.rb +277 -0
  7. data/lib/shoulda/action_controller/matchers.rb +37 -0
  8. data/lib/shoulda/action_controller/matchers/assign_to_matcher.rb +109 -0
  9. data/lib/shoulda/action_controller/matchers/filter_param_matcher.rb +57 -0
  10. data/lib/shoulda/action_controller/matchers/render_with_layout_matcher.rb +81 -0
  11. data/lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb +70 -0
  12. data/lib/shoulda/action_controller/matchers/respond_with_matcher.rb +81 -0
  13. data/lib/shoulda/action_controller/matchers/route_matcher.rb +93 -0
  14. data/lib/shoulda/action_controller/matchers/set_session_matcher.rb +83 -0
  15. data/lib/shoulda/action_controller/matchers/set_the_flash_matcher.rb +85 -0
  16. data/lib/shoulda/action_mailer.rb +1 -1
  17. data/lib/shoulda/action_mailer/assertions.rb +32 -33
  18. data/lib/shoulda/action_view.rb +10 -0
  19. data/lib/shoulda/action_view/macros.rb +56 -0
  20. data/lib/shoulda/active_record.rb +6 -2
  21. data/lib/shoulda/active_record/assertions.rb +62 -81
  22. data/lib/shoulda/active_record/helpers.rb +40 -0
  23. data/lib/shoulda/active_record/macros.rb +514 -640
  24. data/lib/shoulda/active_record/matchers.rb +42 -0
  25. data/lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb +83 -0
  26. data/lib/shoulda/active_record/matchers/allow_value_matcher.rb +102 -0
  27. data/lib/shoulda/active_record/matchers/association_matcher.rb +226 -0
  28. data/lib/shoulda/active_record/matchers/ensure_inclusion_of_matcher.rb +87 -0
  29. data/lib/shoulda/active_record/matchers/ensure_length_of_matcher.rb +141 -0
  30. data/lib/shoulda/active_record/matchers/have_db_column_matcher.rb +169 -0
  31. data/lib/shoulda/active_record/matchers/have_index_matcher.rb +105 -0
  32. data/lib/shoulda/active_record/matchers/have_named_scope_matcher.rb +125 -0
  33. data/lib/shoulda/active_record/matchers/have_readonly_attribute_matcher.rb +59 -0
  34. data/lib/shoulda/active_record/matchers/validate_acceptance_of_matcher.rb +41 -0
  35. data/lib/shoulda/active_record/matchers/validate_numericality_of_matcher.rb +39 -0
  36. data/lib/shoulda/active_record/matchers/validate_presence_of_matcher.rb +60 -0
  37. data/lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb +148 -0
  38. data/lib/shoulda/active_record/matchers/validation_matcher.rb +56 -0
  39. data/lib/shoulda/assertions.rb +50 -40
  40. data/lib/shoulda/autoload_macros.rb +46 -0
  41. data/lib/shoulda/context.rb +124 -126
  42. data/lib/shoulda/helpers.rb +5 -7
  43. data/lib/shoulda/macros.rb +63 -64
  44. data/lib/shoulda/private_helpers.rb +16 -18
  45. data/lib/shoulda/rails.rb +5 -11
  46. data/lib/shoulda/rspec.rb +11 -0
  47. data/lib/shoulda/tasks/list_tests.rake +6 -1
  48. data/lib/shoulda/test_unit.rb +19 -0
  49. data/rails/init.rb +7 -1
  50. data/test/README +2 -2
  51. data/test/fail_macros.rb +16 -16
  52. data/test/functional/posts_controller_test.rb +33 -24
  53. data/test/functional/users_controller_test.rb +0 -19
  54. data/test/matchers/active_record/allow_mass_assignment_of_matcher_test.rb +68 -0
  55. data/test/matchers/active_record/allow_value_matcher_test.rb +41 -0
  56. data/test/matchers/active_record/association_matcher_test.rb +258 -0
  57. data/test/matchers/active_record/ensure_inclusion_of_matcher_test.rb +80 -0
  58. data/test/matchers/active_record/ensure_length_of_matcher_test.rb +158 -0
  59. data/test/matchers/active_record/have_db_column_matcher_test.rb +169 -0
  60. data/test/matchers/active_record/have_index_matcher_test.rb +74 -0
  61. data/test/matchers/active_record/have_named_scope_matcher_test.rb +65 -0
  62. data/test/matchers/active_record/have_readonly_attributes_matcher_test.rb +29 -0
  63. data/test/matchers/active_record/validate_acceptance_of_matcher_test.rb +44 -0
  64. data/test/matchers/active_record/validate_numericality_of_matcher_test.rb +52 -0
  65. data/test/matchers/active_record/validate_presence_of_matcher_test.rb +86 -0
  66. data/test/matchers/active_record/validate_uniqueness_of_matcher_test.rb +147 -0
  67. data/test/matchers/controller/assign_to_matcher_test.rb +35 -0
  68. data/test/matchers/controller/filter_param_matcher_test.rb +32 -0
  69. data/test/matchers/controller/render_with_layout_matcher_test.rb +33 -0
  70. data/test/matchers/controller/respond_with_content_type_matcher_test.rb +27 -0
  71. data/test/matchers/controller/respond_with_matcher_test.rb +106 -0
  72. data/test/matchers/controller/route_matcher_test.rb +58 -0
  73. data/test/matchers/controller/set_session_matcher_test.rb +27 -0
  74. data/test/matchers/controller/set_the_flash_matcher.rb +41 -0
  75. data/test/model_builder.rb +106 -0
  76. data/test/other/autoload_macro_test.rb +18 -0
  77. data/test/other/helpers_test.rb +58 -0
  78. data/test/other/private_helpers_test.rb +1 -1
  79. data/test/other/should_test.rb +16 -16
  80. data/test/rails_root/app/controllers/posts_controller.rb +6 -5
  81. data/test/rails_root/app/models/pets/dog.rb +10 -0
  82. data/test/rails_root/app/models/treat.rb +3 -0
  83. data/test/rails_root/app/models/user.rb +4 -3
  84. data/test/rails_root/app/views/layouts/posts.rhtml +2 -0
  85. data/test/rails_root/config/database.yml +1 -1
  86. data/test/rails_root/config/environment.rb +1 -1
  87. data/test/rails_root/config/environments/{sqlite3.rb → test.rb} +0 -0
  88. data/test/rails_root/db/migrate/001_create_users.rb +3 -2
  89. data/test/rails_root/db/migrate/011_create_treats.rb +12 -0
  90. data/test/rails_root/test/shoulda_macros/custom_macro.rb +6 -0
  91. data/test/rails_root/vendor/gems/gem_with_macro-0.0.1/shoulda_macros/gem_macro.rb +6 -0
  92. data/test/rails_root/vendor/plugins/plugin_with_macro/shoulda_macros/plugin_macro.rb +6 -0
  93. data/test/rspec_test.rb +207 -0
  94. data/test/test_helper.rb +3 -1
  95. data/test/unit/address_test.rb +1 -1
  96. data/test/unit/dog_test.rb +5 -2
  97. data/test/unit/post_test.rb +7 -3
  98. data/test/unit/product_test.rb +2 -2
  99. data/test/unit/tag_test.rb +2 -1
  100. data/test/unit/user_test.rb +27 -9
  101. metadata +82 -13
  102. data/lib/shoulda/controller.rb +0 -30
  103. data/lib/shoulda/controller/formats/html.rb +0 -201
  104. data/lib/shoulda/controller/formats/xml.rb +0 -170
  105. data/lib/shoulda/controller/helpers.rb +0 -64
  106. data/lib/shoulda/controller/macros.rb +0 -316
  107. data/lib/shoulda/controller/resource_options.rb +0 -236
  108. data/test/rails_root/app/models/dog.rb +0 -5
@@ -0,0 +1,83 @@
1
+ module Shoulda # :nodoc:
2
+ module ActionController # :nodoc:
3
+ module Matchers
4
+
5
+ # Ensures that a session key was set to the expected value.
6
+ #
7
+ # Example:
8
+ #
9
+ # it { should set_session(:message) }
10
+ # it { should set_session(:user_id).to(@user.id) }
11
+ # it { should_not set_session(:user_id) }
12
+ def set_session(key)
13
+ SetSessionMatcher.new(key)
14
+ end
15
+
16
+ class SetSessionMatcher # :nodoc:
17
+
18
+ def initialize(key)
19
+ @key = key.to_s
20
+ end
21
+
22
+ def to(value)
23
+ @value = value
24
+ self
25
+ end
26
+
27
+ def matches?(controller)
28
+ @controller = controller
29
+ assigned_value? && assigned_correct_value?
30
+ end
31
+
32
+ def failure_message
33
+ "Expected #{expectation}, but #{result}"
34
+ end
35
+
36
+ def negative_failure_message
37
+ "Didn't expect #{expectation}, but #{result}"
38
+ end
39
+
40
+ def description
41
+ description = "set session variable #{@key.inspect}"
42
+ description << " to #{@value.inspect}" if @value
43
+ description
44
+ end
45
+
46
+ private
47
+
48
+ def assigned_value?
49
+ !assigned_value.blank?
50
+ end
51
+
52
+ def assigned_correct_value?
53
+ return true if @value.nil?
54
+ assigned_value == @value
55
+ end
56
+
57
+ def assigned_value
58
+ session[@key]
59
+ end
60
+
61
+ def session
62
+ @controller.response.session.data
63
+ end
64
+
65
+ def expectation
66
+ expectation = "session variable #{@key} to be set"
67
+ expectation << " to #{@value.inspect}" if @value
68
+ expectation
69
+ end
70
+
71
+ def result
72
+ if session.empty?
73
+ "no session variables were set"
74
+ else
75
+ "the session was #{session.inspect}"
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,85 @@
1
+ module Shoulda # :nodoc:
2
+ module ActionController # :nodoc:
3
+ module Matchers
4
+
5
+ # Ensures that the flash contains the given value. Can be a String, a
6
+ # Regexp, or nil (indicating that the flash should not be set).
7
+ #
8
+ # Example:
9
+ #
10
+ # it { should set_the_flash }
11
+ # it { should set_the_flash.to("Thank you for placing this order.") }
12
+ # it { should set_the_flash.to(/created/i) }
13
+ # it { should_not set_the_flash }
14
+ def set_the_flash
15
+ SetTheFlashMatcher.new
16
+ end
17
+
18
+ class SetTheFlashMatcher # :nodoc:
19
+
20
+ def to(value)
21
+ @value = value
22
+ self
23
+ end
24
+
25
+ def matches?(controller)
26
+ @controller = controller
27
+ sets_the_flash? && string_value_matches? && regexp_value_matches?
28
+ end
29
+
30
+ attr_reader :failure_message, :negative_failure_message
31
+
32
+ def description
33
+ description = "set the flash"
34
+ description << " to #{@value.inspect}" unless @value.nil?
35
+ description
36
+ end
37
+
38
+ def failure_message
39
+ "Expected #{expectation}"
40
+ end
41
+
42
+ def negative_failure_message
43
+ "Did not expect #{expectation}"
44
+ end
45
+
46
+ private
47
+
48
+ def sets_the_flash?
49
+ !flash.blank?
50
+ end
51
+
52
+ def string_value_matches?
53
+ return true unless String === @value
54
+ flash.values.any? {|value| value == @value }
55
+ end
56
+
57
+ def regexp_value_matches?
58
+ return true unless Regexp === @value
59
+ flash.values.any? {|value| value =~ @value }
60
+ end
61
+
62
+ def flash
63
+ @controller.response.session['flash']
64
+ end
65
+
66
+ def expectation
67
+ expectation = "the flash to be set"
68
+ expectation << " to #{@value.inspect}" unless @value.nil?
69
+ expectation << ", but #{flash_description}"
70
+ expectation
71
+ end
72
+
73
+ def flash_description
74
+ if flash.blank?
75
+ "no flash was set"
76
+ else
77
+ "was #{flash.inspect}"
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -4,7 +4,7 @@ require 'shoulda/action_mailer/assertions'
4
4
  module Test # :nodoc: all
5
5
  module Unit
6
6
  class TestCase
7
- include ThoughtBot::Shoulda::ActionMailer::Assertions
7
+ include Shoulda::ActionMailer::Assertions
8
8
  end
9
9
  end
10
10
  end
@@ -1,39 +1,38 @@
1
- module ThoughtBot # :nodoc:
2
- module Shoulda # :nodoc:
3
- module ActionMailer # :nodoc:
4
- module Assertions
5
- # Asserts that an email was delivered. Can take a block that can further
6
- # narrow down the types of emails you're expecting.
7
- #
8
- # assert_sent_email
9
- #
10
- # Passes if ActionMailer::Base.deliveries has an email
11
- #
12
- # assert_sent_email do |email|
13
- # email.subject =~ /hi there/ && email.to.include?('none@none.com')
14
- # end
15
- #
16
- # Passes if there is an email with subject containing 'hi there' and
17
- # 'none@none.com' as one of the recipients.
18
- #
19
- def assert_sent_email
20
- emails = ::ActionMailer::Base.deliveries
21
- assert !emails.empty?, "No emails were sent"
22
- if block_given?
23
- matching_emails = emails.select {|email| yield email }
24
- assert !matching_emails.empty?, "None of the emails matched."
25
- end
1
+ module Shoulda # :nodoc:
2
+ module ActionMailer # :nodoc:
3
+ module Assertions
4
+ # Asserts that an email was delivered. Can take a block that can further
5
+ # narrow down the types of emails you're expecting.
6
+ #
7
+ # assert_sent_email
8
+ #
9
+ # Passes if ActionMailer::Base.deliveries has an email
10
+ #
11
+ # assert_sent_email do |email|
12
+ # email.subject =~ /hi there/ && email.to.include?('none@none.com')
13
+ # end
14
+ #
15
+ # Passes if there is an email with subject containing 'hi there' and
16
+ # 'none@none.com' as one of the recipients.
17
+ #
18
+ def assert_sent_email
19
+ emails = ::ActionMailer::Base.deliveries
20
+ assert !emails.empty?, "No emails were sent"
21
+ if block_given?
22
+ matching_emails = emails.select {|email| yield email }
23
+ assert !matching_emails.empty?, "None of the emails matched."
26
24
  end
25
+ end
27
26
 
28
- # Asserts that no ActionMailer mails were delivered
29
- #
30
- # assert_did_not_send_email
31
- def assert_did_not_send_email
32
- msg = "Sent #{::ActionMailer::Base.deliveries.size} emails.\n"
33
- ::ActionMailer::Base.deliveries.each { |m| msg << " '#{m.subject}' sent to #{m.to.to_sentence}\n" }
34
- assert ::ActionMailer::Base.deliveries.empty?, msg
35
- end
27
+ # Asserts that no ActionMailer mails were delivered
28
+ #
29
+ # assert_did_not_send_email
30
+ def assert_did_not_send_email
31
+ msg = "Sent #{::ActionMailer::Base.deliveries.size} emails.\n"
32
+ ::ActionMailer::Base.deliveries.each { |m| msg << " '#{m.subject}' sent to #{m.to.to_sentence}\n" }
33
+ assert ::ActionMailer::Base.deliveries.empty?, msg
36
34
  end
37
35
  end
38
36
  end
39
37
  end
38
+
@@ -0,0 +1,10 @@
1
+ require 'shoulda'
2
+ require 'shoulda/action_view/macros'
3
+
4
+ module Test # :nodoc: all
5
+ module Unit
6
+ class TestCase
7
+ extend Shoulda::ActionView::Macros
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,56 @@
1
+ module Shoulda # :nodoc:
2
+ module ActionView # :nodoc:
3
+ # = Macro test helpers for your view
4
+ #
5
+ # By using the macro helpers you can quickly and easily create concise and
6
+ # easy to read test suites.
7
+ #
8
+ # This code segment:
9
+ # context "on GET to :new" do
10
+ # setup do
11
+ # get :new
12
+ # end
13
+ #
14
+ # should_render_a_form
15
+ # should_render_page_with_metadata :title => /index/
16
+ #
17
+ # should "do something else really cool" do
18
+ # assert_select '#really_cool'
19
+ # end
20
+ # end
21
+ #
22
+ # Would produce 3 tests for the +show+ action
23
+ module Macros
24
+
25
+ # Macro that creates a test asserting that the rendered view contains a <form> element.
26
+ def should_render_a_form
27
+ should "display a form" do
28
+ assert_select "form", true, "The template doesn't contain a <form> element"
29
+ end
30
+ end
31
+
32
+ # Macro that creates a test asserting that the rendered view contains the selected metatags.
33
+ # Values can be string or Regexps.
34
+ # Example:
35
+ #
36
+ # should_render_page_with_metadata :description => "Description of this page", :keywords => /post/
37
+ #
38
+ # You can also use this method to test the rendered views title.
39
+ #
40
+ # Example:
41
+ # should_render_page_with_metadata :title => /index/
42
+ def should_render_page_with_metadata(options)
43
+ options.each do |key, value|
44
+ should "have metatag #{key}" do
45
+ if key.to_sym == :title
46
+ assert_select "title", value
47
+ else
48
+ assert_select "meta[name=?][content#{"*" if value.is_a?(Regexp)}=?]", key, value
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
@@ -1,12 +1,16 @@
1
1
  require 'shoulda'
2
+ require 'shoulda/active_record/helpers'
3
+ require 'shoulda/active_record/matchers'
2
4
  require 'shoulda/active_record/assertions'
3
5
  require 'shoulda/active_record/macros'
4
6
 
5
7
  module Test # :nodoc: all
6
8
  module Unit
7
9
  class TestCase
8
- include ThoughtBot::Shoulda::ActiveRecord::Assertions
9
- extend ThoughtBot::Shoulda::ActiveRecord::Macros
10
+ include Shoulda::ActiveRecord::Helpers
11
+ include Shoulda::ActiveRecord::Matchers
12
+ include Shoulda::ActiveRecord::Assertions
13
+ extend Shoulda::ActiveRecord::Macros
10
14
  end
11
15
  end
12
16
  end
@@ -1,87 +1,68 @@
1
- module ThoughtBot # :nodoc:
2
- module Shoulda # :nodoc:
3
- module ActiveRecord # :nodoc:
4
- module Assertions
5
- # Asserts that the given object can be saved
6
- #
7
- # assert_save User.new(params)
8
- def assert_save(obj)
9
- assert obj.save, "Errors: #{pretty_error_messages obj}"
10
- obj.reload
11
- end
12
-
13
- # Asserts that the given object is valid
14
- #
15
- # assert_valid User.new(params)
16
- def assert_valid(obj)
17
- assert obj.valid?, "Errors: #{pretty_error_messages obj}"
18
- end
19
-
20
- # Asserts that an Active Record model validates with the passed
21
- # <tt>value</tt> by making sure the <tt>error_message_to_avoid</tt> is not
22
- # contained within the list of errors for that attribute.
23
- #
24
- # assert_good_value(User.new, :email, "user@example.com")
25
- # assert_good_value(User.new, :ssn, "123456789", /length/)
26
- #
27
- # If a class is passed as the first argument, a new object will be
28
- # instantiated before the assertion. If an instance variable exists with
29
- # the same name as the class (underscored), that object will be used
30
- # instead.
31
- #
32
- # assert_good_value(User, :email, "user@example.com")
33
- #
34
- # @product = Product.new(:tangible => false)
35
- # assert_good_value(Product, :price, "0")
36
- def assert_good_value(object_or_klass, attribute, value, error_message_to_avoid = //)
37
- object = get_instance_of(object_or_klass)
38
- object.send("#{attribute}=", value)
39
- object.valid?
40
- assert_does_not_contain(object.errors.on(attribute), error_message_to_avoid, "when set to #{value.inspect}")
41
- end
42
-
43
- # Asserts that an Active Record model invalidates the passed
44
- # <tt>value</tt> by making sure the <tt>error_message_to_expect</tt> is
45
- # contained within the list of errors for that attribute.
46
- #
47
- # assert_bad_value(User.new, :email, "invalid")
48
- # assert_bad_value(User.new, :ssn, "123", /length/)
49
- #
50
- # If a class is passed as the first argument, a new object will be
51
- # instantiated before the assertion. If an instance variable exists with
52
- # the same name as the class (underscored), that object will be used
53
- # instead.
54
- #
55
- # assert_bad_value(User, :email, "invalid")
56
- #
57
- # @product = Product.new(:tangible => true)
58
- # assert_bad_value(Product, :price, "0")
59
- def assert_bad_value(object_or_klass, attribute, value,
60
- error_message_to_expect = self.class.default_error_message(:invalid))
61
- object = get_instance_of(object_or_klass)
62
- object.send("#{attribute}=", value)
63
- assert !object.valid?, "#{object.class} allowed #{value.inspect} as a value for #{attribute}"
64
- assert object.errors.on(attribute), "There are no errors on #{attribute} after being set to #{value.inspect}"
65
- assert_contains(object.errors.on(attribute), error_message_to_expect, "when set to #{value.inspect}")
66
- end
1
+ module Shoulda # :nodoc:
2
+ module ActiveRecord # :nodoc:
3
+ module Assertions
4
+ # Asserts that the given object can be saved
5
+ #
6
+ # assert_save User.new(params)
7
+ def assert_save(obj)
8
+ assert obj.save, "Errors: #{pretty_error_messages obj}"
9
+ obj.reload
10
+ end
67
11
 
68
- def pretty_error_messages(obj)
69
- obj.errors.map do |a, m|
70
- msg = "#{a} #{m}"
71
- msg << " (#{obj.send(a).inspect})" unless a.to_sym == :base
72
- end
73
- end
12
+ # Asserts that the given object is valid
13
+ #
14
+ # assert_valid User.new(params)
15
+ def assert_valid(obj)
16
+ assert obj.valid?, "Errors: #{pretty_error_messages obj}"
17
+ end
74
18
 
75
- private
19
+ # Asserts that an Active Record model validates with the passed
20
+ # <tt>value</tt> by making sure the <tt>error_message_to_avoid</tt> is not
21
+ # contained within the list of errors for that attribute.
22
+ #
23
+ # assert_good_value(User.new, :email, "user@example.com")
24
+ # assert_good_value(User.new, :ssn, "123456789", /length/)
25
+ #
26
+ # If a class is passed as the first argument, a new object will be
27
+ # instantiated before the assertion. If an instance variable exists with
28
+ # the same name as the class (underscored), that object will be used
29
+ # instead.
30
+ #
31
+ # assert_good_value(User, :email, "user@example.com")
32
+ #
33
+ # @product = Product.new(:tangible => false)
34
+ # assert_good_value(Product, :price, "0")
35
+ def assert_good_value(object_or_klass, attribute, value, error_message_to_avoid = nil)
36
+ object = get_instance_of(object_or_klass)
37
+ matcher = allow_value(value).
38
+ for(attribute).
39
+ with_message(error_message_to_avoid)
40
+ assert_accepts(matcher, object)
41
+ end
76
42
 
77
- def get_instance_of(object_or_klass)
78
- if object_or_klass.is_a?(Class)
79
- klass = object_or_klass
80
- instance_variable_get("@#{klass.to_s.underscore}") || klass.new
81
- else
82
- object_or_klass
83
- end
84
- end
43
+ # Asserts that an Active Record model invalidates the passed
44
+ # <tt>value</tt> by making sure the <tt>error_message_to_expect</tt> is
45
+ # contained within the list of errors for that attribute.
46
+ #
47
+ # assert_bad_value(User.new, :email, "invalid")
48
+ # assert_bad_value(User.new, :ssn, "123", /length/)
49
+ #
50
+ # If a class is passed as the first argument, a new object will be
51
+ # instantiated before the assertion. If an instance variable exists with
52
+ # the same name as the class (underscored), that object will be used
53
+ # instead.
54
+ #
55
+ # assert_bad_value(User, :email, "invalid")
56
+ #
57
+ # @product = Product.new(:tangible => true)
58
+ # assert_bad_value(Product, :price, "0")
59
+ def assert_bad_value(object_or_klass, attribute, value,
60
+ error_message_to_expect = nil)
61
+ object = get_instance_of(object_or_klass)
62
+ matcher = allow_value(value).
63
+ for(attribute).
64
+ with_message(error_message_to_expect)
65
+ assert_rejects(matcher, object)
85
66
  end
86
67
  end
87
68
  end