lookout 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/README +645 -0
  2. data/Rakefile +9 -0
  3. data/lib/lookout.rb +34 -0
  4. data/lib/lookout/aphonic.rb +40 -0
  5. data/lib/lookout/benchmark.rb +11 -0
  6. data/lib/lookout/diff.rb +10 -0
  7. data/lib/lookout/diff/algorithms.rb +5 -0
  8. data/lib/lookout/diff/algorithms/difflib.rb +38 -0
  9. data/lib/lookout/diff/algorithms/difflib/position.rb +92 -0
  10. data/lib/lookout/diff/algorithms/difflib/position/to.rb +47 -0
  11. data/lib/lookout/diff/formats.rb +7 -0
  12. data/lib/lookout/diff/formats/hash.rb +53 -0
  13. data/lib/lookout/diff/formats/inline.rb +39 -0
  14. data/lib/lookout/diff/formats/unified.rb +57 -0
  15. data/lib/lookout/diff/group.rb +61 -0
  16. data/lib/lookout/diff/groups.rb +34 -0
  17. data/lib/lookout/diff/match.rb +36 -0
  18. data/lib/lookout/diff/operation.rb +33 -0
  19. data/lib/lookout/diff/operations.rb +36 -0
  20. data/lib/lookout/diff/operations/delete.rb +9 -0
  21. data/lib/lookout/diff/operations/equal.rb +27 -0
  22. data/lib/lookout/diff/operations/insert.rb +9 -0
  23. data/lib/lookout/diff/operations/replace.rb +9 -0
  24. data/lib/lookout/diff/range.rb +91 -0
  25. data/lib/lookout/equality.rb +178 -0
  26. data/lib/lookout/expectation.rb +50 -0
  27. data/lib/lookout/expectations.rb +62 -0
  28. data/lib/lookout/expectations/behavior.rb +20 -0
  29. data/lib/lookout/expectations/state.rb +29 -0
  30. data/lib/lookout/mock.rb +18 -0
  31. data/lib/lookout/mock/method.rb +70 -0
  32. data/lib/lookout/mock/method/arguments.rb +33 -0
  33. data/lib/lookout/mock/method/arguments/any.rb +11 -0
  34. data/lib/lookout/mock/method/arguments/anything.rb +11 -0
  35. data/lib/lookout/mock/method/arguments/list.rb +15 -0
  36. data/lib/lookout/mock/method/arguments/none.rb +11 -0
  37. data/lib/lookout/mock/method/arguments/one.rb +11 -0
  38. data/lib/lookout/mock/method/calls.rb +11 -0
  39. data/lib/lookout/mock/method/calls/class.rb +21 -0
  40. data/lib/lookout/mock/method/calls/exactly.rb +28 -0
  41. data/lib/lookout/mock/method/calls/instance.rb +25 -0
  42. data/lib/lookout/mock/method/calls/lower.rb +22 -0
  43. data/lib/lookout/mock/method/calls/upper.rb +22 -0
  44. data/lib/lookout/mock/methods.rb +12 -0
  45. data/lib/lookout/mock/object.rb +12 -0
  46. data/lib/lookout/object.rb +11 -0
  47. data/lib/lookout/output.rb +21 -0
  48. data/lib/lookout/rake/tasks.rb +36 -0
  49. data/lib/lookout/rake/tasks/gem.rb +49 -0
  50. data/lib/lookout/rake/tasks/tags.rb +16 -0
  51. data/lib/lookout/rake/tasks/test.rb +46 -0
  52. data/lib/lookout/rake/tasks/test/loader.rb +19 -0
  53. data/lib/lookout/recorder.rb +45 -0
  54. data/lib/lookout/recorder/not.rb +11 -0
  55. data/lib/lookout/recorder/tape.rb +21 -0
  56. data/lib/lookout/recorders.rb +6 -0
  57. data/lib/lookout/recorders/reception.rb +47 -0
  58. data/lib/lookout/recorders/state.rb +35 -0
  59. data/lib/lookout/result.rb +23 -0
  60. data/lib/lookout/results.rb +46 -0
  61. data/lib/lookout/results/error.rb +18 -0
  62. data/lib/lookout/results/error/exception.rb +36 -0
  63. data/lib/lookout/results/error/exception/backtrace.rb +41 -0
  64. data/lib/lookout/results/failure.rb +16 -0
  65. data/lib/lookout/results/failures.rb +6 -0
  66. data/lib/lookout/results/failures/behavior.rb +4 -0
  67. data/lib/lookout/results/failures/state.rb +4 -0
  68. data/lib/lookout/results/fulfilled.rb +9 -0
  69. data/lib/lookout/runners.rb +5 -0
  70. data/lib/lookout/runners/console.rb +22 -0
  71. data/lib/lookout/stub.rb +16 -0
  72. data/lib/lookout/stub/method.rb +105 -0
  73. data/lib/lookout/stub/methods.rb +18 -0
  74. data/lib/lookout/stub/object.rb +11 -0
  75. data/lib/lookout/ui.rb +7 -0
  76. data/lib/lookout/ui/console.rb +36 -0
  77. data/lib/lookout/ui/silent.rb +12 -0
  78. data/lib/lookout/version.rb +5 -0
  79. data/lib/lookout/xml.rb +17 -0
  80. data/test/unit/examples.rb +169 -0
  81. data/test/unit/lookout.rb +7 -0
  82. data/test/unit/lookout/diff.rb +4 -0
  83. data/test/unit/lookout/diff/algorithms/difflib.rb +56 -0
  84. data/test/unit/lookout/diff/algorithms/difflib/position.rb +92 -0
  85. data/test/unit/lookout/diff/algorithms/difflib/position/to.rb +12 -0
  86. data/test/unit/lookout/diff/formats/inline.rb +17 -0
  87. data/test/unit/lookout/diff/formats/unified.rb +67 -0
  88. data/test/unit/lookout/diff/group.rb +4 -0
  89. data/test/unit/lookout/diff/groups.rb +102 -0
  90. data/test/unit/lookout/diff/match.rb +5 -0
  91. data/test/unit/lookout/diff/operations.rb +22 -0
  92. data/test/unit/lookout/diff/operations/delete.rb +45 -0
  93. data/test/unit/lookout/diff/operations/equal.rb +45 -0
  94. data/test/unit/lookout/diff/operations/insert.rb +45 -0
  95. data/test/unit/lookout/diff/operations/replace.rb +45 -0
  96. data/test/unit/lookout/diff/range.rb +50 -0
  97. data/test/unit/lookout/equality.rb +113 -0
  98. data/test/unit/lookout/expectation.rb +39 -0
  99. data/test/unit/lookout/expectations.rb +58 -0
  100. data/test/unit/lookout/expectations/behavior.rb +35 -0
  101. data/test/unit/lookout/expectations/state.rb +29 -0
  102. data/test/unit/lookout/mock.rb +4 -0
  103. data/test/unit/lookout/mock/method.rb +143 -0
  104. data/test/unit/lookout/mock/method/arguments.rb +57 -0
  105. data/test/unit/lookout/mock/method/arguments/any.rb +11 -0
  106. data/test/unit/lookout/recorder.rb +11 -0
  107. data/test/unit/lookout/results.rb +30 -0
  108. data/test/unit/lookout/results/error.rb +7 -0
  109. data/test/unit/lookout/results/failures/behavior.rb +7 -0
  110. data/test/unit/lookout/results/failures/state.rb +7 -0
  111. data/test/unit/lookout/results/fulfilled.rb +7 -0
  112. data/test/unit/lookout/runners/console.rb +4 -0
  113. data/test/unit/lookout/stub.rb +4 -0
  114. data/test/unit/lookout/stub/method.rb +48 -0
  115. data/test/unit/lookout/ui/formatters/exception.rb +5 -0
  116. data/test/unit/lookout/ui/formatters/exception/backtrace.rb +11 -0
  117. data/test/unit/lookout/xml.rb +55 -0
  118. metadata +496 -0
@@ -0,0 +1,23 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Result
4
+ class << self
5
+ def is(is)
6
+ [:error, :failure, :fulfilled].each do |type|
7
+ define_method :"#{type}?" do
8
+ type == is
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ def initialize(file, line)
15
+ @file, @line = file, line
16
+ end
17
+
18
+ attr_reader :file, :line
19
+
20
+ def to_s
21
+ '%s:%d' % [file, line]
22
+ end
23
+ end
@@ -0,0 +1,46 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Results
4
+ autoload :Error, 'lookout/results/error'
5
+ autoload :Failure, 'lookout/results/failure'
6
+ autoload :Failures, 'lookout/results/failures'
7
+ autoload :Fulfilled, 'lookout/results/fulfilled'
8
+
9
+ include Enumerable
10
+
11
+ def initialize
12
+ @results = []
13
+ end
14
+
15
+ def <<(result)
16
+ @results << result
17
+ self
18
+ end
19
+
20
+ def each
21
+ @results.each do |result|
22
+ yield result
23
+ end
24
+ self
25
+ end
26
+
27
+ def succeeded?
28
+ all?{ |result| result.fulfilled? }
29
+ end
30
+
31
+ def size
32
+ @results.size
33
+ end
34
+
35
+ def fulfillments
36
+ select{ |result| result.fulfilled? }
37
+ end
38
+
39
+ def errors
40
+ select{ |result| result.error? }
41
+ end
42
+
43
+ def failures
44
+ select{ |result| result.failure? }
45
+ end
46
+ end
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Results::Error < Lookout::Result
4
+ autoload :Exception, 'lookout/results/error/exception'
5
+
6
+ is :error
7
+
8
+ def initialize(file, line, message, exception)
9
+ super file, line
10
+ @message, @exception = message, Exception.new(exception)
11
+ end
12
+
13
+ attr_reader :message, :exception
14
+
15
+ def to_s
16
+ [super, message, exception].compact.join(': ')
17
+ end
18
+ end
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Results::Error::Exception
4
+ autoload :Backtrace, 'lookout/results/error/exception/backtrace'
5
+
6
+ def initialize(exception)
7
+ @exception = exception
8
+ end
9
+
10
+ def message
11
+ # Chomping off a \n here isn’t 100 percent compatible with how Ruby 1.9
12
+ # does it, but it simplifies the code and also makes the output better if
13
+ # the message is a lone \n.
14
+ message = @exception.message.to_str.chomp("\n")
15
+ if @exception.class == RuntimeError and message.empty?
16
+ 'unhandled exception'
17
+ elsif message.empty?
18
+ @exception.class.name
19
+ elsif @exception.class.name.empty? or @exception.class.name =~ /^#/
20
+ message
21
+ else
22
+ before, newline, after = message.partition("\n")
23
+ '%s (%s)%s%s' % [before, @exception.class.name, newline, after]
24
+ end
25
+ end
26
+
27
+ def backtrace
28
+ @backtrace ||= Backtrace.new(@exception.backtrace)
29
+ end
30
+
31
+ def to_s
32
+ "%s\n%s" % [message, backtrace]
33
+ end
34
+
35
+ attr_reader :exception
36
+ end
@@ -0,0 +1,41 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Results::Error::Exception::Backtrace
4
+ def initialize(backtrace, filter = ENV['LOOKOUT_DO_NOT_FILTER_BACKTRACE'].nil?)
5
+ @filter = filter
6
+ @backtrace = case backtrace
7
+ when nil then []
8
+ when String then [backtrace]
9
+ when Array then backtrace.select{ |l| String === l }
10
+ end
11
+ end
12
+
13
+ def backtrace
14
+ return @backtrace unless @filter
15
+ before or outside or @backtrace
16
+ end
17
+
18
+ def to_s
19
+ backtrace.map{ |location| "\tfrom %s" % location }.join("\n")
20
+ end
21
+
22
+ private
23
+
24
+ def before
25
+ nilify(@backtrace.take_while{ |location| not reject? location })
26
+ end
27
+
28
+ def outside
29
+ nilify(@backtrace.reject{ |location| reject? location })
30
+ end
31
+
32
+ def nilify(backtrace)
33
+ backtrace.empty? ? nil : backtrace
34
+ end
35
+
36
+ def reject?(location)
37
+ location.start_with? Root
38
+ end
39
+
40
+ Root = 4.times.reduce(__FILE__){ |path, _| File.dirname(path) }
41
+ end
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Results::Failure < Lookout::Result
4
+ is :failure
5
+
6
+ def initialize(file, line, message)
7
+ super file, line
8
+ @message = message
9
+ end
10
+
11
+ attr_reader :message
12
+
13
+ def to_s
14
+ [super, message].compact.join(': ')
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::Results::Failures
4
+ autoload :Behavior, 'lookout/results/failures/behavior'
5
+ autoload :State, 'lookout/results/failures/state'
6
+ end
@@ -0,0 +1,4 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Results::Failures::Behavior < Lookout::Results::Failure
4
+ end
@@ -0,0 +1,4 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Results::Failures::State < Lookout::Results::Failure
4
+ end
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Results::Fulfilled < Lookout::Result
4
+ is :fulfilled
5
+
6
+ def initialize(file, line)
7
+ super file, line
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::Runners
4
+ autoload :Console, 'lookout/runners/console'
5
+ end
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Runners::Console
4
+ def initialize(expectations = Lookout::Expectations.new)
5
+ @expectations = expectations
6
+ @run = true
7
+ end
8
+
9
+ def install
10
+ at_exit do
11
+ exit 1 unless @run and @expectations.evaluate.succeeded?
12
+ end
13
+ self
14
+ end
15
+
16
+ def expectations_eval(&block)
17
+ @expectations.instance_eval(&block)
18
+ rescue
19
+ @run = false
20
+ raise
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::Stub
4
+ autoload :Method, 'lookout/stub/method'
5
+ autoload :Methods, 'lookout/stub/methods'
6
+ autoload :Object, 'lookout/stub/object'
7
+
8
+ class << self
9
+ def methods
10
+ methods = Methods.new
11
+ yield methods
12
+ ensure
13
+ methods.undefine if methods
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,105 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Stub::Method
4
+ class Values
5
+ def initialize(*values)
6
+ @values = values
7
+ @offset = -1
8
+ end
9
+
10
+ def next
11
+ @offset = [@offset + 1, @values.count - 1].min
12
+ @values[@offset]
13
+ end
14
+
15
+ def call
16
+ yield(*self.next)
17
+ end
18
+ end
19
+
20
+ class Each
21
+ def initialize(*values)
22
+ @values = values
23
+ end
24
+
25
+ def call
26
+ @values.each do |value|
27
+ yield value
28
+ end
29
+ end
30
+ end
31
+
32
+ def initialize(object, method, &body)
33
+ @object, @method, @body = object, method.to_sym, body || Nil
34
+ @yield = nil
35
+ @defined = false
36
+ end
37
+
38
+ def yield(*values)
39
+ @yield = Values.new(*values)
40
+ self
41
+ end
42
+
43
+ def each(*values)
44
+ @yield = Each.new(*values)
45
+ self
46
+ end
47
+
48
+ def define
49
+ return self if @defined
50
+ define!
51
+ @defined = true
52
+ self
53
+ end
54
+
55
+ def call(*args, &block)
56
+ @yield.call(&block) if @yield and block
57
+ @body.call(*args)
58
+ end
59
+
60
+ def undefine
61
+ return self unless @defined
62
+ undefine!
63
+ @defined = false
64
+ self
65
+ end
66
+
67
+ private
68
+
69
+ Nil = proc{ Lookout::Stub::Object.new }
70
+
71
+ def define!
72
+ meta.module_exec(@method, visibility, stash, self) do |method, visibility, stash, stub|
73
+ alias_method stash, method if
74
+ method_defined? method or private_method_defined? method
75
+ define_method method do |*args, &block|
76
+ stub.call(*args, &block)
77
+ end
78
+ send visibility, method
79
+ end
80
+ end
81
+
82
+ def undefine!
83
+ meta.module_exec(@method, stash) do |method, stash|
84
+ remove_method method
85
+ if method_defined? stash or private_method_defined? stash
86
+ alias_method method, stash
87
+ remove_method stash
88
+ end
89
+ end
90
+ end
91
+
92
+ def visibility
93
+ meta.private_method_defined?(@method) ? :private :
94
+ meta.protected_method_defined?(@method) ? :protected :
95
+ :public
96
+ end
97
+
98
+ def stash
99
+ :"__stubbed_method_#{@method}"
100
+ end
101
+
102
+ def meta
103
+ (class << @object; self; end)
104
+ end
105
+ end
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Stub::Methods
4
+ def initialize
5
+ @methods = []
6
+ end
7
+
8
+ def define(object, method, &body)
9
+ Lookout::Stub::Method.new(object, method, &body).define.tap{ |m| @methods << m }
10
+ end
11
+
12
+ def undefine
13
+ @methods.each do |method|
14
+ method.undefine
15
+ end
16
+ self
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Stub::Object
4
+ def inspect
5
+ 'stub'
6
+ end
7
+
8
+ def method_missing(method, *args)
9
+ self
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::UI
4
+ autoload :Console, 'lookout/ui/console'
5
+ autoload :Formatters, 'lookout/ui/formatters'
6
+ autoload :Silent, 'lookout/ui/silent'
7
+ end
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::UI::Console < Lookout::UI::Silent
4
+ def initialize(io = $stdout)
5
+ @io = io
6
+ end
7
+
8
+ def summarize(results, time)
9
+ return if results.succeeded?
10
+ summarize_total results, time
11
+ summarize_group results, :errors
12
+ summarize_group results, :failures
13
+ @io.flush
14
+ end
15
+
16
+ private
17
+
18
+ def summarize_total(results, time)
19
+ @io.printf "Ran %d expectations in %.3f seconds: %s\n",
20
+ results.size,
21
+ time,
22
+ [:errors, :failures, :fulfillments].inject([]){ |result, type|
23
+ next result unless (size = results.send(type).size) > 0
24
+ result << '%d %s' % [size, type]
25
+ }.join(', ')
26
+ end
27
+
28
+ def summarize_group(results, type)
29
+ group = results.send(type)
30
+ return if group.empty?
31
+ @io.puts '', type.to_s.upcase, ''
32
+ group.each do |item|
33
+ @io.puts item, ''
34
+ end
35
+ end
36
+ end