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,22 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Mock::Method::Calls::Lower
4
+ extend Lookout::Mock::Method::Calls::Class
5
+ include Lookout::Mock::Method::Calls::Instance
6
+
7
+ format 1, 0, 'expected %s to be called at least once'
8
+ format 2, 0, 'expected %s to be called at least twice'
9
+ format 2, 1, 'expected %s to be called at least twice, but was only called once'
10
+ format(-1, -1, 'expected %s to be called at least %d times, but was only called %d times')
11
+
12
+ def initialize(method, limit)
13
+ raise ArgumentError, 'limit must be > 0' unless limit > 0
14
+ super
15
+ end
16
+
17
+ private
18
+
19
+ def satisfied?
20
+ @calls >= @limit
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Mock::Method::Calls::Upper
4
+ extend Lookout::Mock::Method::Calls::Class
5
+ include Lookout::Mock::Method::Calls::Instance
6
+
7
+ format 1, 2, 'expected %s to be called at most once, but was called twice'
8
+ format 1, -1, 'expected %s to be called at most once, but was called %d times'
9
+ format 2, -1, 'expected %s to be called at most twice, but was called %d times'
10
+ format(-1, -1, 'expected %s to be called at most %d times, but was called %d times')
11
+
12
+ def initialize(method, limit)
13
+ raise ArgumentError, 'limit must be > 0' unless limit > 0
14
+ super
15
+ end
16
+
17
+ private
18
+
19
+ def satisfied?
20
+ @calls <= @limit
21
+ end
22
+ end
@@ -0,0 +1,12 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Mock::Methods < Lookout::Stub::Methods
4
+ def define(object, method, *args, &block)
5
+ method = Lookout::Mock::Method.new(object, method, *args, &block)
6
+ raise RuntimeError,
7
+ '%s: cannot create mock as a mock has already been created: %s' %
8
+ [method, @methods.first] unless @methods.empty?
9
+ @methods << method.define
10
+ method
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Mock::Object
4
+ def inspect
5
+ 'mock'
6
+ end
7
+
8
+ def method_missing(method, *args, &block)
9
+ raise Lookout::Mock::Method::Calls::Error,
10
+ 'unexpected call to %s' % Lookout::Mock::Method.new(self, method)
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Object
4
+ def to
5
+ Lookout::Recorder.new(self)
6
+ end
7
+
8
+ def not
9
+ Lookout::Recorder::Not.new(self)
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'stringio'
4
+
5
+ class Lookout::Output < StringIO
6
+ def initialize(expected)
7
+ @expected = expected
8
+ super()
9
+ end
10
+
11
+ attr_reader :expected
12
+
13
+ def actual
14
+ rewind
15
+ @actual ||= read
16
+ end
17
+
18
+ def inspect
19
+ 'output(%p)' % expected
20
+ end
21
+ end
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'rake'
4
+ require 'rake/tasklib'
5
+
6
+ module Lookout module Rake end end
7
+
8
+ module Lookout::Rake::Tasks
9
+ autoload :Gem, 'lookout/rake/tasks/gem'
10
+ autoload :Tags, 'lookout/rake/tasks/tags'
11
+ autoload :Test, 'lookout/rake/tasks/test'
12
+
13
+ class << self
14
+ def top_srcdir
15
+ @top_srcdir ||= Dir.pwd
16
+ end
17
+
18
+ def gemspec
19
+ @gemspec ||= Dir['%s/*.gemspec' % top_srcdir].first
20
+ end
21
+
22
+ def specification
23
+ return @specification if defined? @specification
24
+ return nil unless defined? ::Gem
25
+ return nil unless gemspec
26
+ @specification = ::Gem::Specification.load(gemspec)
27
+ end
28
+
29
+ def specification!
30
+ specification or
31
+ raise ArgumentError,
32
+ 'gem specification was not given and could not be found in project root: %s' %
33
+ top_srcdir
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,49 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Rake::Tasks::Gem < Rake::TaskLib
4
+ def initialize(specification = Lookout::Rake::Tasks.specification!)
5
+ specification or
6
+ raise ArgumentError,
7
+ 'gem specification was not given and could not be found in project root: %s' %
8
+ Lookout::Rake::Tasks.top_srcdir
9
+ @specification = specification
10
+ yield self if block_given?
11
+ define
12
+ end
13
+
14
+ def define
15
+ desc 'Build %s' % specification.file_name
16
+ task :build => specification.file_name
17
+ file specification.file_name => specification.files do
18
+ when_writing 'Building %s' % specification.file_name do
19
+ require 'rubygems' unless defined? Gem
20
+ require 'rubygems/installer' unless defined? Gem::Builder
21
+ Gem::Builder.new(specification).build
22
+ end
23
+ end
24
+
25
+ desc 'Check %s' % specification.file_name
26
+ task :check => :build do
27
+ require 'rubygems' unless defined? Gem
28
+ require 'rubygems/installer' unless defined? Gem::Installer
29
+ checkdir = specification.full_name
30
+ Gem::Installer.new(specification.file_name, :unpack => true).unpack checkdir
31
+ sh 'rake --rakefile %s/Rakefile -s test' % checkdir
32
+ rm_r checkdir
33
+ end
34
+
35
+ desc 'Install %s and its dependencies' % specification.file_name
36
+ task :install do
37
+ require 'rubygems' unless defined? Gem
38
+ require 'rubygems/dependency_installer' unless defined? Gem::DependencyInstaller
39
+ Gem::DependencyInstaller.new.install specification.file_name
40
+ end
41
+
42
+ desc 'Push %s to rubygems.org' % specification.file_name
43
+ task :push => :check do
44
+ sh 'gem -%s-verbose push %s' % [verbose ? '' : '-no', specification.file_name]
45
+ end
46
+ end
47
+
48
+ attr_reader :specification
49
+ end
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Rake::Tasks::Tags < Rake::TaskLib
4
+ def initialize(specification = Lookout::Rake::Tasks.specification!)
5
+ @specification = specification
6
+ yield self if block_given?
7
+ define
8
+ end
9
+
10
+ def define
11
+ require 'rbtags/rake/tasks'
12
+ RbTags::Rake::Tasks::Tags.new specification.require_paths, specification.lib_files.sort
13
+ end
14
+
15
+ attr_reader :specification
16
+ end
@@ -0,0 +1,46 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Rake::Tasks::Test < Rake::TaskLib
4
+ LoaderPath = File.join(File.dirname(__FILE__), 'test/loader.rb')
5
+
6
+ def initialize(specification = Lookout::Rake::Tasks.specification, name = :test)
7
+ self.specification, @name = specification, name
8
+ yield self if block_given?
9
+ define
10
+ end
11
+
12
+ def define
13
+ desc @name == :test ? 'Run tests' : 'Run tests for %s' % @name
14
+ task @name do
15
+ ruby '-w %s -- %s %s' % [options, escape(LoaderPath), arguments]
16
+ end
17
+
18
+ task :default => @name unless Rake::Task.task_defined? :default
19
+ end
20
+
21
+ attr_accessor :requires
22
+
23
+ private
24
+
25
+ def specification=(specification)
26
+ @paths, @requires = specification ?
27
+ [specification.require_paths, [specification.name]] :
28
+ [['lib'], []]
29
+ end
30
+
31
+ def options
32
+ @paths.map{ |p| '-I%s' % p }.join(' ')
33
+ end
34
+
35
+ def arguments
36
+ requires.map{ |r| '-r%s' % r }.push('--').concat(files).join(' ')
37
+ end
38
+
39
+ def files
40
+ FileList[ENV.fetch('TEST', 'test/unit/**/*.rb')].map{ |f| escape(f) }
41
+ end
42
+
43
+ def escape(path)
44
+ path.gsub(/([^A-Za-z0-9_\-.,:\/@\n])/n, '\\\\\\1').gsub(/\n/, "'\n'")
45
+ end
46
+ end
@@ -0,0 +1,19 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'lookout'
4
+
5
+ only_load = false
6
+ ARGV.each do |arg|
7
+ begin
8
+ if not only_load and arg == '--'
9
+ only_load = true
10
+ elsif not only_load and arg =~ /\A-r(.*)/
11
+ require $1
12
+ else
13
+ load arg
14
+ end
15
+ rescue SyntaxError => e
16
+ raise e unless matches = %r{\A(.*?:\d+): (.*)}m.match(e.message)
17
+ raise SyntaxError, matches[2], [matches[1]]
18
+ end
19
+ end
@@ -0,0 +1,45 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Recorder < Lookout::Aphonic
4
+ autoload :Not, 'lookout/recorder/not'
5
+ autoload :Tape, 'lookout/recorder/tape'
6
+
7
+ def initialize(subject)
8
+ @subject, @negated = subject, false
9
+ end
10
+
11
+ def not
12
+ @negated = true
13
+ self
14
+ end
15
+
16
+ def receive
17
+ extend Lookout::Recorders::Reception
18
+ receive!
19
+ end
20
+
21
+ def be
22
+ extend Lookout::Recorders::State
23
+ @verb = :be
24
+ self
25
+ end
26
+
27
+ def have
28
+ extend Lookout::Recorders::State
29
+ @verb = :have
30
+ self
31
+ end
32
+
33
+ def subject!(mocks, stubs)
34
+ subject
35
+ end
36
+
37
+ attr_reader :subject
38
+
39
+ def method_missing(method, *args)
40
+ return super unless method.to_s =~ /\?$/
41
+ extend Lookout::Recorders::State
42
+ @verb = nil
43
+ method_missing method, *args
44
+ end
45
+ end
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Recorder::Not < Lookout::Aphonic
4
+ def initialize(subject)
5
+ @subject = subject
6
+ end
7
+
8
+ def to
9
+ @subject.to.not
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Recorder::Tape
4
+ Method = Struct.new(:name, :args)
5
+
6
+ def initialize
7
+ @methods = []
8
+ end
9
+
10
+ def empty?
11
+ @methods.empty?
12
+ end
13
+
14
+ def record(method, args)
15
+ @methods << Method.new(method, args)
16
+ end
17
+
18
+ def play_for(subject)
19
+ @methods.inject(subject){ |result, method| result.send(method.name, *method.args) }
20
+ end
21
+ end
@@ -0,0 +1,6 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::Recorders
4
+ autoload :Reception, 'lookout/recorders/reception'
5
+ autoload :State, 'lookout/recorders/state'
6
+ end
@@ -0,0 +1,47 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::Recorders::Reception
4
+ def subject!(mocks, stubs)
5
+ @mock = @method._lookout_define(mocks)
6
+ methods.play_for @mock
7
+ subject
8
+ end
9
+
10
+ def verify
11
+ @mock.verify
12
+ end
13
+
14
+ private
15
+
16
+ def receive!
17
+ @method = Method.new(self, @negated)
18
+ end
19
+
20
+ def methods
21
+ @methods ||= Lookout::Recorder::Tape.new
22
+ end
23
+
24
+ def method_missing(method, *args, &block)
25
+ super unless defined? @method
26
+ methods.record method, args
27
+ self
28
+ end
29
+
30
+ class Method < Lookout::Aphonic
31
+ undef extend
32
+ undef is_a?
33
+
34
+ def initialize(recorder, negated)
35
+ @recorder, @negated = recorder, negated
36
+ end
37
+
38
+ def method_missing(method, *args, &body)
39
+ @method, @args, @body = method, args, body
40
+ @recorder
41
+ end
42
+
43
+ def _lookout_define(mocks)
44
+ mocks.define(@recorder.subject, @method, *@args, &@body).tap{ |m| m.never if @negated }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,35 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::Recorders::State
4
+ Error = Class.new(StandardError)
5
+
6
+ def verify
7
+ !!methods.play_for(subject) ^ @negated or
8
+ raise Error,
9
+ case [@negated, @verb]
10
+ when [true, :be] then 'expected %p not to be %s'
11
+ when [true, :have] then 'expected %p not to have %s'
12
+ when [true, nil] then 'expected %p to %s'
13
+ when [false, :be] then 'expected %p to be %s'
14
+ when [false, :have] then 'expected %p to have %s'
15
+ when [false, nil] then 'expected %p to %s'
16
+ end % [subject, description.join(' ')]
17
+ end
18
+
19
+ private
20
+
21
+ def methods
22
+ @methods ||= Lookout::Recorder::Tape.new
23
+ end
24
+
25
+ def description
26
+ @description ||= []
27
+ end
28
+
29
+ def method_missing(method, *args)
30
+ description << method.to_s
31
+ args.each{ |arg| description << arg.inspect }
32
+ methods.record method, args
33
+ self
34
+ end
35
+ end