bogus 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +1 -1
- data/Guardfile +1 -3
- data/Guardfile.cucumber +0 -2
- data/README.md +1 -1
- data/bogus.gemspec +3 -1
- data/features/changelog.md +11 -0
- data/features/configuration/fake_ar_attributes.feature +2 -2
- data/features/contract_tests/contract_tests_mocks.feature +5 -5
- data/features/contract_tests/contract_tests_spies.feature +1 -1
- data/features/contract_tests/contract_tests_stubs.feature +6 -6
- data/features/contract_tests/custom_overwritten_class.feature +4 -4
- data/features/contract_tests/return_value_contracts.feature +2 -2
- data/features/fakes/anonymous_doubles.feature +5 -5
- data/features/fakes/duck_types.feature +9 -9
- data/features/fakes/fake_objects.feature +31 -8
- data/features/fakes/global_fake_configuration.feature +5 -5
- data/features/fakes/replacing_classes.feature +5 -5
- data/features/readme.md +5 -5
- data/features/safe_stubbing/argument_matchers.feature +23 -10
- data/features/safe_stubbing/safe_mocking.feature +1 -1
- data/features/safe_stubbing/safe_stubbing.feature +1 -1
- data/features/safe_stubbing/spies.feature +7 -7
- data/lib/bogus.rb +1 -0
- data/lib/bogus/core_ext.rb +22 -0
- data/lib/bogus/fakes/fake.rb +2 -1
- data/lib/bogus/fakes/method_stringifier.rb +1 -0
- data/lib/bogus/mocking_dsl.rb +4 -0
- data/lib/bogus/stubbing/has_overwritten_methods.rb +28 -10
- data/lib/bogus/stubbing/have_received_matcher.rb +4 -2
- data/lib/bogus/stubbing/matchers/any_args.rb +9 -0
- data/lib/bogus/stubbing/matchers/matches_argument.rb +11 -0
- data/lib/bogus/stubbing/{any_args.rb → matchers/with_arguments.rb} +0 -6
- data/lib/bogus/stubbing/overwrites_methods.rb +6 -1
- data/lib/bogus/stubbing/undefined_return_value.rb +4 -0
- data/lib/bogus/support.rb +11 -0
- data/lib/bogus/version.rb +1 -1
- data/spec/bogus/clean_ruby_spec.rb +1 -1
- data/spec/bogus/configuration_spec.rb +2 -2
- data/spec/bogus/contracts/adds_contract_verification_spec.rb +10 -10
- data/spec/bogus/contracts/adds_recording_spec.rb +4 -4
- data/spec/bogus/contracts/interactions_repository_spec.rb +15 -15
- data/spec/bogus/contracts/proxy_class_spec.rb +7 -7
- data/spec/bogus/contracts/records_double_interactions_spec.rb +1 -1
- data/spec/bogus/contracts/verifies_contracts_spec.rb +3 -3
- data/spec/bogus/fakes/base_class_identifier_spec.rb +1 -1
- data/spec/bogus/fakes/class_methods_spec.rb +4 -5
- data/spec/bogus/fakes/converts_name_to_class_spec.rb +3 -3
- data/spec/bogus/fakes/copies_classes_spec.rb +20 -16
- data/spec/bogus/fakes/creates_fakes_spec.rb +6 -6
- data/spec/bogus/fakes/creates_fakes_with_stubbed_methods_spec.rb +16 -15
- data/spec/bogus/fakes/fake_ar_attributes_spec.rb +3 -3
- data/spec/bogus/fakes/fake_configuration_spec.rb +16 -16
- data/spec/bogus/fakes/fake_registry_spec.rb +2 -2
- data/spec/bogus/fakes/fake_spec.rb +1 -1
- data/spec/bogus/fakes/fakes_classes_spec.rb +4 -4
- data/spec/bogus/fakes/faking_factories_spec.rb +4 -4
- data/spec/bogus/fakes/frozen_fakes_spec.rb +4 -4
- data/spec/bogus/fakes/instance_methods_spec.rb +5 -5
- data/spec/bogus/fakes/makes_ducks_spec.rb +3 -3
- data/spec/bogus/fakes/makes_substitute_methods_spec.rb +1 -1
- data/spec/bogus/fakes/overwriten_classes_spec.rb +3 -3
- data/spec/bogus/fakes/overwrites_classes_spec.rb +2 -2
- data/spec/bogus/fakes/registers_created_fakes_spec.rb +3 -3
- data/spec/bogus/fakes/resets_overwritten_classes_spec.rb +3 -3
- data/spec/bogus/fakes/stubbing_new_method_on_fake_class_spec.rb +25 -0
- data/spec/bogus/mocking_dsl_spec.rb +36 -36
- data/spec/bogus/ruby_2_1_support_spec.rb +38 -0
- data/spec/bogus/ruby_2_support_spec.rb +14 -64
- data/spec/bogus/stubbing/anything_spec.rb +5 -5
- data/spec/bogus/stubbing/double_spec.rb +2 -2
- data/spec/bogus/stubbing/have_received_matcher_spec.rb +11 -6
- data/spec/bogus/stubbing/interaction_spec.rb +7 -7
- data/spec/bogus/stubbing/multi_stubber_spec.rb +2 -2
- data/spec/bogus/stubbing/overwrites_methods_spec.rb +8 -8
- data/spec/bogus/stubbing/record_interactions_spec.rb +3 -3
- data/spec/bogus/stubbing/shadow_spec.rb +28 -28
- data/spec/bogus/stubbing/stubbing_existing_methods_on_fakes_spec.rb +50 -0
- data/spec/bogus/stubbing/tracks_existence_of_test_doubles_spec.rb +2 -2
- data/spec/bogus/stubbing/undefined_return_value_spec.rb +2 -2
- data/spec/spec_helper.rb +6 -1
- data/spec/support/shared_examples_for_keyword_arguments.rb +63 -0
- metadata +160 -160
- data/Gemfile.lock +0 -146
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5692979cf19268250f0bd23067c79beca39210f9
|
4
|
+
data.tar.gz: eace904b3205850ab8a3359453d4fe1236e120fe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f8be32e8fbc29928cc5f517c10bf6602dee35910e0c2768d83ec0db7c8a62bdd993cc84482aec9d26dd4ecce2f096f80ac0c9bc8ed2c7f6092bf0e570c7fcf54
|
7
|
+
data.tar.gz: b12ed7d4b58170ff5f7180f559c054817ff7b84476808355d822b7d5270a34083d77f10996036d17d5a45f6da2da80b4e7e4de065e32ab65f244960b1fec43f5
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Guardfile
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
# A sample Guardfile
|
2
2
|
# More info at https://github.com/guard/guard#readme
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
guard 'rspec' do
|
4
|
+
guard 'rspec', all_after_pass: true, all_on_start: true do
|
7
5
|
watch(%r{^spec/.+_spec\.rb$})
|
8
6
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
9
7
|
watch('spec/spec_helper.rb') { "spec" }
|
data/Guardfile.cucumber
CHANGED
data/README.md
CHANGED
data/bogus.gemspec
CHANGED
@@ -36,8 +36,10 @@ Gem::Specification.new do |s|
|
|
36
36
|
s.add_development_dependency 'relish'
|
37
37
|
s.add_development_dependency 'coveralls'
|
38
38
|
|
39
|
-
s.add_development_dependency 'activerecord'
|
39
|
+
s.add_development_dependency 'activerecord', '>= 3', '< 5'
|
40
40
|
s.add_development_dependency 'activerecord-nulldb-adapter'
|
41
41
|
|
42
42
|
s.add_development_dependency 'minitest', '>= 4.7'
|
43
|
+
|
44
|
+
s.add_development_dependency "rb-readline", "~> 0.5.0" # fix for the can't modify string issue
|
43
45
|
end
|
data/features/changelog.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
## 0.1.5
|
2
|
+
|
3
|
+
- Made it possible to use fake objects in case/when statements (override ===)
|
4
|
+
- Allowed stubbing methods defined on Object, such as #to_json
|
5
|
+
- Added `matches` - for matching single arguments when stubbing
|
6
|
+
- Updated RSpec syntax in specs and features (thanks to Michael Durrant)
|
7
|
+
- Done some housekeeping around development dependencies/Gemfile.lock/TravisCI configuration (thanks to Ken Dreyer)
|
8
|
+
- Removed deprecation warnings when using Bogus with RSpec 3.0 (thanks to Michal Muskala)
|
9
|
+
- Added support for Ruby 2.1 required keyword arguments (thanks to Indrek Juhkam)
|
10
|
+
- Fixed a bug that made it impossible to stub .new on fake classes
|
11
|
+
|
1
12
|
## 0.1.4
|
2
13
|
|
3
14
|
- Support for contracts in minitest
|
@@ -48,6 +48,6 @@ Feature: fake_ar_attributes
|
|
48
48
|
post = fake(:blog_post, name: "the name")
|
49
49
|
stub(post).tags { "foo, bar" }
|
50
50
|
|
51
|
-
post.name.
|
52
|
-
post.tags.
|
51
|
+
expect(post.name).to eq("the name")
|
52
|
+
expect(post.tags).to eq("foo, bar")
|
53
53
|
"""
|
@@ -57,7 +57,7 @@ Feature: Contract tests with mocks
|
|
57
57
|
|
58
58
|
student.read("Moby Dick", library)
|
59
59
|
|
60
|
-
library.
|
60
|
+
expect(library).not_to have_received.checkout("Moby Dick")
|
61
61
|
end
|
62
62
|
end
|
63
63
|
"""
|
@@ -77,7 +77,7 @@ Feature: Contract tests with mocks
|
|
77
77
|
|
78
78
|
library.checkout("Moby Dick")
|
79
79
|
|
80
|
-
library.has_book?("Moby Dick").
|
80
|
+
expect(library.has_book?("Moby Dick")).to be_false
|
81
81
|
end
|
82
82
|
end
|
83
83
|
"""
|
@@ -95,11 +95,11 @@ Feature: Contract tests with mocks
|
|
95
95
|
it "allows checking out books that are in the inventory" do
|
96
96
|
library.return("Moby Dick")
|
97
97
|
|
98
|
-
library.has_book?("Moby Dick").
|
98
|
+
expect(library.has_book?("Moby Dick")).to be_true
|
99
99
|
end
|
100
100
|
|
101
101
|
it "does not allow checking out unavailable books" do
|
102
|
-
library.has_book?("Moby Dick").
|
102
|
+
expect(library.has_book?("Moby Dick")).to be_false
|
103
103
|
end
|
104
104
|
|
105
105
|
it "marks books as unavailable after they are checked out" do
|
@@ -107,7 +107,7 @@ Feature: Contract tests with mocks
|
|
107
107
|
|
108
108
|
library.checkout("Moby Dick")
|
109
109
|
|
110
|
-
library.has_book?("Moby Dick").
|
110
|
+
expect(library.has_book?("Moby Dick")).to be_false
|
111
111
|
end
|
112
112
|
end
|
113
113
|
"""
|
@@ -61,7 +61,7 @@ Feature: Contract tests with stubs
|
|
61
61
|
|
62
62
|
student.read("Moby Dick", library)
|
63
63
|
|
64
|
-
library.
|
64
|
+
expect(library).to have_received.checkout("Moby Dick")
|
65
65
|
end
|
66
66
|
|
67
67
|
it "does not check out the book from library if not available" do
|
@@ -70,7 +70,7 @@ Feature: Contract tests with stubs
|
|
70
70
|
|
71
71
|
student.read("Moby Dick", library)
|
72
72
|
|
73
|
-
library.
|
73
|
+
expect(library).not_to have_received.checkout("Moby Dick")
|
74
74
|
end
|
75
75
|
end
|
76
76
|
"""
|
@@ -90,7 +90,7 @@ Feature: Contract tests with stubs
|
|
90
90
|
|
91
91
|
library.checkout("Moby Dick")
|
92
92
|
|
93
|
-
library.has_book?("Moby Dick").
|
93
|
+
expect(library.has_book?("Moby Dick")).to be_false
|
94
94
|
end
|
95
95
|
end
|
96
96
|
"""
|
@@ -108,11 +108,11 @@ Feature: Contract tests with stubs
|
|
108
108
|
it "allows checking out books that are in the inventory" do
|
109
109
|
library.return("Moby Dick")
|
110
110
|
|
111
|
-
library.has_book?("Moby Dick").
|
111
|
+
expect(library.has_book?("Moby Dick")).to be_true
|
112
112
|
end
|
113
113
|
|
114
114
|
it "does not allow checking out unavailable books" do
|
115
|
-
library.has_book?("Moby Dick").
|
115
|
+
expect(library.has_book?("Moby Dick")).to be_false
|
116
116
|
end
|
117
117
|
|
118
118
|
it "marks books as unavailable after they are checked out" do
|
@@ -120,7 +120,7 @@ Feature: Contract tests with stubs
|
|
120
120
|
|
121
121
|
library.checkout("Moby Dick")
|
122
122
|
|
123
|
-
library.has_book?("Moby Dick").
|
123
|
+
expect(library.has_book?("Moby Dick")).to be_false
|
124
124
|
end
|
125
125
|
end
|
126
126
|
"""
|
@@ -77,7 +77,7 @@ Feature: Customizing the overwritten class
|
|
77
77
|
|
78
78
|
student.read("Moby Dick", library)
|
79
79
|
|
80
|
-
library.
|
80
|
+
expect(library).not_to have_received.checkout("Moby Dick")
|
81
81
|
end
|
82
82
|
end
|
83
83
|
"""
|
@@ -95,11 +95,11 @@ Feature: Customizing the overwritten class
|
|
95
95
|
it "allows checking out books that are in the inventory" do
|
96
96
|
library.return("Moby Dick")
|
97
97
|
|
98
|
-
library.has_book?("Moby Dick").
|
98
|
+
expect(library.has_book?("Moby Dick")).to be_true
|
99
99
|
end
|
100
100
|
|
101
101
|
it "does not allow checking out unavailable books" do
|
102
|
-
library.has_book?("Moby Dick").
|
102
|
+
expect(library.has_book?("Moby Dick")).to be_false
|
103
103
|
end
|
104
104
|
|
105
105
|
it "marks books as unavailable after they are checked out" do
|
@@ -107,7 +107,7 @@ Feature: Customizing the overwritten class
|
|
107
107
|
|
108
108
|
library.checkout("Moby Dick")
|
109
109
|
|
110
|
-
library.has_book?("Moby Dick").
|
110
|
+
expect(library.has_book?("Moby Dick")).to be_false
|
111
111
|
end
|
112
112
|
end
|
113
113
|
"""
|
@@ -51,13 +51,13 @@ Feature: Return value contracts
|
|
51
51
|
it "logs in the user with valid data" do
|
52
52
|
stub(authentication_service).authenticate('foo', 'bar')
|
53
53
|
|
54
|
-
controller.create(login: 'foo', password: 'bar').
|
54
|
+
expect(controller.create(login: 'foo', password: 'bar')).to eq(:render_welcome)
|
55
55
|
end
|
56
56
|
|
57
57
|
it "fails with invalid data" do
|
58
58
|
stub(authentication_service).authenticate('baz', 'bar') { raise WrongPassword }
|
59
59
|
|
60
|
-
controller.create(login: 'baz', password: 'bar').
|
60
|
+
expect(controller.create(login: 'baz', password: 'bar')).to eq(:render_error)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
"""
|
@@ -47,7 +47,7 @@ Feature: Anonymous test doubles
|
|
47
47
|
|
48
48
|
jake.sign_up(library)
|
49
49
|
|
50
|
-
jake.library_card.
|
50
|
+
expect(jake.library_card).to eq("the card")
|
51
51
|
end
|
52
52
|
end
|
53
53
|
"""
|
@@ -64,7 +64,7 @@ Feature: Anonymous test doubles
|
|
64
64
|
it "allows stubbing any method with any parameters" do
|
65
65
|
jake.sign_up(library)
|
66
66
|
|
67
|
-
jake.library_card.
|
67
|
+
expect(jake.library_card).to eq("the card")
|
68
68
|
end
|
69
69
|
end
|
70
70
|
"""
|
@@ -92,7 +92,7 @@ Feature: Anonymous test doubles
|
|
92
92
|
|
93
93
|
jake.sign_up(library)
|
94
94
|
|
95
|
-
jake.library_card.
|
95
|
+
expect(jake.library_card).to eq("the card")
|
96
96
|
end
|
97
97
|
end
|
98
98
|
"""
|
@@ -122,7 +122,7 @@ Feature: Anonymous test doubles
|
|
122
122
|
it "allows stubbing any method with any parameters" do
|
123
123
|
jake.sign_up(library)
|
124
124
|
|
125
|
-
jake.library_card.
|
125
|
+
expect(jake.library_card).to eq("the card")
|
126
126
|
end
|
127
127
|
end
|
128
128
|
"""
|
@@ -139,7 +139,7 @@ Feature: Anonymous test doubles
|
|
139
139
|
it "allows spying on any method" do
|
140
140
|
jake.sign_up(library)
|
141
141
|
|
142
|
-
library.
|
142
|
+
expect(library).to have_received.register_junior("Jake")
|
143
143
|
end
|
144
144
|
end
|
145
145
|
"""
|
@@ -64,31 +64,31 @@ Feature: Faking duck types
|
|
64
64
|
let(:duck_instance) { duck.new }
|
65
65
|
|
66
66
|
it "responds to error" do
|
67
|
-
duck_instance.
|
67
|
+
expect(duck_instance).to respond_to(:error)
|
68
68
|
end
|
69
69
|
|
70
70
|
it "has arity 1 for error" do
|
71
|
-
duck_instance.method(:error).arity.
|
71
|
+
expect(duck_instance.method(:error).arity).to eq(1)
|
72
72
|
end
|
73
73
|
|
74
74
|
it "responds to warn" do
|
75
|
-
duck_instance.
|
75
|
+
expect(duck_instance).to respond_to(:warn)
|
76
76
|
end
|
77
77
|
|
78
78
|
it "has arity 2 for warn" do
|
79
|
-
duck_instance.method(:warn).arity.
|
79
|
+
expect(duck_instance.method(:warn).arity).to eq(2)
|
80
80
|
end
|
81
81
|
|
82
82
|
it "does not respond to connection" do
|
83
|
-
duck_instance.
|
83
|
+
expect(duck_instance).not_to respond_to(:connection)
|
84
84
|
end
|
85
85
|
|
86
86
|
it "does not respond to socket" do
|
87
|
-
duck_instance.
|
87
|
+
expect(duck_instance).not_to respond_to(:socket)
|
88
88
|
end
|
89
89
|
|
90
90
|
it "does not respond to debug" do
|
91
|
-
duck_instance.
|
91
|
+
expect(duck_instance).not_to respond_to(:debug)
|
92
92
|
end
|
93
93
|
end
|
94
94
|
"""
|
@@ -108,7 +108,7 @@ Feature: Faking duck types
|
|
108
108
|
it "logs the exception" do
|
109
109
|
notifier.notify("whoa!")
|
110
110
|
|
111
|
-
logger.
|
111
|
+
expect(logger).to have_received.error("whoa!")
|
112
112
|
end
|
113
113
|
end
|
114
114
|
"""
|
@@ -138,7 +138,7 @@ Feature: Faking duck types
|
|
138
138
|
it "logs the exception" do
|
139
139
|
notifier.notify("whoa!")
|
140
140
|
|
141
|
-
logger.
|
141
|
+
expect(logger).to have_received.error("whoa!")
|
142
142
|
end
|
143
143
|
end
|
144
144
|
"""
|
@@ -60,7 +60,7 @@ Feature: Faking existing classes
|
|
60
60
|
fake(:library)
|
61
61
|
|
62
62
|
it "does something" do
|
63
|
-
Student.learn(library).
|
63
|
+
expect(Student.learn(library)).to be_true
|
64
64
|
end
|
65
65
|
end
|
66
66
|
"""
|
@@ -77,7 +77,7 @@ Feature: Faking existing classes
|
|
77
77
|
fake(:library) { PublicLibrary }
|
78
78
|
|
79
79
|
it "uses the class provided in block instead of the guessed one" do
|
80
|
-
library.class.name.
|
80
|
+
expect(library.class.name).to eq("PublicLibrary")
|
81
81
|
end
|
82
82
|
end
|
83
83
|
"""
|
@@ -91,11 +91,11 @@ Feature: Faking existing classes
|
|
91
91
|
fake(:library, as: :class)
|
92
92
|
|
93
93
|
it "is a class" do
|
94
|
-
library.
|
94
|
+
expect(library).to be_a(Class)
|
95
95
|
end
|
96
96
|
|
97
97
|
it "has the same name as original class" do
|
98
|
-
library.name.
|
98
|
+
expect(library.name).to eq(Library.name)
|
99
99
|
end
|
100
100
|
|
101
101
|
it "has same methods as original class" do
|
@@ -114,10 +114,33 @@ Feature: Faking existing classes
|
|
114
114
|
return_book: "returned") }
|
115
115
|
|
116
116
|
it "sets the default return value for provided functions" do
|
117
|
-
library.checkout("Moby Dick").
|
118
|
-
library.checkout("Three Musketeers").
|
119
|
-
library.return_book("Moby Dick").
|
120
|
-
library.return_book("Three Musketeers").
|
117
|
+
expect(library.checkout("Moby Dick")).to eq("checked out")
|
118
|
+
expect(library.checkout("Three Musketeers")).to eq("checked out")
|
119
|
+
expect(library.return_book("Moby Dick")).to eq("returned")
|
120
|
+
expect(library.return_book("Three Musketeers")).to eq("returned")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
"""
|
124
|
+
|
125
|
+
Scenario: Fakes are identified as instances of the faked class
|
126
|
+
Then spec file with following content should pass:
|
127
|
+
"""ruby
|
128
|
+
require_relative 'library'
|
129
|
+
|
130
|
+
def library?(object)
|
131
|
+
case object
|
132
|
+
when Library
|
133
|
+
true
|
134
|
+
else
|
135
|
+
false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "library class fake" do
|
140
|
+
fake(:library)
|
141
|
+
|
142
|
+
it "is identified as Library" do
|
143
|
+
expect(library?(library)).to be_true
|
121
144
|
end
|
122
145
|
end
|
123
146
|
"""
|
@@ -46,17 +46,17 @@ Feature: Global fake configuration
|
|
46
46
|
|
47
47
|
it "is a class" do
|
48
48
|
# because of the as: :class specified in the fake definition
|
49
|
-
library.
|
49
|
+
expect(library).to be_an_instance_of(Class)
|
50
50
|
end
|
51
51
|
|
52
52
|
it "is a copy of PublicLibrary" do
|
53
53
|
# because of the block passed into configuration
|
54
|
-
library.name.
|
54
|
+
expect(library.name).to eq("PublicLibrary")
|
55
55
|
end
|
56
56
|
|
57
57
|
it "returns has stubbed books_by_author" do
|
58
58
|
# because of the inline-stubbed books_by_author
|
59
|
-
library.books_by_author("Mark Twain").
|
59
|
+
expect(library.books_by_author("Mark Twain")).to eq([])
|
60
60
|
end
|
61
61
|
end
|
62
62
|
"""
|
@@ -71,7 +71,7 @@ Feature: Global fake configuration
|
|
71
71
|
fake(:library, books_by_author: ["Some Book"])
|
72
72
|
|
73
73
|
it "can be overridden in the shortcut definition" do
|
74
|
-
library.books_by_author("Charles Dickens").
|
74
|
+
expect(library.books_by_author("Charles Dickens")).to eq(["Some Book"])
|
75
75
|
end
|
76
76
|
end
|
77
77
|
"""
|
@@ -85,7 +85,7 @@ Feature: Global fake configuration
|
|
85
85
|
describe "The library fake" do
|
86
86
|
it "can be overridden in the helper" do
|
87
87
|
library = fake(:library, books_by_author: ["Some Book"])
|
88
|
-
library.books_by_author("Charles Dickens").
|
88
|
+
expect(library.books_by_author("Charles Dickens")).to eq(["Some Book"])
|
89
89
|
end
|
90
90
|
end
|
91
91
|
"""
|