Exspec 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/bin/exspec ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "exspec"
4
+
5
+ if ARGV.empty?
6
+ started = Exspec::Extension.start_exspec
7
+ Exspec::IrbExspec.start_irb unless started
8
+ else
9
+ exspec = Exspec::Exspec.new
10
+
11
+ spec_arg = ARGV.join " "
12
+ spec = exspec.spec spec_arg
13
+
14
+ reporter = Exspec::REGRESSION_TEST_REPORTER.new
15
+ if !spec.nil? && spec.exist?
16
+ exspec.report_to(reporter) { exspec.run_stack spec }
17
+ else
18
+ specs = exspec.specs spec_arg, true
19
+ specs.each do |spec|
20
+ spec.stack.each do |parent|
21
+ if parent != spec
22
+ specs.delete(parent)
23
+ end
24
+ end
25
+ end
26
+ exspec.report_to(reporter) { exspec.run_specs specs }
27
+ end
28
+
29
+ failed = reporter.failed
30
+ puts "#{failed.length} of #{reporter.specs.length} specs failed" + (failed.empty? ? "!" : ":")
31
+ reporter.failed.each do |spec|
32
+ puts "- #{spec.full_description}"
33
+ end
34
+ end
@@ -0,0 +1,75 @@
1
+ module Exspec
2
+ class ContextManager
3
+ def initialize(exspec)
4
+ @exspec = exspec
5
+ @global_context = context
6
+ setup_global_context
7
+ setup_exspec_context
8
+ start_new_context
9
+ end
10
+
11
+ attr_reader :exspec, :last_value
12
+ attr_accessor :last_exspec_value
13
+
14
+ def start_new_context
15
+ context = global_eval "lambda { binding }.call"
16
+ self.context = context
17
+ Extension.setup_context self
18
+ context
19
+ end
20
+
21
+ def context
22
+ @binding ||= Object.new.instance_eval "binding"
23
+ end
24
+
25
+ def context=(value)
26
+ @binding = value
27
+ end
28
+
29
+ def last_value=(value)
30
+ @last_value=value
31
+ global_eval "_ = exspec.last_value"
32
+ value
33
+ end
34
+
35
+ def last_exspec_value
36
+ @last_exspec_value
37
+ end
38
+
39
+ def last_exspec_value=(value)
40
+ @last_exspec_value = value
41
+ exspec_eval "_ = exspec.last_exspec_value"
42
+ end
43
+
44
+ def eval(statement)
45
+ self.last_value = raw_eval statement
46
+ end
47
+
48
+ def raw_eval(statement)
49
+ context.eval statement
50
+ end
51
+
52
+ def global_eval(statement)
53
+ @global_context.eval statement
54
+ end
55
+
56
+ def exspec_eval(statement)
57
+ @exspec_context.eval statement
58
+ end
59
+
60
+ private
61
+
62
+ def setup_global_context
63
+ global_instance = global_eval "self"
64
+ global_instance.instance_variable_set :@exspec, @exspec
65
+ global_instance.class.send :attr_reader, :exspec
66
+ global_eval "_ = nil"
67
+ Extension.setup_global_context self
68
+ end
69
+
70
+ def setup_exspec_context
71
+ @exspec_context = global_eval "lambda { |_| binding }.call nil"
72
+ Extension.setup_exspec_context self
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,24 @@
1
+ module Exspec
2
+ class ExecuteCallbacks
3
+ def initialize
4
+ @before = []
5
+ @after = []
6
+ end
7
+
8
+ def before(command=nil, params=nil, &block)
9
+ if block_given?
10
+ @before << block
11
+ else
12
+ @before.each { |proc| proc.call(command, params) }
13
+ end
14
+ end
15
+
16
+ def after(command=nil, params=nil, value=nil, &block)
17
+ if block_given?
18
+ @after << block
19
+ else
20
+ @after.each { |proc| proc.call(command, params, value) }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,227 @@
1
+ require_relative "execute_callbacks"
2
+
3
+ module Exspec
4
+ class Executor
5
+ def initialize(exspec)
6
+ @exspec = exspec
7
+ end
8
+
9
+ delegate :puts, :print, :return_spec, :context, :to => :@exspec
10
+ attr_reader :exspec
11
+
12
+ def eval(instruction, &callback_block)
13
+ callbacks = ExecuteCallbacks.new
14
+ Extension.set_execute_callbacks callbacks
15
+ callback_block.call callbacks if block_given?
16
+ instruction.strip!
17
+ eval = true
18
+ val = nil
19
+ if instruction.start_with? COMMAND_PREFIX
20
+ parts = instruction.split " "
21
+ command = parts[0][1..-1]
22
+ param_string = parts[1..-1].join " "
23
+ eval = false
24
+ val = Extension.execute_command self, command, param_string, callbacks
25
+ if val.nil?
26
+ val = case command
27
+ when ""
28
+ execute(command, parameters(param_string), callbacks) do
29
+ exspec.exspec_eval param_string
30
+ end
31
+ when "_"
32
+ execute(command, parameters(param_string), callbacks) do
33
+ exspec.last_exspec_value
34
+ end
35
+ when "inspect"
36
+ execute(command, callbacks) do
37
+ exspec.inspect_last_value
38
+ end
39
+ when "redo"
40
+ execute(command, callbacks) do
41
+ exspec.redo
42
+ end
43
+ when "retry", "rerun", "again"
44
+ execute(command, callbacks) do
45
+ exspec.retry
46
+ end
47
+ when "save"
48
+ execute(command, parameters(param_string, COMMENT_SIGN), callbacks) do |params|
49
+ exspec.save *params
50
+ end
51
+ when "include", "call", "include_segment", "call_segment"
52
+ execute(command, parameters(param_string), callbacks) do |params|
53
+ exspec.include *params
54
+ end
55
+ when "run", "run_spec", "run_segment"
56
+ execute(command, parameters(param_string), callbacks) do |params|
57
+ exspec.run *params
58
+ end
59
+ when "run_stack"
60
+ execute(command, parameters(param_string), callbacks) do |params|
61
+ exspec.run_stack *params
62
+ end
63
+ when "load"
64
+ execute(command, parameters(param_string), callbacks) do |params|
65
+ exspec.load *params
66
+ end
67
+ when "comment", "#"
68
+ execute(command, parameters(param_string), callbacks) do |params|
69
+ exspec.comment *params
70
+ end
71
+ when "assert"
72
+ execute(command, parameters(param_string, COMMENT_SIGN), callbacks) do |params|
73
+ exspec.assert *params
74
+ end
75
+ when "expect"
76
+ execute(command, parameters(param_string, COMMENT_SIGN), callbacks) do |params|
77
+ exspec.expect *params
78
+ end
79
+ when "expect_inspect"
80
+ execute(command, parameters(param_string, COMMENT_SIGN), callbacks) do |params|
81
+ exspec.expect_inspect *params
82
+ end
83
+ when "skip"
84
+ execute(command, callbacks) do
85
+ SkipSignal
86
+ end
87
+ when "load_current", "reload_current", "discard"
88
+ execute(command, callbacks) do
89
+ exspec.load exspec.current_spec
90
+ end
91
+ when "load_parent", "up", "independent"
92
+ execute(command, callbacks) do
93
+ spec = exspec.current_spec
94
+ spec = spec.parent unless spec.nil?
95
+ exspec.load spec
96
+ end
97
+ when "load#"
98
+ execute(command, parameters(param_string), callbacks) do |params|
99
+ menu_action(params, Spec) { |spec| spec.load }
100
+ end
101
+ when "run#", "run_spec#", "run_segment#"
102
+ execute(command, parameters(param_string), callbacks) do |params|
103
+ menu_action(params, Spec) { |spec| spec.run }
104
+ end
105
+ when "run_stack#"
106
+ execute(command, parameters(param_string), callbacks) do |params|
107
+ menu_action(params, Spec) { |spec| spec.run_stack }
108
+ end
109
+ when "include#", "include_segment#", "call#", "call_segment#"
110
+ execute(command, parameters(param_string), callbacks) do |params|
111
+ menu_action(params, Spec) { |spec| spec.include }
112
+ end
113
+ when "ignore", "erase", "delete"
114
+ execute(command, callbacks) do
115
+ exspec.erase_last_instruction
116
+ return_spec exspec.logger.last_value
117
+ end
118
+ when "ignore#", "erase#", "delete#"
119
+ execute(command, parameters(param_string), callbacks) do |params|
120
+ menu_action(params) do |entry|
121
+ exspec.logger.entries.delete entry
122
+ end
123
+ return_spec exspec.logger.last_value
124
+ end
125
+ when "reset", "clear"
126
+ execute(command, callbacks) do
127
+ exspec.reset
128
+ end
129
+ when "log", "instructions", "history"
130
+ execute(command, callbacks) do
131
+ menu(exspec.logger.entries) { |entry| entry[:instruction] }
132
+ end
133
+ when "stack"
134
+ execute(command, callbacks) do
135
+ menu(exspec.current_spec && exspec.current_spec.stack) do |spec|
136
+ spec.name
137
+ end
138
+ end
139
+ when "specs", "tests"
140
+ execute(command, parameters(param_string), callbacks) do |params|
141
+ menu(exspec.specs *params) { |spec| spec.name }
142
+ end
143
+ when "specs#", "tests#"
144
+ execute(command, parameters(param_string), callbacks) do |params|
145
+ menu_action(params, Spec) do |spec|
146
+ menu(spec.children) { |spec| spec.name }
147
+ end
148
+ end
149
+ when "no_log", "without_logging", "silent"
150
+ val = exspec.without_logging { exspec.execute param_string }
151
+ return_spec exspec.logger.last_value
152
+ val
153
+ when "log_off", "disable_log"
154
+ execute(command, callbacks) do
155
+ exspec.logger.enabled = false
156
+ exspec.last_value
157
+ end
158
+ when "log_on", "enable_log"
159
+ execute(command, callbacks) do
160
+ exspec.logger.enabled = true
161
+ return_spec exspec.logger.last_value
162
+ end
163
+ else
164
+ eval = true
165
+ end
166
+ end
167
+ end
168
+ if eval
169
+ val = execute(callbacks) do
170
+ exspec.eval instruction
171
+ end
172
+ end
173
+ val
174
+ end
175
+
176
+ private
177
+
178
+ def menu(options=nil)
179
+ return @menu || [] unless options.is_a?(Array)
180
+ @menu = options
181
+ puts '====================================='
182
+ @menu.each.with_index do |option, index|
183
+ puts "#{index}. #{block_given? ? yield(option) : option}"
184
+ end
185
+ puts '====================================='
186
+ @menu
187
+ end
188
+
189
+ def menu_action(params, type=nil)
190
+ index = params.is_a?(Array) ? params[0] : nil
191
+ return nil if index.nil?
192
+ index = index.to_i
193
+ element = menu[index]
194
+ return element unless type.nil? || element.is_a?(type)
195
+ yield element, index
196
+ end
197
+
198
+ def execute(command=nil, params=nil, callbacks, &execute)
199
+ val = nil
200
+ callbacks.before command, params
201
+ begin
202
+ val = execute.call params
203
+ rescue Exception => e
204
+ val = e
205
+ raise
206
+ ensure
207
+ callbacks.after command, params, val
208
+ end
209
+ val
210
+ end
211
+
212
+ def parameters(param_string, *separators)
213
+ param_string.strip!
214
+ params = []
215
+ separators.each do |separator|
216
+ parts = " #{param_string}".split separator
217
+ if parts.length > 1
218
+ param = parts[0].strip
219
+ params << (param.empty? ? nil : param)
220
+ param_string = parts[1..-1].join(separator).strip
221
+ end
222
+ end
223
+ params << (param_string.empty? ? nil : param_string)
224
+ params.reverse.drop_while(&:nil?).reverse
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,70 @@
1
+ module Exspec::Extension
2
+ @@module = self
3
+ @@extensions = {}
4
+
5
+ def self.loaded
6
+ apply :loaded
7
+ end
8
+
9
+ def self.config(config)
10
+ apply :config, nil, false, config
11
+ end
12
+
13
+ def self.start_exspec
14
+ apply :start_exspec, nil, true
15
+ end
16
+
17
+ def self.set_execute_callbacks(options)
18
+ apply :set_execute_callbacks, nil, false, options
19
+ end
20
+
21
+ def self.initialize_exspec(exspec, components)
22
+ apply :initialize_exspec, exspec, false, components
23
+ end
24
+
25
+ def self.execute_command(executor, command, param_string, options)
26
+ apply :execute_command, executor, true, command, param_string, options
27
+ end
28
+
29
+ def self.setup_context(context_manager)
30
+ apply :setup_context, context_manager
31
+ end
32
+
33
+ def self.setup_global_context(context_manager)
34
+ apply :setup_global_context, context_manager
35
+ end
36
+
37
+ def self.setup_exspec_context(context_manager)
38
+ apply :setup_exspec_context, context_manager
39
+ end
40
+
41
+ def self.apply(extension_point, extended_instance=nil, return_first=false, *args)
42
+ extensions(extension_point).each do |extension|
43
+ val = if extended_instance
44
+ extended_instance.instance_exec *args, &extension
45
+ else
46
+ extension.call *args
47
+ end
48
+ return val if return_first && !val.nil?
49
+ end
50
+ return nil
51
+ end
52
+
53
+ def self.extensions(extension_point)
54
+ extension_point = extension_point.to_sym
55
+ extensions = (@@extensions[extension_point] = []) unless extensions = @@extensions[extension_point]
56
+ extensions
57
+ end
58
+
59
+ def method_missing(method, *args, &block)
60
+ def_extension method, block
61
+ end
62
+
63
+ def extensions(extension_point)
64
+ @@module.extensions extension_point
65
+ end
66
+
67
+ def def_extension(extension_point, block)
68
+ extensions(extension_point.to_sym) << block
69
+ end
70
+ end
@@ -0,0 +1,125 @@
1
+ module Exspec::Mocking
2
+ extend Exspec::Extension
3
+
4
+ execute_command do |command, param_string, options|
5
+ case command
6
+ when "mock", "stub"
7
+ execute(command, parameters(param_string), options) do |params|
8
+ if params.empty?
9
+ exspec.commit "#{Exspec::COMMAND_PREFIX}mock", Mock.new
10
+ else
11
+ mock_var = params[0]
12
+ exspec.commit "#{Exspec::COMMAND_PREFIX}mock #{mock_var}"
13
+ puts "assigning #{command} to #{mock_var}"
14
+ context.raw_eval "#{mock_var} = #{Mock.name}.new"
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ class Mock < BasicObject
21
+ def initialize
22
+ @methods = {}
23
+ @attributes = {}
24
+ @children = {}
25
+ @method_calls = []
26
+ end
27
+
28
+ def new(*args, &block)
29
+ _log_call :new, args, block
30
+ _defined?(:new) ? _call(:new, *args, &block) : self
31
+ end
32
+
33
+ def ==(*args, &block)
34
+ _log_call :==, args, block
35
+ _defined?(:==) ? _call(:==, *args, &block) : false
36
+ end
37
+
38
+ def inspect(*args, &block)
39
+ _log_call :inspect, args, block
40
+ _defined?(:inspect) ? _call(:inspect, *args, &block) : "#<Exspec Mock>"
41
+ end
42
+
43
+ def to_s(*args, &block)
44
+ _log_call :to_s, args, block
45
+ _defined?(:to_s) ? _call(:to_s, *args, &block) : "Exspec Mock"
46
+ end
47
+
48
+ def nil?(*args, &block)
49
+ _log_call :nil?, args, block
50
+ _defined?(:nil?) ? _call(:nil?, *args, &block) : false
51
+ end
52
+
53
+ def _def(method, &body)
54
+ @methods[method.to_sym] = body
55
+ end
56
+
57
+ def _defined?(method)
58
+ @methods.include? method.to_sym
59
+ end
60
+
61
+ def _method_calls(method=nil)
62
+ if method.nil?
63
+ @method_calls
64
+ else
65
+ @method_calls.select { |call| call[:method] == method.to_sym }
66
+ end
67
+ end
68
+
69
+ def _have_been_called?(method)
70
+ @method_calls.any? { |call| call[:method] == method.to_sym }
71
+ end
72
+
73
+ def _times_called(method)
74
+ @method_calls.count { |call| call[:method] == method.to_sym }
75
+ end
76
+
77
+ def _first_call(method)
78
+ @method_calls.find { |call| call[:method] == method.to_sym }
79
+ end
80
+
81
+ def _last_call(method)
82
+ @method_calls.reverse.find { |call| call[:method] == method.to_sym }
83
+ end
84
+
85
+ def _log_call(method, args, block)
86
+ @method_calls << { :method => method.to_sym, :args => args, :block => block }
87
+ end
88
+
89
+ def _attribute_set?(attribute)
90
+ @attributes.include? attribute.to_sym
91
+ end
92
+
93
+ def _attribute(attribute)
94
+ @attributes[attribute.to_sym]
95
+ end
96
+
97
+ def _set_attribute(attribute, value)
98
+ @attributes[attribute.to_sym] = value
99
+ end
100
+
101
+ def _child(name)
102
+ name = name.to_sym
103
+ if @children.include? name
104
+ @attributes[name]
105
+ else
106
+ @attributes[name] = Mock.new
107
+ end
108
+ end
109
+
110
+ def _call(method, *args, &block)
111
+ return @methods[method.to_sym].call (args + [block]) if _defined? method
112
+ if method.to_s.end_with?("=") && !args.empty?
113
+ return _set_attribute(method.to_s.chop, args[0])
114
+ elsif _attribute_set?(method)
115
+ return _attribute(method)
116
+ end
117
+ _child(method)
118
+ end
119
+
120
+ def method_missing(method, *args, &block)
121
+ _log_call method, args, block
122
+ _call(method, *args, &block)
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,78 @@
1
+ module Exspec::Rails
2
+ extend Exspec::Extension
3
+
4
+ @@rails = self
5
+ @@app_path = nil
6
+ @@enabled = true
7
+
8
+ def self.enabled=(value)
9
+ @@enabled = value
10
+ end
11
+
12
+ def self.is_available?
13
+ return @@enabled && !!app_path
14
+ end
15
+
16
+ def self.app_path
17
+ return @@app_path if @@app_path
18
+ parent_dirs do |path|
19
+ if File.file?(File.expand_path("config/boot.rb", path)) && File.file?(File.expand_path("config/application.rb", path))
20
+ @@app_path = path
21
+ return @@app_path
22
+ end
23
+ end
24
+ nil
25
+ end
26
+
27
+ def self.start_console
28
+ if is_available?
29
+ begin
30
+ require_environment
31
+ ::Rails::Console.start(::Rails.application)
32
+ return true
33
+ rescue Exception => e
34
+ @@enabled = false
35
+ end
36
+ end
37
+ return false
38
+ end
39
+
40
+ def self.require_environment
41
+ if is_available?
42
+ begin
43
+ require "rails"
44
+ require "rails/commands/console"
45
+ require File.expand_path("config/boot", app_path)
46
+ require File.expand_path("config/application", app_path)
47
+ ::Rails.application.require_environment!
48
+ rescue Exception => e
49
+ @@enabled = false
50
+ end
51
+ end
52
+ end
53
+
54
+ config do |config|
55
+ if is_available?
56
+ config[:test_dir] = File.expand_path(config[:test_dir], app_path)
57
+ end
58
+ end
59
+
60
+ setup_global_context do
61
+ @@rails.require_environment
62
+ end
63
+
64
+ setup_context do
65
+ if @@rails.is_available?
66
+ begin
67
+ ::ActionDispatch::Reloader.cleanup!
68
+ ::ActionDispatch::Reloader.prepare!
69
+ rescue Exception => e
70
+ @@enabled = false
71
+ end
72
+ end
73
+ end
74
+
75
+ start_irb do
76
+ start_console
77
+ end
78
+ end
@@ -0,0 +1,10 @@
1
+ def parent_dirs
2
+ root = File.expand_path "/"
3
+ level = 0
4
+ begin
5
+ relative = "../" * level
6
+ path = File.expand_path relative
7
+ yield path
8
+ level += 1
9
+ end until path == root
10
+ end
@@ -0,0 +1,35 @@
1
+ require_relative "../context_manager"
2
+
3
+ module Exspec
4
+ class IrbContextManager < ContextManager
5
+ delegate :irb_workspace, :irb_context, :to => :exspec
6
+
7
+ def context
8
+ irb_workspace.binding
9
+ end
10
+
11
+ def context=(value)
12
+ irb_workspace.instance_variable_set(:@binding, value)
13
+ end
14
+
15
+ def last_output
16
+ irb_context.inspect_last_value
17
+ end
18
+
19
+ def last_value
20
+ irb_context.last_value
21
+ end
22
+
23
+ def last_value=(value)
24
+ irb_context.set_last_value(value)
25
+ end
26
+
27
+ def define_eval(&eval)
28
+ @eval = eval
29
+ end
30
+
31
+ def eval(instruction)
32
+ @eval.call instruction
33
+ end
34
+ end
35
+ end