mcmire-context 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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