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.
- data/.travis.yml +1 -0
- data/Gemfile.lock +6 -1
- data/README.md +3 -0
- data/features/changelog.md +30 -22
- data/features/configuration/fake_ar_attributes.feature +3 -1
- data/features/configuration/search_modules.feature +5 -0
- data/features/contract_tests/contract_tests_mocks.feature +12 -1
- data/features/contract_tests/contract_tests_spies.feature +14 -2
- data/features/contract_tests/contract_tests_stubs.feature +13 -2
- data/features/contract_tests/return_value_contracts.feature +15 -4
- data/features/fakes/anonymous_doubles.feature +15 -1
- data/features/fakes/duck_types.feature +12 -2
- data/features/fakes/fake_objects.feature +11 -1
- data/features/fakes/global_fake_configuration.feature +4 -1
- data/features/readme.md +2 -2
- data/features/safe_stubbing/argument_matchers.feature +32 -2
- data/features/safe_stubbing/safe_mocking.feature +9 -2
- data/features/safe_stubbing/safe_stubbing.feature +11 -2
- data/features/safe_stubbing/spies.feature +52 -1
- data/features/step_definitions/rspec_steps.rb +1 -2
- data/features/support/env.rb +19 -0
- data/lib/bogus/active_record_accessors.rb +4 -4
- data/lib/bogus/adds_recording.rb +1 -0
- data/lib/bogus/any_args.rb +32 -3
- data/lib/bogus/class_methods.rb +7 -1
- data/lib/bogus/copies_classes.rb +5 -2
- data/lib/bogus/fake.rb +0 -2
- data/lib/bogus/have_received_matcher.rb +5 -0
- data/lib/bogus/interaction.rb +66 -35
- data/lib/bogus/interactions_repository.rb +1 -1
- data/lib/bogus/makes_substitute_methods.rb +3 -2
- data/lib/bogus/mocking_dsl.rb +8 -0
- data/lib/bogus/public_methods.rb +1 -1
- data/lib/bogus/rspec_extensions.rb +8 -1
- data/lib/bogus/same_class.rb +14 -0
- data/lib/bogus/shadow.rb +8 -12
- data/lib/bogus/verifies_stub_definition.rb +1 -5
- data/lib/bogus/version.rb +1 -1
- data/spec/bogus/adds_recording_spec.rb +8 -0
- data/spec/bogus/class_methods_spec.rb +8 -2
- data/spec/bogus/clean_ruby_spec.rb +15 -0
- data/spec/bogus/have_received_matcher_spec.rb +45 -27
- data/spec/bogus/instance_methods_spec.rb +1 -1
- data/spec/bogus/interaction_spec.rb +87 -83
- data/spec/bogus/interactions_repository_spec.rb +8 -11
- data/spec/bogus/shadow_spec.rb +4 -1
- metadata +81 -39
- 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 "
|
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
|
-
|
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 "
|
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 "
|
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
|
data/features/readme.md
CHANGED
@@ -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
|
-
|
41
|
-
|
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 "
|
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("
|
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 "
|
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
|
-
|
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 "
|
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
|
-
|
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 "
|
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 =
|
28
|
+
file_name = "foo_#{rand(1000000)}_spec.rb"
|
30
29
|
|
31
30
|
steps %Q{
|
32
31
|
Given a spec file named "#{file_name}" with:
|
data/features/support/env.rb
CHANGED
@@ -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 :
|
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
|
24
|
-
|
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 -
|
32
|
+
all_attributes - model_methods.all
|
33
33
|
end
|
34
34
|
|
35
35
|
class Attribute < Struct.new(:name)
|