Exspec 1.0.1

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/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