bogus 0.1.0 → 0.1.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 (48) hide show
  1. data/.travis.yml +1 -0
  2. data/Gemfile.lock +6 -1
  3. data/README.md +3 -0
  4. data/features/changelog.md +30 -22
  5. data/features/configuration/fake_ar_attributes.feature +3 -1
  6. data/features/configuration/search_modules.feature +5 -0
  7. data/features/contract_tests/contract_tests_mocks.feature +12 -1
  8. data/features/contract_tests/contract_tests_spies.feature +14 -2
  9. data/features/contract_tests/contract_tests_stubs.feature +13 -2
  10. data/features/contract_tests/return_value_contracts.feature +15 -4
  11. data/features/fakes/anonymous_doubles.feature +15 -1
  12. data/features/fakes/duck_types.feature +12 -2
  13. data/features/fakes/fake_objects.feature +11 -1
  14. data/features/fakes/global_fake_configuration.feature +4 -1
  15. data/features/readme.md +2 -2
  16. data/features/safe_stubbing/argument_matchers.feature +32 -2
  17. data/features/safe_stubbing/safe_mocking.feature +9 -2
  18. data/features/safe_stubbing/safe_stubbing.feature +11 -2
  19. data/features/safe_stubbing/spies.feature +52 -1
  20. data/features/step_definitions/rspec_steps.rb +1 -2
  21. data/features/support/env.rb +19 -0
  22. data/lib/bogus/active_record_accessors.rb +4 -4
  23. data/lib/bogus/adds_recording.rb +1 -0
  24. data/lib/bogus/any_args.rb +32 -3
  25. data/lib/bogus/class_methods.rb +7 -1
  26. data/lib/bogus/copies_classes.rb +5 -2
  27. data/lib/bogus/fake.rb +0 -2
  28. data/lib/bogus/have_received_matcher.rb +5 -0
  29. data/lib/bogus/interaction.rb +66 -35
  30. data/lib/bogus/interactions_repository.rb +1 -1
  31. data/lib/bogus/makes_substitute_methods.rb +3 -2
  32. data/lib/bogus/mocking_dsl.rb +8 -0
  33. data/lib/bogus/public_methods.rb +1 -1
  34. data/lib/bogus/rspec_extensions.rb +8 -1
  35. data/lib/bogus/same_class.rb +14 -0
  36. data/lib/bogus/shadow.rb +8 -12
  37. data/lib/bogus/verifies_stub_definition.rb +1 -5
  38. data/lib/bogus/version.rb +1 -1
  39. data/spec/bogus/adds_recording_spec.rb +8 -0
  40. data/spec/bogus/class_methods_spec.rb +8 -2
  41. data/spec/bogus/clean_ruby_spec.rb +15 -0
  42. data/spec/bogus/have_received_matcher_spec.rb +45 -27
  43. data/spec/bogus/instance_methods_spec.rb +1 -1
  44. data/spec/bogus/interaction_spec.rb +87 -83
  45. data/spec/bogus/interactions_repository_spec.rb +8 -11
  46. data/spec/bogus/shadow_spec.rb +4 -1
  47. metadata +81 -39
  48. checksums.yaml +0 -7
@@ -21,7 +21,7 @@ Feature: Faking duck types
21
21
  end
22
22
 
23
23
  Background:
24
- Given a file named "foo.rb" with:
24
+ Given a file named "loggers.rb" with:
25
25
  """ruby
26
26
  class DatabaseLogger
27
27
  def error(message); end
@@ -56,6 +56,8 @@ Feature: Faking duck types
56
56
  Scenario: Copying instance methods
57
57
  Then spec file with following content should pass:
58
58
  """ruby
59
+ require_relative 'loggers'
60
+
59
61
  describe "make_duck" do
60
62
  let(:duck) { make_duck(DatabaseLogger, NetworkLogger,
61
63
  DevNullLogger) }
@@ -94,6 +96,8 @@ Feature: Faking duck types
94
96
  Scenario: Faking duck types
95
97
  Then spec file with following content should pass:
96
98
  """ruby
99
+ require_relative 'loggers'
100
+
97
101
  describe "fake with multiple classes" do
98
102
  fake(:logger) { [DatabaseLogger,
99
103
  NetworkLogger,
@@ -110,7 +114,7 @@ Feature: Faking duck types
110
114
  """
111
115
 
112
116
  Scenario: Globally configured duck types
113
- Then spec file with following content should pass:
117
+ Given a file named "fakes.rb" with:
114
118
  """ruby
115
119
  Bogus.fakes do
116
120
  logger_implementations = proc{ [DatabaseLogger,
@@ -119,6 +123,12 @@ Feature: Faking duck types
119
123
 
120
124
  fake :logger, class: logger_implementations
121
125
  end
126
+ """
127
+
128
+ Then spec file with following content should pass:
129
+ """ruby
130
+ require_relative 'fakes'
131
+ require_relative 'loggers'
122
132
 
123
133
  describe "fake with multiple classes" do
124
134
  fake(:logger)
@@ -26,7 +26,7 @@ Feature: Faking existing classes
26
26
  let(:foo) { fake(:foo, bar: "value") }
27
27
 
28
28
  Background:
29
- Given a file named "foo.rb" with:
29
+ Given a file named "library.rb" with:
30
30
  """ruby
31
31
  class Library
32
32
  def checkout(book)
@@ -38,7 +38,10 @@ Feature: Faking existing classes
38
38
  def self.look_up(book)
39
39
  end
40
40
  end
41
+ """
41
42
 
43
+ Given a file named "student.rb" with:
44
+ """ruby
42
45
  class Student
43
46
  def self.learn(library = Library.new)
44
47
  library.checkout("hello world")
@@ -50,6 +53,9 @@ Feature: Faking existing classes
50
53
  Scenario: Calling methods that exist on real object
51
54
  Then spec file with following content should pass:
52
55
  """ruby
56
+ require_relative 'student'
57
+ require_relative 'library'
58
+
53
59
  describe Student do
54
60
  fake(:library)
55
61
 
@@ -79,6 +85,8 @@ Feature: Faking existing classes
79
85
  Scenario: Fakes which are classes
80
86
  Then spec file with following content should pass:
81
87
  """ruby
88
+ require_relative 'library'
89
+
82
90
  describe "library class fake" do
83
91
  fake(:library, as: :class)
84
92
 
@@ -99,6 +107,8 @@ Feature: Faking existing classes
99
107
  Scenario: Fakes with inline return values
100
108
  Then spec file with following content should pass:
101
109
  """ruby
110
+ require_relative 'library'
111
+
102
112
  describe "library class fake" do
103
113
  let(:library) { fake(:library, checkout: "checked out",
104
114
  return_book: "returned") }
@@ -18,7 +18,7 @@ Feature: Global fake configuration
18
18
  in your spec helper, or a file required from it.
19
19
 
20
20
  Background:
21
- Given a file named "foo.rb" with:
21
+ Given a file named "public_library.rb" with:
22
22
  """ruby
23
23
  class PublicLibrary
24
24
  def self.books_by_author(name)
@@ -39,6 +39,7 @@ Feature: Global fake configuration
39
39
  Then spec file with following content should pass:
40
40
  """ruby
41
41
  require_relative "fakes"
42
+ require_relative "public_library"
42
43
 
43
44
  describe "The library fake" do
44
45
  fake(:library)
@@ -64,6 +65,7 @@ Feature: Global fake configuration
64
65
  Then spec file with following content should pass:
65
66
  """ruby
66
67
  require_relative "fakes"
68
+ require_relative "public_library"
67
69
 
68
70
  describe "The library fake" do
69
71
  fake(:library, books_by_author: ["Some Book"])
@@ -78,6 +80,7 @@ Feature: Global fake configuration
78
80
  Then spec file with following content should pass:
79
81
  """ruby
80
82
  require_relative "fakes"
83
+ require_relative "public_library"
81
84
 
82
85
  describe "The library fake" do
83
86
  it "can be overridden in the helper" do
@@ -37,8 +37,8 @@ Bogus makes your test doubles more assertive. They will no longer be too shy to
37
37
  Let's reexamine our previous example, this time Bogus-style:
38
38
 
39
39
  it "returns the average score" do
40
- students = fake(:students, get: [5, 9])
41
- scores = fake(:scores, all: ["John", "Mary"])
40
+ scores = fake(:scores, get: [5, 9])
41
+ students = fake(:students, all: ["John", "Mary"])
42
42
 
43
43
  report_card = ReportCard.new(scores, students)
44
44
 
@@ -3,7 +3,7 @@ Feature: Argument matchers
3
3
  Bogus supports some argument matchers for use, when you don't really care about exact equality of arguments passed in or spied on.
4
4
 
5
5
  Background:
6
- Given a file named "foo.rb" with:
6
+ Given a file named "catalog.rb" with:
7
7
  """ruby
8
8
  class Catalog
9
9
  def self.books_by_author_and_title(author, title)
@@ -14,17 +14,47 @@ Feature: Argument matchers
14
14
  Scenario: Stubbing methods with any arguments
15
15
  Then the following test should pass:
16
16
  """ruby
17
+ require_relative 'catalog'
18
+
17
19
  stub(Catalog).books_by_author_and_title(any_args) { :some_book }
18
20
 
19
- Catalog.books_by_author_and_title("Mark Twain", "Tom Sawyer").should == :some_book
21
+ Catalog.books_by_author_and_title("Arthur Conan Doyle", "Sherlock Holmes").should == :some_book
20
22
  """
21
23
 
22
24
  Scenario: Stubbing methods with some wildcard arguments
23
25
  Then the following test should pass:
24
26
  """ruby
27
+ require_relative 'catalog'
28
+
29
+ stub(Catalog).books_by_author_and_title(any_args) { :some_book }
25
30
  stub(Catalog).books_by_author_and_title("Mark Twain", anything) { :twains_book }
26
31
 
27
32
  Catalog.books_by_author_and_title("Mark Twain", "Tom Sawyer").should == :twains_book
28
33
  Catalog.books_by_author_and_title("Mark Twain", "Huckleberry Finn").should == :twains_book
34
+ Catalog.books_by_author_and_title("Arthur Conan Doyle", "Sherlock Holmes").should == :some_book
35
+ """
36
+
37
+ Scenario: Stubbing methods with proc argument matcher
38
+ Then the following test should pass:
39
+ """ruby
40
+ require_relative 'catalog'
41
+
42
+ stub(Catalog).books_by_author_and_title(any_args) { :some_book }
43
+ stub(Catalog).books_by_author_and_title(with{|author| author =~ /Twain/ }) { :twains_book }
44
+
45
+ Catalog.books_by_author_and_title("Mark Twain", "Tom Sawyer").should == :twains_book
46
+ Catalog.books_by_author_and_title("M. Twain", "Huckleberry Finn").should == :twains_book
47
+ Catalog.books_by_author_and_title("Arthur Conan Doyle", "Sherlock Holmes").should == :some_book
29
48
  """
30
49
 
50
+ Scenario: Stubbing methods with argument type matcher
51
+ Then the following test should pass:
52
+ """ruby
53
+ require_relative 'catalog'
54
+
55
+ stub(Catalog).books_by_author_and_title(any_args) { :some_book }
56
+ stub(Catalog).books_by_author_and_title(any(String), any(String)) { :twains_book }
57
+
58
+ Catalog.books_by_author_and_title("Mark Twain", "Tom Sawyer").should == :twains_book
59
+ Catalog.books_by_author_and_title("M. Twain", :other_book).should == :some_book
60
+ """
@@ -15,7 +15,7 @@ Feature: Safe mocking
15
15
  You can only mock methods that actually exist on an object. It will also work with methods that the object `responds_to?`, but (obviously) without being able to check the method signature.
16
16
 
17
17
  Background:
18
- Given a file named "foo.rb" with:
18
+ Given a file named "library.rb" with:
19
19
  """ruby
20
20
  class Library
21
21
  def checkout(book)
@@ -26,8 +26,9 @@ Feature: Safe mocking
26
26
  Scenario: Mocking methods that exist on real object
27
27
  Then spec file with following content should pass:
28
28
  """ruby
29
- describe Library do
29
+ require_relative 'library'
30
30
 
31
+ describe Library do
31
32
  it "does something" do
32
33
  library = Library.new
33
34
  mock(library).checkout("some book") { :checked_out }
@@ -40,6 +41,8 @@ Feature: Safe mocking
40
41
  Scenario: Mocking methods that do not exist on real object
41
42
  Then spec file with following content should fail:
42
43
  """ruby
44
+ require_relative 'library'
45
+
43
46
  describe Library do
44
47
  it "does something" do
45
48
  library = Library.new
@@ -52,6 +55,8 @@ Feature: Safe mocking
52
55
  Scenario: Mocking methods with wrong number of arguments
53
56
  Then spec file with following content should fail:
54
57
  """ruby
58
+ require_relative 'library'
59
+
55
60
  describe Library do
56
61
  it "does something" do
57
62
  library = Library.new
@@ -64,6 +69,8 @@ Feature: Safe mocking
64
69
  Scenario: Mocks require the methods to be called
65
70
  Then spec file with following content should fail:
66
71
  """ruby
72
+ require_relative 'library'
73
+
67
74
  describe Library do
68
75
  it "does something" do
69
76
  library = Library.new
@@ -7,7 +7,7 @@ Feature: Safe stubbing
7
7
  stub(object).method_name(arg1, arg2, ...) { return_value }
8
8
 
9
9
  Background:
10
- Given a file named "foo.rb" with:
10
+ Given a file named "library.rb" with:
11
11
  """ruby
12
12
  class Library
13
13
  def checkout(book)
@@ -18,8 +18,9 @@ Feature: Safe stubbing
18
18
  Scenario: Stubbing methods that exist on real object
19
19
  Then spec file with following content should pass:
20
20
  """ruby
21
- describe Library do
21
+ require_relative 'library'
22
22
 
23
+ describe Library do
23
24
  it "does something" do
24
25
  library = Library.new
25
26
  stub(library).checkout("some book") { :checked_out }
@@ -32,6 +33,8 @@ Feature: Safe stubbing
32
33
  Scenario: Stubbing methods that do not exist on real object
33
34
  Then spec file with following content should fail:
34
35
  """ruby
36
+ require_relative 'library'
37
+
35
38
  describe Library do
36
39
  it "does something" do
37
40
  library = Library.new
@@ -43,6 +46,8 @@ Feature: Safe stubbing
43
46
  Scenario: Stubbing methods with wrong number of arguments
44
47
  Then spec file with following content should fail:
45
48
  """ruby
49
+ require_relative 'library'
50
+
46
51
  describe Library do
47
52
  it "does something" do
48
53
  library = Library.new
@@ -54,6 +59,8 @@ Feature: Safe stubbing
54
59
  Scenario: Stubs allow the methods to be called
55
60
  Then spec file with following content should pass:
56
61
  """ruby
62
+ require_relative 'library'
63
+
57
64
  describe Library do
58
65
  it "does something" do
59
66
  library = Library.new
@@ -65,6 +72,8 @@ Feature: Safe stubbing
65
72
  Scenario: Stubbing methods multiple times
66
73
  Then spec file with following content should fail:
67
74
  """ruby
75
+ require_relative 'library'
76
+
68
77
  describe Library do
69
78
  it "stubbing with too many arguments" do
70
79
  library = Library.new
@@ -5,14 +5,17 @@ Feature: Spies
5
5
  Typically, stubbing libraries force you to first stub a method, so that you can later make sure it was called. However, if you use fakes, Bogus lets you verify that a method was called (or not) without stubbing it first.
6
6
 
7
7
  Background:
8
- Given a file named "foo.rb" with:
8
+ Given a file named "library.rb" with:
9
9
  """ruby
10
10
  class Library
11
11
  def checkout(book)
12
12
  # marks book as checked out
13
13
  end
14
14
  end
15
+ """
15
16
 
17
+ Given a file named "student.rb" with:
18
+ """ruby
16
19
  class Student
17
20
  def initialize(library)
18
21
  @library = library
@@ -29,6 +32,9 @@ Feature: Spies
29
32
  Scenario: Ensuring methods were called
30
33
  Then spec file with following content should pass:
31
34
  """ruby
35
+ require_relative 'student'
36
+ require_relative 'library'
37
+
32
38
  describe Student do
33
39
  fake(:library)
34
40
 
@@ -46,6 +52,9 @@ Feature: Spies
46
52
  Scenario: Spying on methods that do not exist
47
53
  Then spec file with following content should fail:
48
54
  """ruby
55
+ require_relative 'student'
56
+ require_relative 'library'
57
+
49
58
  describe Student do
50
59
  fake(:library)
51
60
 
@@ -62,6 +71,9 @@ Feature: Spies
62
71
  Scenario: Spying on methods with wrong number of arguments
63
72
  Then spec file with following content should fail:
64
73
  """ruby
74
+ require_relative 'student'
75
+ require_relative 'library'
76
+
65
77
  describe Student do
66
78
  fake(:library)
67
79
 
@@ -79,6 +91,9 @@ Feature: Spies
79
91
  Scenario: Spying on previously stubbed methods
80
92
  Then spec file with following content should pass:
81
93
  """ruby
94
+ require_relative 'student'
95
+ require_relative 'library'
96
+
82
97
  describe Student do
83
98
  fake(:library)
84
99
 
@@ -91,3 +106,39 @@ Feature: Spies
91
106
  end
92
107
  end
93
108
  """
109
+
110
+ Scenario: Spying on attribute writers
111
+ Given a file named "canvas.rb" with:
112
+ """ruby
113
+ class Canvas
114
+ def background_color=(color)
115
+ # do something complicated
116
+ end
117
+ end
118
+ """
119
+
120
+ Given a file named "popup.rb" with:
121
+ """ruby
122
+ class Popup
123
+ def self.alert(message, canvas)
124
+ canvas.background_color = "red"
125
+ # display message
126
+ end
127
+ end
128
+ """
129
+
130
+ Then spec file with following content should pass:
131
+ """ruby
132
+ require_relative 'canvas'
133
+ require_relative 'popup'
134
+
135
+ describe Popup do
136
+ fake(:canvas)
137
+
138
+ it "sets the background to red" do
139
+ Popup.alert("No such file!", canvas)
140
+
141
+ canvas.should have_received(:background_color=, "red")
142
+ end
143
+ end
144
+ """
@@ -6,7 +6,6 @@ Given /^a spec file named "([^"]*)" with:$/ do |file_name, string|
6
6
  Given a file named "#{file_name}" with:
7
7
  """ruby
8
8
  require 'bogus/rspec'
9
- require_relative 'foo'
10
9
 
11
10
  #{string}
12
11
  """
@@ -26,7 +25,7 @@ Then /^all the specs should pass$/ do
26
25
  end
27
26
 
28
27
  When /^I run spec with the following content:$/ do |string|
29
- file_name = 'foo_spec.rb'
28
+ file_name = "foo_#{rand(1000000)}_spec.rb"
30
29
 
31
30
  steps %Q{
32
31
  Given a spec file named "#{file_name}" with:
@@ -1,5 +1,24 @@
1
1
  require 'aruba/cucumber'
2
+ require 'aruba/jruby'
2
3
 
3
4
  Before('@known_bug') do
4
5
  pending("This scenario fails because of a known bug")
5
6
  end
7
+
8
+ Before do |scenario|
9
+ dir_name = "scenario-#{rand(1_000_000)}"
10
+ create_dir(dir_name)
11
+ cd(dir_name)
12
+ end
13
+
14
+ Before do
15
+ @aruba_timeout_seconds = 60
16
+ end
17
+
18
+ if RUBY_PLATFORM == 'java' && ENV['TRAVIS']
19
+ Aruba.configure do |config|
20
+ config.before_cmd do
21
+ set_env('JAVA_OPTS', "#{ENV['JAVA_OPTS']} -d64")
22
+ end
23
+ end
24
+ end
@@ -7,7 +7,7 @@ module Bogus
7
7
 
8
8
  takes :klass, :instance_methods
9
9
 
10
- def_delegators :instance_methods, :remove, :define
10
+ def_delegators :model_methods, :remove, :define
11
11
 
12
12
  def all
13
13
  return [] unless klass < ActiveRecord::Base
@@ -20,8 +20,8 @@ module Bogus
20
20
 
21
21
  private
22
22
 
23
- def instance_methods
24
- @instance_methods.call(klass)
23
+ def model_methods
24
+ instance_methods.call(klass)
25
25
  end
26
26
 
27
27
  def all_attributes
@@ -29,7 +29,7 @@ module Bogus
29
29
  end
30
30
 
31
31
  def missing_attributes
32
- all_attributes - instance_methods.all
32
+ all_attributes - model_methods.all
33
33
  end
34
34
 
35
35
  class Attribute < Struct.new(:name)