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.
- data/README +645 -0
- data/Rakefile +9 -0
- data/lib/lookout.rb +34 -0
- data/lib/lookout/aphonic.rb +40 -0
- data/lib/lookout/benchmark.rb +11 -0
- data/lib/lookout/diff.rb +10 -0
- data/lib/lookout/diff/algorithms.rb +5 -0
- data/lib/lookout/diff/algorithms/difflib.rb +38 -0
- data/lib/lookout/diff/algorithms/difflib/position.rb +92 -0
- data/lib/lookout/diff/algorithms/difflib/position/to.rb +47 -0
- data/lib/lookout/diff/formats.rb +7 -0
- data/lib/lookout/diff/formats/hash.rb +53 -0
- data/lib/lookout/diff/formats/inline.rb +39 -0
- data/lib/lookout/diff/formats/unified.rb +57 -0
- data/lib/lookout/diff/group.rb +61 -0
- data/lib/lookout/diff/groups.rb +34 -0
- data/lib/lookout/diff/match.rb +36 -0
- data/lib/lookout/diff/operation.rb +33 -0
- data/lib/lookout/diff/operations.rb +36 -0
- data/lib/lookout/diff/operations/delete.rb +9 -0
- data/lib/lookout/diff/operations/equal.rb +27 -0
- data/lib/lookout/diff/operations/insert.rb +9 -0
- data/lib/lookout/diff/operations/replace.rb +9 -0
- data/lib/lookout/diff/range.rb +91 -0
- data/lib/lookout/equality.rb +178 -0
- data/lib/lookout/expectation.rb +50 -0
- data/lib/lookout/expectations.rb +62 -0
- data/lib/lookout/expectations/behavior.rb +20 -0
- data/lib/lookout/expectations/state.rb +29 -0
- data/lib/lookout/mock.rb +18 -0
- data/lib/lookout/mock/method.rb +70 -0
- data/lib/lookout/mock/method/arguments.rb +33 -0
- data/lib/lookout/mock/method/arguments/any.rb +11 -0
- data/lib/lookout/mock/method/arguments/anything.rb +11 -0
- data/lib/lookout/mock/method/arguments/list.rb +15 -0
- data/lib/lookout/mock/method/arguments/none.rb +11 -0
- data/lib/lookout/mock/method/arguments/one.rb +11 -0
- data/lib/lookout/mock/method/calls.rb +11 -0
- data/lib/lookout/mock/method/calls/class.rb +21 -0
- data/lib/lookout/mock/method/calls/exactly.rb +28 -0
- data/lib/lookout/mock/method/calls/instance.rb +25 -0
- data/lib/lookout/mock/method/calls/lower.rb +22 -0
- data/lib/lookout/mock/method/calls/upper.rb +22 -0
- data/lib/lookout/mock/methods.rb +12 -0
- data/lib/lookout/mock/object.rb +12 -0
- data/lib/lookout/object.rb +11 -0
- data/lib/lookout/output.rb +21 -0
- data/lib/lookout/rake/tasks.rb +36 -0
- data/lib/lookout/rake/tasks/gem.rb +49 -0
- data/lib/lookout/rake/tasks/tags.rb +16 -0
- data/lib/lookout/rake/tasks/test.rb +46 -0
- data/lib/lookout/rake/tasks/test/loader.rb +19 -0
- data/lib/lookout/recorder.rb +45 -0
- data/lib/lookout/recorder/not.rb +11 -0
- data/lib/lookout/recorder/tape.rb +21 -0
- data/lib/lookout/recorders.rb +6 -0
- data/lib/lookout/recorders/reception.rb +47 -0
- data/lib/lookout/recorders/state.rb +35 -0
- data/lib/lookout/result.rb +23 -0
- data/lib/lookout/results.rb +46 -0
- data/lib/lookout/results/error.rb +18 -0
- data/lib/lookout/results/error/exception.rb +36 -0
- data/lib/lookout/results/error/exception/backtrace.rb +41 -0
- data/lib/lookout/results/failure.rb +16 -0
- data/lib/lookout/results/failures.rb +6 -0
- data/lib/lookout/results/failures/behavior.rb +4 -0
- data/lib/lookout/results/failures/state.rb +4 -0
- data/lib/lookout/results/fulfilled.rb +9 -0
- data/lib/lookout/runners.rb +5 -0
- data/lib/lookout/runners/console.rb +22 -0
- data/lib/lookout/stub.rb +16 -0
- data/lib/lookout/stub/method.rb +105 -0
- data/lib/lookout/stub/methods.rb +18 -0
- data/lib/lookout/stub/object.rb +11 -0
- data/lib/lookout/ui.rb +7 -0
- data/lib/lookout/ui/console.rb +36 -0
- data/lib/lookout/ui/silent.rb +12 -0
- data/lib/lookout/version.rb +5 -0
- data/lib/lookout/xml.rb +17 -0
- data/test/unit/examples.rb +169 -0
- data/test/unit/lookout.rb +7 -0
- data/test/unit/lookout/diff.rb +4 -0
- data/test/unit/lookout/diff/algorithms/difflib.rb +56 -0
- data/test/unit/lookout/diff/algorithms/difflib/position.rb +92 -0
- data/test/unit/lookout/diff/algorithms/difflib/position/to.rb +12 -0
- data/test/unit/lookout/diff/formats/inline.rb +17 -0
- data/test/unit/lookout/diff/formats/unified.rb +67 -0
- data/test/unit/lookout/diff/group.rb +4 -0
- data/test/unit/lookout/diff/groups.rb +102 -0
- data/test/unit/lookout/diff/match.rb +5 -0
- data/test/unit/lookout/diff/operations.rb +22 -0
- data/test/unit/lookout/diff/operations/delete.rb +45 -0
- data/test/unit/lookout/diff/operations/equal.rb +45 -0
- data/test/unit/lookout/diff/operations/insert.rb +45 -0
- data/test/unit/lookout/diff/operations/replace.rb +45 -0
- data/test/unit/lookout/diff/range.rb +50 -0
- data/test/unit/lookout/equality.rb +113 -0
- data/test/unit/lookout/expectation.rb +39 -0
- data/test/unit/lookout/expectations.rb +58 -0
- data/test/unit/lookout/expectations/behavior.rb +35 -0
- data/test/unit/lookout/expectations/state.rb +29 -0
- data/test/unit/lookout/mock.rb +4 -0
- data/test/unit/lookout/mock/method.rb +143 -0
- data/test/unit/lookout/mock/method/arguments.rb +57 -0
- data/test/unit/lookout/mock/method/arguments/any.rb +11 -0
- data/test/unit/lookout/recorder.rb +11 -0
- data/test/unit/lookout/results.rb +30 -0
- data/test/unit/lookout/results/error.rb +7 -0
- data/test/unit/lookout/results/failures/behavior.rb +7 -0
- data/test/unit/lookout/results/failures/state.rb +7 -0
- data/test/unit/lookout/results/fulfilled.rb +7 -0
- data/test/unit/lookout/runners/console.rb +4 -0
- data/test/unit/lookout/stub.rb +4 -0
- data/test/unit/lookout/stub/method.rb +48 -0
- data/test/unit/lookout/ui/formatters/exception.rb +5 -0
- data/test/unit/lookout/ui/formatters/exception/backtrace.rb +11 -0
- data/test/unit/lookout/xml.rb +55 -0
- 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
|
data/lib/lookout/mock.rb
ADDED
@@ -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,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
|
+
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
|