--- shoulda version 7 Tue Sep 30 20:17:24 +0000 2008
+++ shoulda version 8 Wed Oct 01 03:01:57 +0000 2008
@@ -1,108 +1,164 @@
-= Assertions
-assert_contains ['a', '1'], /a/
-assert_does_not_contain ['a', '1'], /b/
+Installing
+----------
-assert_same_elements [1, 2, 3], [3, 2, 1]
+ As a Rails plugin
+ -----------------
+
+ script/plugin install git://github.com/thoughtbot/shoulda.git
+
+ As a Rails gem
+ --------------
+
+ In config/environment.rb:
+ config.gem 'thoughtbot-shoulda', :lib => 'shoulda/rails', :source =>
+ 'http://gems.github.com'
+
+ Then run:
+ rake gems:install gems:unpack
+
+ As a standalone gem
+ -------------------
+
+ Run:
+ sudo gem install thoughtbot-shoulda -s http://gems.github.com
+
+ In your test, or test_helper.rb:
+ require 'shoulda'
-assert_bad_value User, :birthdate, "Older than you!"
-assert_good_value User, :email, "bob@email.com"
+Assertions
+----------
-assert_save @user
-assert_valid @user
+ assert_contains <array>, <object in array, or regular expression to match>
+ assert_does_not_contain <array>, <object not in array, or regular expression
+ to not match>
+
+ assert_same_elements <array>, <array with same elements, but different order>
+
+ assert_bad_value <class>, <attribute>, <value that should cause an validation
+ error on attribute>
+ assert_good_value <class>, <attribute>, <value that should not cause a
+ validation error on attribute>
+
+ assert_save <object which .save returns true>
+ assert_valid <object which .valid? returns true>
+
+ assert_sent_email do |email|
+ email.subject =~ /activated/ && email.to.include?('bob@email.com')
+ end
+ assert_did_not_send_email do |email|
+ email.subject =~ /activated/ && email.to.include?('bob@email.com')
+ end
-assert_sent_email do |email|
- email.subject =~ /activated/ && email.to.include?('bob@email.com')
-end
-assert_did_not_send_email do |email|
- email.subject =~ /activated/ && email.to.include?('bob@email.com')
-end
+Basics
+------
-assert_xml_response
+ class FooTest < Test::Unit::TestCase
+ context <context description string> do
+ setup do
+ # ...
+ end
+
+ teardown do
+ end
+
+ should <description string> do
+ end
+
+ should_eventually <description string>
+ should_eventually <description string> do
+ # this code can be broken, but won't break the build
+ end
+ end
+
+ should <string description> do
+ # ...
+ end
+ end
-= Macros
-should_eventually 'be awesome'
-should_eventually 'clean my room' do
- raise "I am so broken"
-end
-should_change "Post.count", :from => 0, :to => 1
-should_change "@post.title", :from => "old", :to => "new"
-should_change "@post.title"
-should_change "@post.title" :from => "old"
-should_change "@post.title" :to => "new"
-should_not_change "Post.count"
+General Macros
+--------------
+
+ should_change "Post.count", :from => 0, :to => 1
+ should_change "@post.title", :from => "old", :to => "new"
+ should_change "@post.title"
+ should_change "@post.title" :from => "old"
+ should_change "@post.title" :to => "new"
+ should_not_change "Post.count"
-== Class under test
+Macros for class under test
+---------------------------
-should_have_class_methods :find, :destroy
-should_have_instance_methods :email, :name, :name=
+ should_have_class_methods :find, :destroy
+ should_have_instance_methods :email, :name, :name=
-== ActiveRecord
+ActiveRecord Macros
+-------------------
-should_have_db_columns :id, :email, :name, :created_at
-should_have_db_column :email, :type => "string", :default => nil, :precision =>
-nil, :limit => 255, :null => true, :primary => false, :scale => nil, :sql_type
-=> 'varchar(255)'
+ should_have_db_columns :id, :email, :name, :created_at
+ should_have_db_column :email, :type => "string", :default => nil, :precision
+ => nil, :limit => 255,
+ :null => true, :primary => false, :scale
+ => nil, :sql_type => 'varchar(255)'
+
+ should_have_indices :email, :name, [:commentable_type, :commentable_id]
+ should_have_index :age
+
+ should_have_named_scope 'recent(5)', :limit => 5
+ should_have_named_scope 'recent(1)', :limit => 1
+
+ should_require_acceptance_of :eula
+
+ should_ensure_length_at_least :name, 3
+ should_ensure_length_is :ssn, 9
+ should_ensure_value_in_range :age, (0..100)
+
+ should_only_allow_numeric_values_for :age
+
+ should_have_readonly_attributes :password, :admin_flag
+
+ should_require_attributes :name, :phone_number
+
+ should_require_unique_attributes :keyword, :username
+ should_require_unique_attributes :name, :message => "O NOES! SOMEONE STOELED
+ YER NAME!"
+ should_require_unique_attributes :email, :scoped_to => :name
+ should_require_unique_attributes :address, :scoped_to => [:first_name,
+ :last_name]
+
+ should_protect_attributes :password, :admin_flag
+
+ should_allow_values_for :phone, "(123) 999-3049", "201-0023"
+ should_not_allow_values_for :phone, "I am totally not a phone number",
+ "201-0023"
+
+ should_belong_to :parent
+
+ should_have_one :god
+
+ should_have_many :friends
+ should_have_many :enemies, :through => :friends
+ should_have_many :enemies, :dependent => :destroy
+
+ should_have_and_belong_to_many :posts, :cars
-should_have_indices :email, :name, [:commentable_type, :commentable_id]
-should_have_index :age
+ActionController Macros
+-----------------------
-should_have_named_scope 'recent(5)', :limit => 5
-should_have_named_scope 'recent(1)', :limit => 1
-
-should_require_acceptance_of :eula
-
-should_ensure_length_at_least :name, 3
-should_ensure_length_is :ssn, 9
-should_ensure_value_in_range :age, (0..100)
-
-should_only_allow_numeric_values_for :age
-
-should_have_readonly_attributes :password, :admin_flag
-
-should_require_attributes :name, :phone_number
-
-should_require_unique_attributes :keyword, :username
-should_require_unique_attributes :name, :message => "someone stole your name"
-should_require_unique_attributes :email, :scoped_to => :name
-should_require_unique_attributes :address, :scoped_to => [:first_name,
-:last_name]
-
-should_protect_attributes :password, :admin_flag
-
-should_allow_values_for :phone, "(123) 999-3049", "201-0023"
-should_not_allow_values_for :phone, "I am totally not a phone number",
-"201-0023"
-
-should_belong_to :parent
-
-should_have_one :god
-
-should_have_many :friends
-should_have_many :enemies, :through => :friends
-should_have_many :enemies, :dependent => :destroy
-
-should_have_and_belong_to_many :posts, :cars
-
-
-
-== ActionController
-
-should_assign_to
-should_be_restful
-should_belong_to
-should_filter_params
-should_not_assign_to
-should_not_set_the_flash
-should_redirect_to
-should_render_a_form
-should_render_template
-should_respond_with
-should_respond_with_xml_for
-should_route
-should_set_the_flash_to
-
+ should_assign_to
+ should_be_restful
+ should_belong_to
+ should_filter_params
+ should_not_assign_to
+ should_not_set_the_flash
+ should_redirect_to
+ should_render_a_form
+ should_render_template
+ should_respond_with
+ should_respond_with_xml_for
+ should_route
+ should_set_the_flash_to