lookout 2.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.
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,50 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::Expectation
4
+ def self.on(expected, file, line, &block)
5
+ (expected.is_a?(Lookout::Recorder) ?
6
+ Lookout::Expectations::Behavior :
7
+ Lookout::Expectations::State).new(expected, file, line, &block)
8
+ end
9
+
10
+ def initialize(expected, file, line, &block)
11
+ @expected, @file, @line, @block = expected, file, line.to_i, block
12
+ end
13
+
14
+ def evaluate
15
+ Lookout::Stub.methods{ |stubs| @stubs = stubs; evaluate_with_stubs }.tap{ @stubs = nil }
16
+ end
17
+
18
+ def stub(*args)
19
+ raise ArgumentError,
20
+ 'wrong number of arguments (%d for 1)' % args.length unless args.count < 2
21
+ return Lookout::Stub::Object.new if args.length < 1
22
+ case args[0]
23
+ when Hash
24
+ Lookout::Stub::Object.new.tap{ |stub|
25
+ args[0].each do |name, value|
26
+ @stubs.define(stub, name){ value }
27
+ end
28
+ }
29
+ else
30
+ Method.new(@stubs, args[0])
31
+ end
32
+ end
33
+
34
+ attr_reader :file, :line
35
+
36
+ private
37
+
38
+ class Method < Lookout::Aphonic
39
+ undef extend
40
+ undef is_a?
41
+
42
+ def initialize(stubs, object)
43
+ @stubs, @object = stubs, object
44
+ end
45
+
46
+ def method_missing(method, &body)
47
+ @stubs.define(@object, method, &body)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,62 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Expectations
4
+ autoload :Behavior, 'lookout/expectations/behavior'
5
+ autoload :State, 'lookout/expectations/state'
6
+
7
+ include Enumerable
8
+
9
+ def initialize
10
+ @expectations = []
11
+ end
12
+
13
+ def mock
14
+ Lookout::Mock::Object.new
15
+ end
16
+
17
+ def arg
18
+ Lookout::Mock::Method::Arguments::Anything.new
19
+ end
20
+
21
+ def without_arguments
22
+ Lookout::Mock::Method::Arguments::None.new
23
+ end
24
+
25
+ def stub
26
+ Lookout::Stub::Object.new
27
+ end
28
+
29
+ def output(string)
30
+ Lookout::Output.new(string)
31
+ end
32
+
33
+ def xml(string)
34
+ Lookout::XML.new(string)
35
+ end
36
+
37
+ def expect(expected, &block)
38
+ file, line = /\A(.*):(\d+)(?::in .*)?\z/.match(caller.first)[1..2]
39
+ @expectations << Lookout::Expectation.on(expected, file, line, &block)
40
+ expected
41
+ end
42
+
43
+ def evaluate(ui = Lookout::UI::Console.new, results = Lookout::Results.new)
44
+ ui.start
45
+ ui.summarize results, Lookout::Benchmark.time{
46
+ each(ENV['LINE'] ? ENV['LINE'].to_i : nil) do |expectation|
47
+ results << expectation.evaluate.tap{ |result| ui.report result }
48
+ end
49
+ }
50
+ results
51
+ end
52
+
53
+ def each(line = nil)
54
+ return enum_for(:each, line) unless block_given?
55
+ (line ?
56
+ Array(@expectations.reverse.find{ |e| e.line <= line }) :
57
+ @expectations).each do |expectation|
58
+ yield expectation
59
+ end
60
+ self
61
+ end
62
+ end
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Expectations::Behavior
4
+ include Lookout::Expectation
5
+
6
+ def evaluate_with_stubs
7
+ Lookout::Mock.methods do |mocks|
8
+ @expected.subject! mocks, @stubs
9
+ instance_exec @expected.subject, &@block if @block
10
+ @expected.verify
11
+ end
12
+ Lookout::Results::Fulfilled.new(file, line)
13
+ rescue Lookout::Recorders::State::Error => e
14
+ Lookout::Results::Failures::State.new(file, line, e.message)
15
+ rescue Lookout::Mock::Error => e
16
+ Lookout::Results::Failures::Behavior.new(file, line, e.message)
17
+ rescue Exception => e
18
+ Lookout::Results::Error.new(file, line, nil, e)
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Expectations::State
4
+ include Lookout::Expectation
5
+
6
+ def evaluate_with_stubs
7
+ check(@block ? instance_exec(@expected, &@block) : false)
8
+ rescue Exception => e
9
+ return check(e) if StandardError === @expected and @expected.class == e.class
10
+ return Lookout::Results::Fulfilled.new(file, line) if @expected.eql? e.class
11
+ Lookout::Results::Error.new(file, line,
12
+ if Class === @expected and StandardError >= @expected
13
+ Lookout::Equality.message(@expected, e.class)
14
+ elsif StandardError === @expected
15
+ Lookout::Equality.message(@expected.class, e.class)
16
+ else
17
+ nil
18
+ end,
19
+ e)
20
+ end
21
+
22
+ private
23
+
24
+ def check(actual)
25
+ (@expected == actual or Lookout::Equality.equal? @expected, actual) ?
26
+ Lookout::Results::Fulfilled.new(file, line) :
27
+ Lookout::Results::Failures::State.new(file, line, Lookout::Equality.message(@expected, actual))
28
+ end
29
+ end
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::Mock
4
+ autoload :Method, 'lookout/mock/method'
5
+ autoload :Methods, 'lookout/mock/methods'
6
+ autoload :Object, 'lookout/mock/object'
7
+
8
+ Error = Class.new(StandardError)
9
+
10
+ class << self
11
+ def methods
12
+ methods = Methods.new
13
+ yield methods
14
+ ensure
15
+ methods.undefine if methods
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,70 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Mock::Method < Lookout::Stub::Method
4
+ autoload :Arguments, 'lookout/mock/method/arguments'
5
+ autoload :Calls, 'lookout/mock/method/calls'
6
+
7
+ def initialize(object, method, *args, &body)
8
+ super object, method, &body
9
+ @args = Arguments.new(*args)
10
+ at_least_once
11
+ end
12
+
13
+ def never
14
+ exactly(0)
15
+ end
16
+
17
+ def at_most_once
18
+ at_most(1)
19
+ end
20
+
21
+ def once
22
+ exactly(1)
23
+ end
24
+
25
+ def at_least_once
26
+ at_least(1)
27
+ end
28
+
29
+ def twice
30
+ exactly(2)
31
+ end
32
+
33
+ def at_most(times)
34
+ @calls = Calls::Upper.new(self, times)
35
+ self
36
+ end
37
+
38
+ def exactly(times)
39
+ @calls = Calls::Exactly.new(self, times)
40
+ self
41
+ end
42
+
43
+ def at_least(times)
44
+ @calls = Calls::Lower.new(self, times)
45
+ self
46
+ end
47
+
48
+ def call(*args, &block)
49
+ @calls.call
50
+ @args.verify(*args)
51
+ super
52
+ rescue Lookout::Mock::Error => e
53
+ raise e, '%s: %s' % [self, e]
54
+ end
55
+
56
+ def verify
57
+ @calls.verify
58
+ self
59
+ end
60
+
61
+ def to_s
62
+ '%p.%s%p' % [@object, @method, @args]
63
+ end
64
+
65
+ private
66
+
67
+ def stash
68
+ :"__mocked_method_#{@method}"
69
+ end
70
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Mock::Method::Arguments
4
+ autoload :Any, 'lookout/mock/method/arguments/any'
5
+ autoload :Anything, 'lookout/mock/method/arguments/anything'
6
+ autoload :List, 'lookout/mock/method/arguments/list'
7
+ autoload :None, 'lookout/mock/method/arguments/none'
8
+
9
+ Error = Class.new(Lookout::Mock::Error)
10
+
11
+ def initialize(*args)
12
+ self.args = args
13
+ end
14
+
15
+ def verify(*args)
16
+ @args == args or
17
+ raise Error, 'unexpected arguments: (%s)≠(%p)' %
18
+ [args.map{ |arg| arg.inspect }.join(', '), @args]
19
+ end
20
+
21
+ def inspect
22
+ result = @args.inspect
23
+ result.empty? ? "" : '(%s)' % result
24
+ end
25
+
26
+ protected
27
+
28
+ def args=(args)
29
+ return @args = Any.new if args.empty?
30
+ none = args.find{ |arg| arg.is_a? None } and return @args = none
31
+ @args = List.new(args)
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Mock::Method::Arguments::Any
4
+ def ==(other)
5
+ true
6
+ end
7
+
8
+ def inspect
9
+ '*args, &block'
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Mock::Method::Arguments::Anything
4
+ def ==(other)
5
+ true
6
+ end
7
+
8
+ def inspect
9
+ 'arg'
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Mock::Method::Arguments::List
4
+ def initialize(args)
5
+ @args = args
6
+ end
7
+
8
+ def ==(other)
9
+ Lookout::Equality.equal?(@args, other)
10
+ end
11
+
12
+ def inspect
13
+ @args.map{ |arg| arg.inspect }.join(', ')
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Mock::Method::Arguments::None
4
+ def ==(other)
5
+ other.empty?
6
+ end
7
+
8
+ def inspect
9
+ ""
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Mock::Method::Arguments::Any
4
+ def ==(other)
5
+ other.count == 1
6
+ end
7
+
8
+ def inspect
9
+ 'arg'
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::Mock::Method::Calls
4
+ autoload :Class, 'lookout/mock/method/calls/class'
5
+ autoload :Exactly, 'lookout/mock/method/calls/exactly'
6
+ autoload :Instance, 'lookout/mock/method/calls/instance'
7
+ autoload :Lower, 'lookout/mock/method/calls/lower'
8
+ autoload :Upper, 'lookout/mock/method/calls/upper'
9
+
10
+ Error = ::Class.new(Lookout::Mock::Error)
11
+ end
@@ -0,0 +1,21 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::Mock::Method::Calls::Class
4
+ def format(limit, calls, format = nil)
5
+ return formats[limit][calls] unless format
6
+ if limit == -1
7
+ formats.default = Hash.new([format, [:@method, :@expected, :@calls]])
8
+ elsif calls == -1
9
+ formats[limit].default = [format, [:@method, :@calls]]
10
+ else
11
+ formats[limit][calls] = [format, [:@method]]
12
+ end
13
+ self
14
+ end
15
+
16
+ private
17
+
18
+ def formats
19
+ @formats ||= Hash.new{ |hash, key| hash[key] = {} }
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Mock::Method::Calls::Exactly
4
+ extend Lookout::Mock::Method::Calls::Class
5
+ include Lookout::Mock::Method::Calls::Instance
6
+
7
+ format 0, 1, 'expected %s not to be called'
8
+ format 0, 2, 'expected %s not to be called, but was called twice'
9
+ format 0, -1, 'expected %s not to be called, but was called %d times'
10
+ format 1, 0, 'expected %s to be called'
11
+ format 1, 2, 'expected %s to be called once, not twice'
12
+ format 1, -1, 'expected %s to be called once, not %d times'
13
+ format 2, 0, 'expected %s to be called twice'
14
+ format 2, 1, 'expected %s to be called twice, but was only called once'
15
+ format 2, -1, 'expected %s to be called twice, not %d times'
16
+ format(-1, -1, 'expected %s to be called %d times, not %d times')
17
+
18
+ def initialize(method, limit)
19
+ raise ArgumentError, 'limit must be >= 0' unless limit >= 0
20
+ super
21
+ end
22
+
23
+ private
24
+
25
+ def satisfied?
26
+ @calls == @limit
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::Mock::Method::Calls::Instance
4
+ def initialize(method, limit)
5
+ @method, @limit = method, limit
6
+ @calls = 0
7
+ end
8
+
9
+ def call
10
+ @calls += 1
11
+ self
12
+ end
13
+
14
+ def verify
15
+ raise Lookout::Mock::Method::Calls::Error, message unless satisfied?
16
+ self
17
+ end
18
+
19
+ private
20
+
21
+ def message
22
+ format, variables = self.class.format(@limit, @calls)
23
+ format % variables.map{ |v| instance_variable_get(v) }
24
+ end
25
+ end