tu-context 0.5.7
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.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/History.txt +10 -0
- data/License.txt +20 -0
- data/Manifest.txt +30 -0
- data/PostInstall.txt +0 -0
- data/README.rdoc +159 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/config/hoe.rb +73 -0
- data/config/requirements.rb +15 -0
- data/context.gemspec +44 -0
- data/countloc.rb +65 -0
- data/lib/context.rb +19 -0
- data/lib/context/context.rb +64 -0
- data/lib/context/core_ext/rails_hacks.rb +10 -0
- data/lib/context/core_ext/string.rb +17 -0
- data/lib/context/lifecycle.rb +103 -0
- data/lib/context/shared_behavior.rb +97 -0
- data/lib/context/suite.rb +39 -0
- data/lib/context/test.rb +37 -0
- data/lib/context/version.rb +9 -0
- data/setup.rb +1585 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/test/test_context.rb +57 -0
- data/test/test_core_ext.rb +25 -0
- data/test/test_helper.rb +2 -0
- data/test/test_lifecycle.rb +224 -0
- data/test/test_nested_lifecycle.rb +44 -0
- data/test/test_shared.rb +116 -0
- data/test/test_shared_lifecycle.rb +24 -0
- data/test/test_test.rb +23 -0
- metadata +108 -0
data/countloc.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
def extract_path(argv)
|
3
|
+
if argv[1].nil?
|
4
|
+
if argv[0] =~ /-a/
|
5
|
+
return "/**/*.rb"
|
6
|
+
elsif argv[0]
|
7
|
+
if argv[0] =~ /\.rb$/
|
8
|
+
return argv[0]
|
9
|
+
end
|
10
|
+
return argv[0] + "/**/*.rb"
|
11
|
+
else
|
12
|
+
return "/**/*.rb"
|
13
|
+
end
|
14
|
+
elsif argv[1] =~ /\.rb$/
|
15
|
+
return argv[1]
|
16
|
+
else
|
17
|
+
return argv[1] + "/**/*.rb"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def all?
|
22
|
+
ARGV.join =~ /-a/
|
23
|
+
end
|
24
|
+
|
25
|
+
def comment?(line)
|
26
|
+
line =~ /^\s*#/
|
27
|
+
end
|
28
|
+
|
29
|
+
def blank?(line)
|
30
|
+
line =~ /^\s*$/
|
31
|
+
end
|
32
|
+
|
33
|
+
def puke(header, locs, comments, blanks)
|
34
|
+
puts header + ":"
|
35
|
+
puts "#{locs} loc"
|
36
|
+
puts "#{comments} lines of comments"
|
37
|
+
puts "#{blanks} blank lines"
|
38
|
+
end
|
39
|
+
|
40
|
+
dir = File.dirname(__FILE__)
|
41
|
+
full_path = File.join(dir,extract_path(ARGV))
|
42
|
+
gloc = gcmts = gblanks = 0
|
43
|
+
Dir[File.expand_path("#{full_path}")].uniq.each do |file|
|
44
|
+
if file =~ /.*\.rb$/
|
45
|
+
|
46
|
+
loc = cmts = blanks = 0
|
47
|
+
|
48
|
+
File.open(file, "r") do |f|
|
49
|
+
while f.gets
|
50
|
+
if comment?($_)
|
51
|
+
cmts += 1
|
52
|
+
elsif blank?($_)
|
53
|
+
blanks += 1
|
54
|
+
else
|
55
|
+
loc += 1
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
gcmts += cmts
|
60
|
+
gloc += loc
|
61
|
+
gblanks += blanks
|
62
|
+
puke(file, loc, cmts, blanks) if all?
|
63
|
+
end
|
64
|
+
end
|
65
|
+
puke("Total", gloc, gcmts, gblanks)
|
data/lib/context.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'test/unit'
|
6
|
+
|
7
|
+
require 'context/core_ext/string'
|
8
|
+
require 'context/core_ext/rails_hacks'
|
9
|
+
|
10
|
+
require 'context/version'
|
11
|
+
require 'context/suite'
|
12
|
+
require 'context/test'
|
13
|
+
require 'context/lifecycle'
|
14
|
+
require 'context/context'
|
15
|
+
require 'context/shared_behavior'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
extend Context::Context
|
19
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Context
|
2
|
+
module Context
|
3
|
+
# Test::Unit uses ObjectSpace to figure out what Test::Unit:TestCase instances are running
|
4
|
+
# Contexts are not named and therefore sometimes get garbage collected.
|
5
|
+
# Think of #context_list as the shelter for nameless contexts
|
6
|
+
attr_accessor :context_list
|
7
|
+
|
8
|
+
def context_name #:nodoc:
|
9
|
+
@context_name ||= ""
|
10
|
+
if superclass.respond_to?(:context_name)
|
11
|
+
return "#{superclass.context_name} #{@context_name}".gsub(/^\s+/, "")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def context_name=(val) #:nodoc:
|
16
|
+
@context_name = val
|
17
|
+
end
|
18
|
+
|
19
|
+
# Add a context to a set of tests.
|
20
|
+
#
|
21
|
+
# context "A new account" do
|
22
|
+
# it "should not have users"
|
23
|
+
# assert Account.new.users.empty?
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# The context name is prepended to the test name, so failures look like this:
|
28
|
+
#
|
29
|
+
# 1) Failure:
|
30
|
+
# test_a_new_account_should_not_have_users() [./test/test_accounts.rb:4]:
|
31
|
+
# <false> is not true.
|
32
|
+
#
|
33
|
+
# Contexts can also be nested like so:
|
34
|
+
#
|
35
|
+
# context "A new account" do
|
36
|
+
# context "created by the web application" do
|
37
|
+
# it "should have web as its vendor" do
|
38
|
+
# assert_equal "web", users(:web_user).vendor
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# Since contexts create a singleton instance of a class, each one must have its own before/after blocks. This
|
44
|
+
# will be tweaked in future releases to allow you to chain these blocks from its parent contexts.
|
45
|
+
#
|
46
|
+
def context(name, &block)
|
47
|
+
cls = Class.new(self)
|
48
|
+
cls.context_name = name
|
49
|
+
# puts "Creating context #{cls.context_name}"
|
50
|
+
|
51
|
+
# Care about Rails tests in nested contexts
|
52
|
+
cls.tests($1.constantize) if defined?(Rails) &&
|
53
|
+
self.name =~ /^(.*(Controller|Helper|Mailer))Test/ &&
|
54
|
+
self < ActiveSupport::TestCase
|
55
|
+
|
56
|
+
cls.class_eval(&block)
|
57
|
+
(self.context_list ||= []) << cls
|
58
|
+
const_set("Test#{name.to_class_name}#{cls.object_id.abs}", cls)
|
59
|
+
cls
|
60
|
+
end
|
61
|
+
|
62
|
+
%w(contexts describe describes group specify specifies).each {|m| alias_method m, :context}
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class 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
|
+
self.downcase.gsub(/[\s:',\.~;!#=\(\)&\?]+/, '_')
|
6
|
+
end
|
7
|
+
|
8
|
+
# Borrowed from +camelize+ in ActiveSupport
|
9
|
+
def to_module_name
|
10
|
+
self.to_method_name.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
11
|
+
end
|
12
|
+
|
13
|
+
# Borrowed from +camelize+ in ActiveSupport
|
14
|
+
def to_class_name
|
15
|
+
self.to_method_name.gsub(/\/(.?)/) { "#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
class Test::Unit::TestCase
|
2
|
+
class << self
|
3
|
+
attr_accessor :before_each_callbacks, :before_all_callbacks, :after_each_callbacks, :after_all_callbacks, :before_should_callbacks
|
4
|
+
|
5
|
+
# Add logic to run before the tests (i.e., a +setup+ method)
|
6
|
+
#
|
7
|
+
# before do
|
8
|
+
# @user = User.first
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
def before(period = :each, &block)
|
12
|
+
unless block_given?
|
13
|
+
block = period
|
14
|
+
period = :each
|
15
|
+
end
|
16
|
+
|
17
|
+
send("before_#{period}_callbacks") << block
|
18
|
+
end
|
19
|
+
|
20
|
+
alias :setup :before
|
21
|
+
|
22
|
+
# Add logic to run after the tests (i.e., a +teardown+ method)
|
23
|
+
#
|
24
|
+
# after do
|
25
|
+
# User.delete_all
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
def after(period = :each, &block)
|
29
|
+
unless block_given?
|
30
|
+
block = period
|
31
|
+
period = :each
|
32
|
+
end
|
33
|
+
|
34
|
+
send("after_#{period}_callbacks") << block
|
35
|
+
end
|
36
|
+
|
37
|
+
alias :teardown :after
|
38
|
+
|
39
|
+
def gather_callbacks(callback_type, period) # :nodoc:
|
40
|
+
callbacks = superclass.respond_to?(:gather_callbacks) ? superclass.gather_callbacks(callback_type, period) : []
|
41
|
+
callbacks.push(*send("#{callback_type}_#{period}_callbacks"))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
self.before_all_callbacks = []
|
46
|
+
self.before_each_callbacks = []
|
47
|
+
self.after_each_callbacks = []
|
48
|
+
self.after_all_callbacks = []
|
49
|
+
self.before_should_callbacks = {}
|
50
|
+
|
51
|
+
def self.inherited(child) # :nodoc:
|
52
|
+
super
|
53
|
+
child.before_all_callbacks = []
|
54
|
+
child.before_each_callbacks = []
|
55
|
+
child.after_each_callbacks = []
|
56
|
+
child.after_all_callbacks = []
|
57
|
+
child.before_should_callbacks = {}
|
58
|
+
|
59
|
+
child.class_eval do
|
60
|
+
def setup(&block)
|
61
|
+
super
|
62
|
+
|
63
|
+
unless self.class.before_should_callbacks[method_name].nil?
|
64
|
+
instance_eval(&self.class.before_should_callbacks[method_name])
|
65
|
+
end
|
66
|
+
|
67
|
+
run_each_callbacks :before
|
68
|
+
end
|
69
|
+
|
70
|
+
def teardown
|
71
|
+
super
|
72
|
+
|
73
|
+
run_each_callbacks :after
|
74
|
+
end
|
75
|
+
end if self == Test::Unit::TestCase
|
76
|
+
end
|
77
|
+
|
78
|
+
def run_each_callbacks(callback_type) # :nodoc:
|
79
|
+
self.class.gather_callbacks(callback_type, :each).each do |c|
|
80
|
+
c.is_a?(Proc) ? instance_eval(&c) : send(c)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def run_all_callbacks(callback_type) # :nodoc:
|
85
|
+
previous_ivars = instance_variables
|
86
|
+
self.class.gather_callbacks(callback_type, :all).each { |c| instance_eval(&c) if c }
|
87
|
+
(instance_variables - previous_ivars).inject({}) do |hash, ivar|
|
88
|
+
hash.update ivar => instance_variable_get(ivar)
|
89
|
+
end
|
90
|
+
rescue Object => exception
|
91
|
+
raise <<-BANG
|
92
|
+
Error running the #{callback_type}(:all) callback for #{name}
|
93
|
+
#{exception.class.name}: #{exception.message}
|
94
|
+
#{exception.backtrace.join("\n")}
|
95
|
+
BANG
|
96
|
+
end
|
97
|
+
|
98
|
+
def set_values_from_callbacks(values) # :nodoc:
|
99
|
+
values.each do |name, value|
|
100
|
+
instance_variable_set name, value
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Context
|
2
|
+
class SharedBehavior < Module
|
3
|
+
def self.create_from_behavior(beh) # :nodoc:
|
4
|
+
mod = self.new
|
5
|
+
mod._behavior = beh
|
6
|
+
mod
|
7
|
+
end
|
8
|
+
|
9
|
+
def _behavior=(beh) # :nodoc:
|
10
|
+
@_behavior = beh
|
11
|
+
end
|
12
|
+
|
13
|
+
def included(including_module) # :nodoc:
|
14
|
+
including_module.class_eval(&@_behavior)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Test::Unit::TestCase
|
20
|
+
class << self
|
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
|
97
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Test
|
2
|
+
module Unit
|
3
|
+
class TestCase
|
4
|
+
class << self
|
5
|
+
# Tweaks to standard method so we don't get superclass methods and we don't
|
6
|
+
# get weird default tests
|
7
|
+
def suite # :nodoc:
|
8
|
+
method_names = public_instance_methods - superclass.public_instance_methods
|
9
|
+
|
10
|
+
tests = method_names.delete_if {|method_name| method_name !~ /^test./}
|
11
|
+
suite = Test::Unit::TestSuite.new(name)
|
12
|
+
|
13
|
+
tests.sort.each do |test|
|
14
|
+
catch(:invalid_test) do
|
15
|
+
suite << new(test)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
suite
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class TestSuite
|
25
|
+
# Runs the tests and/or suites contained in this
|
26
|
+
# TestSuite.
|
27
|
+
def run(result, &progress_block) # :nodoc:
|
28
|
+
yield(STARTED, name)
|
29
|
+
ivars_from_callback = @tests.first.run_all_callbacks(:before) if @tests.first.is_a?(Test::Unit::TestCase)
|
30
|
+
@tests.each do |test|
|
31
|
+
test.set_values_from_callbacks(ivars_from_callback) if ivars_from_callback
|
32
|
+
test.run(result, &progress_block)
|
33
|
+
end
|
34
|
+
ivars_from_callback = @tests.first.run_all_callbacks(:after) if ivars_from_callback
|
35
|
+
yield(FINISHED, name)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/context/test.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
class Test::Unit::TestCase
|
2
|
+
class << self
|
3
|
+
# Create a test method. +name+ is a native-language string to describe the test
|
4
|
+
# (e.g., no more +test_this_crazy_thing_with_underscores+).
|
5
|
+
#
|
6
|
+
# test "A user should not be able to delete another user" do
|
7
|
+
# assert_false @user.can?(:delete, @other_user)
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
def test(name, opts={}, &block)
|
11
|
+
test_name = ["test:", context_name, name].reject { |n| n == "" }.join(' ')
|
12
|
+
# puts "running test #{test_name}"
|
13
|
+
defined = instance_method(test_name) rescue false
|
14
|
+
raise "#{test_name} is already defined in #{self}" if defined
|
15
|
+
|
16
|
+
unless opts[:before].nil?
|
17
|
+
before_should_callbacks[test_name] = opts[:before]
|
18
|
+
end
|
19
|
+
|
20
|
+
if block_given?
|
21
|
+
define_method(test_name, &block)
|
22
|
+
else
|
23
|
+
define_method(test_name) do
|
24
|
+
flunk "No implementation provided for #{name}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
%w(it should tests).each {|m| alias_method m, :test}
|
30
|
+
|
31
|
+
def before_test(name, &block)
|
32
|
+
test(name, :before => block) {}
|
33
|
+
end
|
34
|
+
|
35
|
+
%w(before_it before_should before_tests).each {|m| alias_method m, :before_test}
|
36
|
+
end
|
37
|
+
end
|