mcmire-context 0.5.6

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.
@@ -0,0 +1,6 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'context/core'
5
+
6
+ Context.setup Test::Unit::TestCase
@@ -0,0 +1,102 @@
1
+ require 'test/unit'
2
+
3
+ module Context
4
+ class << self
5
+ attr_accessor :core_class
6
+ end
7
+
8
+ def self.setup(test_case)
9
+ if core_class
10
+ if core_class == test_case
11
+ return
12
+ else
13
+ raise ArgumentError, "Currently, you're not allowed to run Context.setup again and clobber '#{core_class.name}'. Require 'context/core' and pick ONE class."
14
+ end
15
+ end
16
+
17
+ self.core_class = test_case
18
+ test_case.class_eval do
19
+ include TestCase
20
+ extend TestCase::ClassMethods
21
+
22
+ # for some reason, Test::Unit::TestCase won't let me cleanly override
23
+ # #suite with an extended module :(
24
+ def self.suite
25
+ context_suite
26
+ end
27
+ end
28
+ end
29
+
30
+ module TestCase
31
+ module ClassMethods
32
+ # Test::Unit uses ObjectSpace to figure out what Test::Unit:TestCase instances are running
33
+ # Contexts are not named and therefore sometimes get garbage collected.
34
+ # Think of #context_list as the shelter for nameless contexts
35
+ attr_accessor :context_list
36
+
37
+ def context_name #:nodoc:
38
+ @context_name ||= ""
39
+ if superclass.respond_to?(:context_name)
40
+ return "#{superclass.context_name} #{@context_name}".gsub(/^\s+/, "")
41
+ end
42
+ end
43
+
44
+ def context_name=(val) #:nodoc:
45
+ @context_name = val
46
+ end
47
+
48
+ # Add a context to a set of tests.
49
+ #
50
+ # context "A new account" do
51
+ # it "should not have users"
52
+ # assert Account.new.users.empty?
53
+ # end
54
+ # end
55
+ #
56
+ # The context name is prepended to the test name, so failures look like this:
57
+ #
58
+ # 1) Failure:
59
+ # test_a_new_account_should_not_have_users() [./test/test_accounts.rb:4]:
60
+ # <false> is not true.
61
+ #
62
+ # Contexts can also be nested like so:
63
+ #
64
+ # context "A new account" do
65
+ # context "created by the web application" do
66
+ # it "should have web as its vendor" do
67
+ # assert_equal "web", users(:web_user).vendor
68
+ # end
69
+ # end
70
+ # end
71
+ #
72
+ # Since contexts create a singleton instance of a class, each one must have its own before/after blocks. This
73
+ # will be tweaked in future releases to allow you to chain these blocks from its parent contexts.
74
+ #
75
+ def context(name, &block)
76
+ cls = Class.new(self)
77
+ cls.context_name = name
78
+
79
+ # Care about Rails tests in nested contexts
80
+ cls.tests($1.constantize) if defined?(Rails) &&
81
+ self.name =~ /^(.*(Controller|Helper|Mailer))Test/ &&
82
+ self < ActiveSupport::TestCase
83
+
84
+ cls.class_eval(&block)
85
+ (self.context_list ||= []) << cls
86
+ const_set("Test#{name.to_class_name}#{cls.object_id.abs}", cls)
87
+ cls
88
+ end
89
+
90
+ %w(contexts describe describes group specify specifies).each {|m| alias_method m, :context}
91
+ end
92
+ end
93
+ end
94
+
95
+ require 'context/core_ext/string'
96
+ require 'context/core_ext/rails_hacks'
97
+
98
+ require 'context/version'
99
+ require 'context/suite'
100
+ require 'context/test'
101
+ require 'context/lifecycle'
102
+ require 'context/shared_behavior'
@@ -0,0 +1,8 @@
1
+ module Context::TestCase::ClassMethods
2
+ def setup_for_shoulda
3
+ self.instance_eval do
4
+ alias :setup :before
5
+ alias :teardown :after
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,29 @@
1
+ module Context::String
2
+ # Replaces spaces and tabs with _ so we can use the string as a method name
3
+ # Also replace dangerous punctuation
4
+ def to_method_name
5
+ downcased = self.downcase
6
+ downcased.gsub!(/[\s:',\.~;!#=\-\(\)\?]+/,'_')
7
+ downcased
8
+ end
9
+
10
+ # Borrowed from +camelize+ in ActiveSupport
11
+ def to_module_name
12
+ meth_name = self.to_method_name
13
+ meth_name.gsub!(/\/(.?)/) { "::#{$1.upcase}" }
14
+ meth_name.gsub!(/(?:^|_)(.)/) { $1.upcase }
15
+ meth_name
16
+ end
17
+
18
+ # Borrowed from +camelize+ in ActiveSupport
19
+ def to_class_name
20
+ meth_name = self.to_method_name
21
+ meth_name.gsub!(/\/(.?)/) { "#{$1.upcase}" }
22
+ meth_name.gsub!(/(?:^|_)(.)/) { $1.upcase }
23
+ meth_name
24
+ end
25
+ end
26
+
27
+ class String
28
+ include Context::String
29
+ end
@@ -0,0 +1,115 @@
1
+ module Context
2
+ module TestCase::ClassMethods
3
+ attr_accessor :before_each_callbacks, :before_all_callbacks, :after_each_callbacks, :after_all_callbacks, :before_should_callbacks
4
+
5
+ def self.extended(test_case)
6
+ test_case.before_all_callbacks = []
7
+ test_case.before_each_callbacks = []
8
+ test_case.after_each_callbacks = []
9
+ test_case.after_all_callbacks = []
10
+ test_case.before_should_callbacks = {}
11
+ end
12
+
13
+ # Add logic to run before the tests (i.e., a +setup+ method)
14
+ #
15
+ # before do
16
+ # @user = User.first
17
+ # end
18
+ #
19
+ def before(period = :each, &block)
20
+ unless block_given?
21
+ block = period
22
+ period = :each
23
+ end
24
+
25
+ send("before_#{period}_callbacks") << block
26
+ end
27
+
28
+ alias :setup :before
29
+
30
+ # Add logic to run after the tests (i.e., a +teardown+ method)
31
+ #
32
+ # after do
33
+ # User.delete_all
34
+ # end
35
+ #
36
+ def after(period = :each, &block)
37
+ unless block_given?
38
+ block = period
39
+ period = :each
40
+ end
41
+
42
+ send("after_#{period}_callbacks") << block
43
+ end
44
+
45
+ alias :teardown :after
46
+
47
+ def gather_callbacks(callback_type, period) # :nodoc:
48
+ callbacks = superclass.respond_to?(:gather_callbacks) ? superclass.gather_callbacks(callback_type, period) : []
49
+ callbacks.push(*send("#{callback_type}_#{period}_callbacks"))
50
+ end
51
+
52
+ def inherited(child) # :nodoc:
53
+ super
54
+ child.before_all_callbacks = []
55
+ child.before_each_callbacks = []
56
+ child.after_each_callbacks = []
57
+ child.after_all_callbacks = []
58
+ child.before_should_callbacks = {}
59
+
60
+ child.class_eval do
61
+ def setup(&block)
62
+ super
63
+ run_context_before_callbacks
64
+ end
65
+
66
+ def teardown
67
+ super
68
+ run_context_after_callbacks
69
+ end
70
+ end if self == ::Context.core_class
71
+ end
72
+ end
73
+
74
+ module TestCase
75
+ def run_each_callbacks(callback_type) # :nodoc:
76
+ self.class.gather_callbacks(callback_type, :each).each do |c|
77
+ next if !c
78
+ c.is_a?(Proc) ? instance_eval(&c) : send(c)
79
+ end
80
+ end
81
+
82
+ def run_all_callbacks(callback_type) # :nodoc:
83
+ previous_ivars = instance_variables
84
+ self.class.gather_callbacks(callback_type, :all).each { |c| instance_eval(&c) if c }
85
+ (instance_variables - previous_ivars).inject({}) do |hash, ivar|
86
+ hash.update ivar => instance_variable_get(ivar)
87
+ end
88
+ rescue Object => exception
89
+ raise <<-BANG
90
+ Error running the #{callback_type}(:all) callback for #{name}
91
+ #{exception.class.name}: #{exception.message}
92
+ #{exception.backtrace.join("\n")}
93
+ BANG
94
+ end
95
+
96
+ def set_values_from_callbacks(values) # :nodoc:
97
+ values.each do |name, value|
98
+ instance_variable_set name, value
99
+ end
100
+ end
101
+
102
+ private
103
+ def run_context_before_callbacks
104
+ unless self.class.before_should_callbacks[method_name].nil?
105
+ instance_eval(&self.class.before_should_callbacks[method_name])
106
+ end
107
+
108
+ run_each_callbacks :before
109
+ end
110
+
111
+ def run_context_after_callbacks
112
+ run_each_callbacks :after
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,96 @@
1
+ module Context
2
+ class SharedBehavior < Module
3
+ def self.create_from_behavior(beh) # :nodoc:
4
+ mod = self.new
5
+ mod._behavior = beh
6
+
7
+ mod
8
+ end
9
+
10
+ def _behavior=(beh) # :nodoc:
11
+ @_behavior = beh
12
+ end
13
+
14
+ def included(arg) # :nodoc:
15
+ arg.instance_eval(&@_behavior)
16
+ end
17
+ end
18
+ end
19
+
20
+ module Context::TestCase::ClassMethods
21
+ # Share behavior among different contexts. This creates a module (actually, a Module subclass)
22
+ # that is included using the +use+ method (or one of its aliases) provided by context or +include+
23
+ # if you know the module's constant name.
24
+ #
25
+ # ==== Examples
26
+ #
27
+ # shared "other things" do
28
+ # it "should do things but not some things" do
29
+ # # behavior is fun
30
+ # end
31
+ # end
32
+ #
33
+ # use "other things"
34
+ # # or...
35
+ # it_should_behave_like "other things"
36
+ #
37
+ # shared :client do
38
+ # it "should be a client to our server" do
39
+ # # TODO: client behavior here
40
+ # end
41
+ # end
42
+ #
43
+ # use :client
44
+ # # or...
45
+ # uses "client"
46
+ # behaves_like "client"
47
+ #
48
+ def shared(name, &block)
49
+ case name.class.name
50
+ when "String"
51
+ name = name.to_module_name
52
+ when "Symbol"
53
+ name = name.to_s.to_module_name
54
+ else
55
+ raise ArgumentError, "Provide a String or Symbol as the name of the shared behavior group"
56
+ end
57
+
58
+ Object.const_set(name, Context::SharedBehavior.create_from_behavior(block))
59
+ end
60
+
61
+ %w(shared_behavior share_as share_behavior_as shared_examples_for).each {|m| alias_method m, :shared}
62
+
63
+ # Pull in behavior shared by +shared+ or a module.
64
+ #
65
+ # ==== Examples
66
+ #
67
+ # shared "other things" do
68
+ # it "should do things but not some things" do
69
+ # # behavior is fun
70
+ # end
71
+ # end
72
+ #
73
+ # use "other things"
74
+ # # or...
75
+ # it_should_behave_like "other things"
76
+ #
77
+ # module Things
78
+ # end
79
+ #
80
+ # uses Things
81
+ #
82
+ def use(shared_name)
83
+ case shared_name.class.name
84
+ when "Context::SharedBehavior", "Module"
85
+ include shared_name
86
+ when "String"
87
+ include Object.const_get(shared_name.to_module_name)
88
+ when "Symbol"
89
+ include Object.const_get(shared_name.to_s.to_module_name)
90
+ else
91
+ raise ArgumentError, "Provide a String or Symbol as the name of the shared behavior group or the module name"
92
+ end
93
+ end
94
+
95
+ %w(uses it_should_behave_like behaves_like uses_examples_from).each {|m| alias_method m, :use}
96
+ end
@@ -0,0 +1,35 @@
1
+ module Context
2
+ module TestCase::ClassMethods
3
+ # Tweaks to standard method so we don't get superclass methods and we don't
4
+ # get weird default tests
5
+ def context_suite # :nodoc:
6
+ method_names = public_instance_methods - superclass.public_instance_methods
7
+
8
+ tests = method_names.delete_if {|method_name| method_name !~ /^test./}
9
+ suite = TestSuite.new(name)
10
+
11
+ tests.sort.each do |test|
12
+ catch(:invalid_test) do
13
+ suite << new(test)
14
+ end
15
+ end
16
+
17
+ suite
18
+ end
19
+ end
20
+
21
+ class TestSuite < Test::Unit::TestSuite
22
+ # Runs the tests and/or suites contained in this
23
+ # TestSuite.
24
+ def run(result, &progress_block) # :nodoc:
25
+ yield(STARTED, name)
26
+ ivars_from_callback = @tests.first.run_all_callbacks(:before) if @tests.first.is_a?(Context.core_class)
27
+ @tests.each do |test|
28
+ test.set_values_from_callbacks(ivars_from_callback) if ivars_from_callback
29
+ test.run(result, &progress_block)
30
+ end
31
+ ivars_from_callback = @tests.first.run_all_callbacks(:after) if ivars_from_callback
32
+ yield(FINISHED, name)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,34 @@
1
+ module Context::TestCase::ClassMethods
2
+ # Create a test method. +name+ is a native-language string to describe the test
3
+ # (e.g., no more +test_this_crazy_thing_with_underscores+).
4
+ #
5
+ # test "A user should not be able to delete another user" do
6
+ # assert_false @user.can?(:delete, @other_user)
7
+ # end
8
+ #
9
+ def test(name, opts={}, &block)
10
+ test_name = ["test:", context_name, name].reject { |n| n == "" }.join(' ')
11
+ defined = instance_method(test_name) rescue false
12
+ raise "#{test_name} is already defined in #{self}" if defined
13
+
14
+ unless opts[:before].nil?
15
+ before_should_callbacks[test_name] = opts[:before]
16
+ end
17
+
18
+ if block_given?
19
+ define_method(test_name, &block)
20
+ else
21
+ define_method(test_name) do
22
+ flunk "No implementation provided for #{name}"
23
+ end
24
+ end
25
+ end
26
+
27
+ %w(it should tests).each {|m| alias_method m, :test}
28
+
29
+ def before_test(name, &block)
30
+ test(name, :before => block) {}
31
+ end
32
+
33
+ %w(before_it before_should before_tests).each {|m| alias_method m, :before_test}
34
+ end
@@ -0,0 +1,9 @@
1
+ module Context
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 5
5
+ TINY = 6
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,34 @@
1
+ desc 'Release the website and new gem version'
2
+ task :deploy => [:check_version, :website, :release] do
3
+ puts "Remember to create SVN tag:"
4
+ puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
5
+ "svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
6
+ puts "Suggested comment:"
7
+ puts "Tagging release #{CHANGES}"
8
+ end
9
+
10
+ desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
11
+ task :local_deploy => [:website_generate, :install_gem]
12
+
13
+ task :check_version do
14
+ unless ENV['VERSION']
15
+ puts 'Must pass a VERSION=x.y.z release version'
16
+ exit
17
+ end
18
+ unless ENV['VERSION'] == VERS
19
+ puts "Please update your version.rb to match the release version, currently #{VERS}"
20
+ exit
21
+ end
22
+ end
23
+
24
+ desc 'Install the package as a gem, without generating documentation(ri/rdoc)'
25
+ task :install_gem_no_doc => [:clean, :package] do
26
+ sh "#{'sudo ' unless Hoe::WINDOZE }gem install pkg/*.gem --no-rdoc --no-ri"
27
+ end
28
+
29
+ namespace :manifest do
30
+ desc 'Recreate Manifest.txt to include ALL files'
31
+ task :refresh do
32
+ `rake check_manifest | patch -p0 > Manifest.txt`
33
+ end
34
+ end