motion-spec 0.1.0

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,92 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # MotionSpec is built off of MacBacon, which is derived from Bacon, which is a
3
+ # micro-port of Rspec. See the LICENSE for core contributors and copyright years
4
+
5
+ module MotionSpec
6
+ DEFAULT_OUTPUT_MODULE = SpecDoxOutput
7
+
8
+ Counter = Hash.new(0)
9
+ ErrorLog = ''
10
+ Shared = Hash.new { |_, name|
11
+ raise NameError, "no such context: #{name.inspect}"
12
+ }
13
+
14
+ RestrictName = // unless defined? RestrictName
15
+ RestrictContext = // unless defined? RestrictContext
16
+
17
+ Backtraces = true unless defined? Backtraces
18
+
19
+ Outputs = {
20
+ 'spec_dox' => SpecDoxOutput,
21
+ 'fast' => FastOutput,
22
+ 'test_unit' => TestUnitOutput,
23
+ 'tap' => TapOutput,
24
+ 'knock' => KnockOutput,
25
+ 'rubymine' => RubyMineOutput,
26
+ 'colorized' => ColorizedOutput
27
+ }
28
+
29
+ def self.add_context(context)
30
+ (@contexts ||= []) << context
31
+ end
32
+
33
+ def self.current_context_index
34
+ @current_context_index ||= 0
35
+ end
36
+
37
+ def self.current_context
38
+ @contexts[current_context_index]
39
+ end
40
+
41
+ def self.run(arg = nil)
42
+ unless respond_to?(:handle_specification_begin)
43
+ extend(Outputs[ENV['output']] || DEFAULT_OUTPUT_MODULE)
44
+ end
45
+
46
+ @timer ||= Time.now
47
+
48
+ if Platform.android?
49
+ @main_activity ||= arg
50
+
51
+ @contexts.each { |context| execute_context(context) }
52
+ return handle_summary
53
+ end
54
+
55
+ Counter[:context_depth] += 1
56
+ handle_specification_begin(current_context.name)
57
+ current_context.performSelector('run', withObject: nil, afterDelay: 0)
58
+ end
59
+
60
+ def self.execute_context(context)
61
+ unless respond_to?(:handle_specification_begin)
62
+ extend(Outputs[ENV['output']] || DEFAULT_OUTPUT_MODULE)
63
+ end
64
+
65
+ Counter[:context_depth] += 1
66
+ handle_specification_begin(context.name)
67
+ context.run
68
+ handle_specification_end
69
+ Counter[:context_depth] -= 1
70
+ end
71
+
72
+ # Android-only.
73
+ def self.main_activity
74
+ @main_activity
75
+ end
76
+
77
+ def self.context_did_finish(context)
78
+ return if Platform.android?
79
+
80
+ handle_specification_end
81
+
82
+ Counter[:context_depth] -= 1
83
+
84
+ if (@current_context_index + 1) < @contexts.size
85
+ @current_context_index += 1
86
+ return run
87
+ end
88
+
89
+ handle_summary
90
+ exit(Counter.values_at(:failed, :errors).inject(:+))
91
+ end
92
+ end
@@ -0,0 +1,11 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ class Error < RuntimeError
4
+ attr_accessor :count_as
5
+
6
+ def initialize(count_as, message)
7
+ @count_as = count_as
8
+ super message
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ # -*- encoding : utf-8 -*-
2
+ class Object
3
+ def true?; false; end
4
+ def false?; false; end
5
+ end
6
+
7
+ class TrueClass
8
+ def true?; true; end
9
+ end
10
+
11
+ class FalseClass
12
+ def false?; true; end
13
+ end
@@ -0,0 +1,2 @@
1
+ # -*- encoding : utf-8 -*-
2
+ Exception.log_exceptions = false if Exception.respond_to? :log_exceptions
@@ -0,0 +1,13 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Kernel
3
+ private
4
+
5
+ def describe(*args, &block)
6
+ MotionSpec::Context.new(args.join(' '), &block)
7
+ end
8
+ alias_method :context, :describe
9
+
10
+ def shared(name, &block)
11
+ MotionSpec::Shared[name] = block
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ # -*- encoding : utf-8 -*-
2
+ class Numeric
3
+ def close?(to, delta)
4
+ (to.to_f - self).abs <= delta.to_f rescue false
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ # -*- encoding : utf-8 -*-
2
+ class Object
3
+ def should(*args, &block)
4
+ MotionSpec::Should.new(self).be(*args, &block)
5
+ end
6
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding : utf-8 -*-
2
+ class Proc
3
+ def raise?(*exceptions)
4
+ call
5
+ rescue *(exceptions.empty? ? RuntimeError : exceptions) => e
6
+ e
7
+ else
8
+ false
9
+ end
10
+
11
+ def throw?(sym)
12
+ catch(sym) {
13
+ call
14
+ return false
15
+ }
16
+ true
17
+ end
18
+
19
+ def change?
20
+ pre_result = yield
21
+ call
22
+ post_result = yield
23
+ pre_result != post_result
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module ColorizedOutput
4
+ GREEN = "\033[0;32m"
5
+ RED = "\033[0;31m"
6
+ RESET = "\033[00m"
7
+
8
+ def handle_specification_begin(name); end
9
+ def handle_specification_end; end
10
+
11
+ def handle_requirement_begin(description); end
12
+
13
+ def handle_requirement_end(error)
14
+ if error.empty?
15
+ print "#{GREEN}.#{RESET}"
16
+ else
17
+ print "#{RED}#{error[0..0]}#{RESET}"
18
+ end
19
+ end
20
+
21
+ def handle_summary
22
+ puts ''
23
+ puts '', ErrorLog if Backtraces && !ErrorLog.empty?
24
+
25
+ duration = '%0.2f' % (Time.now - @timer)
26
+ puts '', "Finished in #{duration} seconds."
27
+
28
+ failure = Counter[:errors] > 0 || Counter[:failed] > 0
29
+ color = failure ? RED : GREEN
30
+
31
+ puts "#{color}%d tests, %d assertions, %d failures, %d errors#{RESET}" %
32
+ Counter.values_at(:specifications, :requirements, :failed, :errors)
33
+ puts ''
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module FastOutput
4
+ def handle_specification_begin(name); end
5
+ def handle_specification_end; end
6
+
7
+ def handle_requirement_begin(description); end
8
+
9
+ def handle_requirement_end(error)
10
+ return if error.empty?
11
+ print error[0..0]
12
+ end
13
+
14
+ def handle_summary
15
+ puts '', "Finished in #{Time.now - @timer} seconds."
16
+ puts ErrorLog if Backtraces
17
+ puts '%d tests, %d assertions, %d failures, %d errors' %
18
+ Counter.values_at(:specifications, :requirements, :failed, :errors)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module KnockOutput
4
+ def handle_specification_begin(name); end
5
+ def handle_specification_end; end
6
+
7
+ def handle_requirement_begin(description)
8
+ @description = description
9
+ ErrorLog.replace ''
10
+ end
11
+
12
+ def handle_requirement_end(error)
13
+ if error.empty?
14
+ puts 'ok - %s' % [@description]
15
+ else
16
+ puts 'not ok - %s: %s' % [@description, error]
17
+ puts ErrorLog.strip.gsub(/^/, '# ') if Backtraces
18
+ end
19
+ end
20
+
21
+ def handle_summary; end
22
+ end
23
+ end
@@ -0,0 +1,86 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module RubyMineOutput
4
+ @@entered = false
5
+ @@description = nil
6
+ @@specification = nil
7
+ @@started = nil
8
+
9
+ def handle_specification_begin(name)
10
+ unless @@entered
11
+ puts "##teamcity[enteredTheMatrix timestamp = '#{java_time}']\n\n"
12
+ @@entered = true
13
+ end
14
+ @@specification = name
15
+ puts "##teamcity[testSuiteStarted timestamp = '#{java_time}' name = '#{escape_message(name)}']\n\n"
16
+ end
17
+
18
+ def handle_specification_end
19
+ puts "##teamcity[testSuiteFinished timestamp = '#{java_time}' name = '#{escape_message(@@specification)}']\n\n" if Counter[:context_depth] == 1
20
+ end
21
+
22
+ def handle_requirement_begin(description)
23
+ @@description = description
24
+ @@started = Time.now
25
+ puts "##teamcity[testStarted timestamp = '#{java_time}' captureStandardOutput = 'true' name = '#{escape_message(description)}']\n\n"
26
+ end
27
+
28
+ def handle_requirement_end(error)
29
+ if !error.empty?
30
+ puts "##teamcity[testFailed timestamp = '#{java_time}' message = '#{escape_message(error)}' name = '#{escape_message(@@description)}']\n\n"
31
+ end
32
+ duration = ((Time.now - @@started) * 1000).to_i
33
+ puts "##teamcity[testFinished timestamp = '#{java_time}' duration = '#{duration}' name = '#{escape_message(@@description)}']\n\n"
34
+ end
35
+
36
+ def handle_summary
37
+ print ErrorLog if Backtraces
38
+ puts '%d specifications (%d requirements), %d failures, %d errors' %
39
+ Counter.values_at(:specifications, :requirements, :failed, :errors)
40
+ end
41
+
42
+ def spaces
43
+ ' ' * (Counter[:context_depth] - 1)
44
+ end
45
+
46
+ def java_time
47
+ convert_time_to_java_simple_date(Time.now)
48
+ end
49
+
50
+ def escape_message(message)
51
+ copy_of_text = String.new(message)
52
+
53
+ copy_of_text.gsub!(/\|/, '||')
54
+
55
+ copy_of_text.gsub!(/'/, "|'")
56
+ copy_of_text.gsub!(/\n/, '|n')
57
+ copy_of_text.gsub!(/\r/, '|r')
58
+ copy_of_text.gsub!(/\]/, '|]')
59
+
60
+ copy_of_text.gsub!(/\[/, '|[')
61
+
62
+ begin
63
+ copy_of_text.encode!('UTF-8') if copy_of_text.respond_to? :encode!
64
+ copy_of_text.gsub!(/\u0085/, '|x') # next line
65
+ copy_of_text.gsub!(/\u2028/, '|l') # line separator
66
+ copy_of_text.gsub!(/\u2029/, '|p') # paragraph separator
67
+ rescue
68
+ # it is not an utf-8 compatible string :(
69
+ end
70
+
71
+ copy_of_text
72
+ end
73
+
74
+ def convert_time_to_java_simple_date(time)
75
+ gmt_offset = time.gmt_offset
76
+ gmt_sign = gmt_offset < 0 ? '-' : '+'
77
+ gmt_hours = gmt_offset.abs / 3600
78
+ gmt_minutes = gmt_offset.abs % 3600
79
+
80
+ millisec = time.usec == 0 ? 0 : time.usec / 1000
81
+
82
+ # Time string in Java SimpleDateFormat
83
+ sprintf("#{time.strftime('%Y-%m-%dT%H:%M:%S.')}%03d#{gmt_sign}%02d%02d", millisec, gmt_hours, gmt_minutes)
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module SpecDoxOutput
4
+ def handle_specification_begin(name)
5
+ puts spaces + name
6
+ end
7
+
8
+ def handle_specification_end
9
+ puts if Counter[:context_depth] == 1
10
+ end
11
+
12
+ def handle_requirement_begin(description)
13
+ print "#{spaces} - #{description}"
14
+ end
15
+
16
+ def handle_requirement_end(error)
17
+ puts error.empty? ? '' : " [#{error}]"
18
+ end
19
+
20
+ def handle_summary
21
+ print ErrorLog if Backtraces
22
+ puts '%d specifications (%d requirements), %d failures, %d errors' %
23
+ Counter.values_at(:specifications, :requirements, :failed, :errors)
24
+ end
25
+
26
+ def spaces
27
+ ' ' * (Counter[:context_depth] - 1)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,39 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module TapOutput
4
+ @@count = 1
5
+ @@describe = ''
6
+
7
+ def handle_specification_begin(name)
8
+ @@describe << "#{name} "
9
+ end
10
+
11
+ def handle_specification_end
12
+ @@describe = ''
13
+ end
14
+
15
+ def handle_requirement_begin(description)
16
+ @description = @@describe + description
17
+ @description.sub!(/^[#\s]+/, '')
18
+ ErrorLog.replace ''
19
+ end
20
+
21
+ def handle_requirement_end(error)
22
+ if error.empty?
23
+ puts 'ok %-3d - %s' % [@@count, @description]
24
+ else
25
+ puts 'not ok %d - %s: %s' %
26
+ [@@count, @description, error]
27
+ puts ErrorLog.strip.gsub(/^/, '# ') if Backtraces
28
+ end
29
+
30
+ @@count += 1
31
+ end
32
+
33
+ def handle_summary
34
+ puts "1..#{Counter[:specifications]}"
35
+ puts '# %d tests, %d assertions, %d failures, %d errors' %
36
+ Counter.values_at(:specifications, :requirements, :failed, :errors)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module TestUnitOutput
4
+ def handle_specification_begin(name); end
5
+ def handle_specification_end; end
6
+
7
+ def handle_requirement_begin(description); end
8
+
9
+ def handle_requirement_end(error)
10
+ if error.empty?
11
+ print '.'
12
+ else
13
+ print error[0..0]
14
+ end
15
+ end
16
+
17
+ def handle_summary
18
+ puts '', "Finished in #{Time.now - @timer} seconds."
19
+ puts ErrorLog if Backtraces
20
+ puts '%d tests, %d assertions, %d failures, %d errors' %
21
+ Counter.values_at(:specifications, :requirements, :failed, :errors)
22
+ end
23
+ end
24
+ end