bogus 0.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 (72) hide show
  1. data/.gitignore +7 -0
  2. data/.pelusa.yml +1 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +75 -0
  6. data/Guardfile +15 -0
  7. data/README.md +272 -0
  8. data/Rakefile +1 -0
  9. data/bogus.gemspec +34 -0
  10. data/features/configuration_options.feature +43 -0
  11. data/features/contract_tests_mocks.feature +100 -0
  12. data/features/contract_tests_spies.feature +72 -0
  13. data/features/contract_tests_stubs.feature +101 -0
  14. data/features/fake_objects.feature +94 -0
  15. data/features/return_value_contracts.feature +90 -0
  16. data/features/safe_mocking.feature +59 -0
  17. data/features/safe_stubbing.feature +62 -0
  18. data/features/spies.feature +78 -0
  19. data/features/step_definitions/rspec_steps.rb +68 -0
  20. data/features/support/env.rb +1 -0
  21. data/lib/bogus.rb +35 -0
  22. data/lib/bogus/adds_recording.rb +11 -0
  23. data/lib/bogus/configuration.rb +9 -0
  24. data/lib/bogus/contract_not_fulfilled.rb +24 -0
  25. data/lib/bogus/converts_name_to_class.rb +31 -0
  26. data/lib/bogus/copies_classes.rb +44 -0
  27. data/lib/bogus/creates_fakes.rb +32 -0
  28. data/lib/bogus/double.rb +10 -0
  29. data/lib/bogus/fake.rb +33 -0
  30. data/lib/bogus/fake_registry.rb +13 -0
  31. data/lib/bogus/injector.rb +64 -0
  32. data/lib/bogus/interaction.rb +24 -0
  33. data/lib/bogus/interaction_presenter.rb +29 -0
  34. data/lib/bogus/interactions_repository.rb +19 -0
  35. data/lib/bogus/invocation_matcher.rb +27 -0
  36. data/lib/bogus/method_stringifier.rb +31 -0
  37. data/lib/bogus/overwrites_classes.rb +9 -0
  38. data/lib/bogus/proxy_class.rb +22 -0
  39. data/lib/bogus/public_methods.rb +46 -0
  40. data/lib/bogus/record_interactions.rb +17 -0
  41. data/lib/bogus/recording_proxy.rb +18 -0
  42. data/lib/bogus/records_double_interactions.rb +11 -0
  43. data/lib/bogus/registers_created_fakes.rb +11 -0
  44. data/lib/bogus/rr_proxy.rb +5 -0
  45. data/lib/bogus/rspec.rb +4 -0
  46. data/lib/bogus/rspec_extensions.rb +32 -0
  47. data/lib/bogus/takes.rb +8 -0
  48. data/lib/bogus/verifies_contracts.rb +12 -0
  49. data/lib/bogus/verifies_stub_definition.rb +37 -0
  50. data/lib/bogus/version.rb +3 -0
  51. data/pelusa.sh +3 -0
  52. data/rbs.sh +3 -0
  53. data/spec/bogus/adds_recording_spec.rb +33 -0
  54. data/spec/bogus/configuration_spec.rb +17 -0
  55. data/spec/bogus/converts_name_to_class_spec.rb +40 -0
  56. data/spec/bogus/copies_classes_spec.rb +175 -0
  57. data/spec/bogus/creates_fakes_spec.rb +59 -0
  58. data/spec/bogus/double_spec.rb +31 -0
  59. data/spec/bogus/fake_registry_spec.rb +24 -0
  60. data/spec/bogus/interaction_spec.rb +68 -0
  61. data/spec/bogus/interactions_repository_spec.rb +50 -0
  62. data/spec/bogus/invocation_matcher_spec.rb +26 -0
  63. data/spec/bogus/mocking_dsl_spec.rb +76 -0
  64. data/spec/bogus/overwrites_classes_spec.rb +26 -0
  65. data/spec/bogus/proxy_class_spec.rb +95 -0
  66. data/spec/bogus/record_interactions_spec.rb +27 -0
  67. data/spec/bogus/records_double_interactions_spec.rb +25 -0
  68. data/spec/bogus/registers_created_fakes_spec.rb +25 -0
  69. data/spec/bogus/verifies_contracts_spec.rb +42 -0
  70. data/spec/bogus/verifies_stub_definition_spec.rb +71 -0
  71. data/spec/spec_helper.rb +14 -0
  72. metadata +299 -0
@@ -0,0 +1,100 @@
1
+ Feature: Contract tests with mocks
2
+
3
+ Background:
4
+ Given a file named "foo.rb" with:
5
+ """ruby
6
+ class Library
7
+ def initialize
8
+ @books = []
9
+ end
10
+
11
+ def has_book?(book)
12
+ @books.include?(book)
13
+ end
14
+
15
+ def checkout(book)
16
+ @books.delete(book)
17
+ end
18
+
19
+ def return(book)
20
+ @books << book
21
+ end
22
+ end
23
+
24
+ class Student
25
+ def read(book, library = Library.new)
26
+ if library.has_book?(book)
27
+ library.checkout(book)
28
+ end
29
+ end
30
+ end
31
+ """
32
+ And a spec file named "student_spec.rb" with:
33
+ """ruby
34
+ describe Student do
35
+ fake(:library)
36
+
37
+ it "checks out the book from library if it is available" do
38
+ student = Student.new
39
+ mock(library).has_book?("Moby Dick") { true }
40
+ mock(library).checkout("Moby Dick") { "Moby Dick" }
41
+
42
+ student.read("Moby Dick", library)
43
+ end
44
+
45
+ it "does not check out the book from library if not available" do
46
+ student = Student.new
47
+ mock(library).has_book?("Moby Dick") { false }
48
+ dont_allow(library).checkout("Moby Dick")
49
+
50
+ student.read("Moby Dick", library)
51
+ end
52
+ end
53
+ """
54
+
55
+ Scenario: Fails when mocked methods are not called on real object
56
+ Then spec file with following content should fail:
57
+ """ruby
58
+ describe Library do
59
+ verify_contract(:library)
60
+
61
+ let(:library) { Library.new }
62
+
63
+ it "marks books as unavailable after they are checked out" do
64
+ library.return("Moby Dick")
65
+
66
+ library.checkout("Moby Dick")
67
+
68
+ library.has_book?("Moby Dick").should be_false
69
+ end
70
+ end
71
+ """
72
+
73
+ Scenario: Verifies that mocked methods are called
74
+ Then spec file with following content should pass:
75
+ """ruby
76
+ describe Library do
77
+ verify_contract(:library)
78
+
79
+ let(:library) { Library.new }
80
+
81
+ it "allows checking out books that are in the inventory" do
82
+ library.return("Moby Dick")
83
+
84
+ library.has_book?("Moby Dick").should be_true
85
+ end
86
+
87
+ it "does not allow checking out unavailable books" do
88
+ library.has_book?("Moby Dick").should be_false
89
+ end
90
+
91
+ it "marks books as unavailable after they are checked out" do
92
+ library.return("Moby Dick")
93
+
94
+ library.checkout("Moby Dick")
95
+
96
+ library.has_book?("Moby Dick").should be_false
97
+ end
98
+ end
99
+ """
100
+
@@ -0,0 +1,72 @@
1
+ Feature: Contract tests with spies
2
+
3
+ Background:
4
+ Given a file named "foo.rb" with:
5
+ """ruby
6
+ class Library
7
+ def checkout(book)
8
+ end
9
+ end
10
+
11
+ class Student
12
+ def read(book, library = Libarary.new)
13
+ library.checkout(book)
14
+ # ...
15
+ end
16
+ end
17
+ """
18
+ And a spec file named "student_spec.rb" with:
19
+ """ruby
20
+ describe Student do
21
+ fake(:library)
22
+
23
+ it "reads books from library" do
24
+ student = Student.new
25
+
26
+ student.read("Moby Dick", library)
27
+
28
+ library.should have_received.checkout("Moby Dick")
29
+ end
30
+ end
31
+ """
32
+
33
+ Scenario: Stubbing methods that exist on real object
34
+ Then spec file with following content should pass:
35
+ """ruby
36
+ describe Library do
37
+ verify_contract(:library)
38
+
39
+ it "checks out books" do
40
+ library = Library.new
41
+
42
+ library.checkout("Moby Dick")
43
+
44
+ # ...
45
+ end
46
+ end
47
+ """
48
+
49
+ Scenario: Verifing that stubbed methods are tested
50
+ Then spec file with following content should fail:
51
+ """ruby
52
+ describe Library do
53
+ verify_contract(:library)
54
+
55
+ end
56
+ """
57
+
58
+ Scenario: Verifying that methods are tested with right arguments
59
+ Then spec file with following content should fail:
60
+ """ruby
61
+ describe Library do
62
+ verify_contract(:library)
63
+
64
+ it "checks out books" do
65
+ library = Library.new
66
+
67
+ library.checkout("Moby Dick 2: The ulitmate")
68
+
69
+ # ...
70
+ end
71
+ end
72
+ """
@@ -0,0 +1,101 @@
1
+ Feature: Contract tests with stubs
2
+
3
+ Background:
4
+ Given a file named "foo.rb" with:
5
+ """ruby
6
+ class Library
7
+ def initialize
8
+ @books = []
9
+ end
10
+
11
+ def has_book?(book)
12
+ @books.include?(book)
13
+ end
14
+
15
+ def checkout(book)
16
+ @books.delete(book)
17
+ end
18
+
19
+ def return(book)
20
+ @books << book
21
+ end
22
+ end
23
+
24
+ class Student
25
+ def read(book, library = Library.new)
26
+ if library.has_book?(book)
27
+ library.checkout(book)
28
+ end
29
+ end
30
+ end
31
+ """
32
+ And a spec file named "student_spec.rb" with:
33
+ """ruby
34
+ describe Student do
35
+ fake(:library)
36
+
37
+ it "checks out the book from library if it is available" do
38
+ student = Student.new
39
+ stub(library).has_book?("Moby Dick") { true }
40
+
41
+ student.read("Moby Dick", library)
42
+
43
+ library.should have_received.checkout("Moby Dick")
44
+ end
45
+
46
+ it "does not check out the book from library if not available" do
47
+ student = Student.new
48
+ stub(library).has_book?("Moby Dick") { false }
49
+
50
+ student.read("Moby Dick", library)
51
+
52
+ library.should_not have_received.checkout("Moby Dick")
53
+ end
54
+ end
55
+ """
56
+
57
+ Scenario: Fails when stubbed methods are not called on real object
58
+ Then spec file with following content should fail:
59
+ """ruby
60
+ describe Library do
61
+ verify_contract(:library)
62
+
63
+ let(:library) { Library.new }
64
+
65
+ it "marks books as unavailable after they are checked out" do
66
+ library.return("Moby Dick")
67
+
68
+ library.checkout("Moby Dick")
69
+
70
+ library.has_book?("Moby Dick").should be_false
71
+ end
72
+ end
73
+ """
74
+
75
+ Scenario: Verifies that stubbed methods are called
76
+ Then spec file with following content should pass:
77
+ """ruby
78
+ describe Library do
79
+ verify_contract(:library)
80
+
81
+ let(:library) { Library.new }
82
+
83
+ it "allows checking out books that are in the inventory" do
84
+ library.return("Moby Dick")
85
+
86
+ library.has_book?("Moby Dick").should be_true
87
+ end
88
+
89
+ it "does not allow checking out unavailable books" do
90
+ library.has_book?("Moby Dick").should be_false
91
+ end
92
+
93
+ it "marks books as unavailable after they are checked out" do
94
+ library.return("Moby Dick")
95
+
96
+ library.checkout("Moby Dick")
97
+
98
+ library.has_book?("Moby Dick").should be_false
99
+ end
100
+ end
101
+ """
@@ -0,0 +1,94 @@
1
+ Feature: Faking existing classes
2
+
3
+ Bogus makes it easy to create fakes, which behave like a null-object and
4
+ have the same interface as the object being faked.
5
+
6
+ Background:
7
+ Given a file named "foo.rb" with:
8
+ """ruby
9
+ class Library
10
+ def checkout(book)
11
+ end
12
+
13
+ def return_book(book)
14
+ end
15
+
16
+ def self.look_up(book)
17
+ end
18
+ end
19
+
20
+ class Student
21
+ def self.learn(library = Library.new)
22
+ library.checkout("hello world")
23
+ true
24
+ end
25
+ end
26
+ """
27
+
28
+ Scenario: Calling methods that exist on real object
29
+ Then spec file with following content should pass:
30
+ """ruby
31
+ describe Student do
32
+ fake(:library)
33
+
34
+ it "does something" do
35
+ Student.learn(library).should be_true
36
+ end
37
+ end
38
+ """
39
+
40
+ Scenario: Fakes have null-object semantics
41
+ Then spec file with following content should pass:
42
+ """ruby
43
+ describe "library fake" do
44
+ fake(:library)
45
+
46
+ it "returns self from all methods" do
47
+ library.checkout("hello").should == library
48
+ end
49
+
50
+ it "makes method chaining possible" do
51
+ library.checkout("hello").return_book("world").should == library
52
+ end
53
+ end
54
+ """
55
+
56
+ Scenario: Taking the guesswork out of finding a class to copy
57
+ Then spec file with following content should pass:
58
+ """ruby
59
+ class PublicLibrary
60
+ def checkout(book)
61
+ end
62
+ end
63
+
64
+ describe "logger fake" do
65
+ fake(:library) { PublicLibrary }
66
+
67
+ it "uses the class provided in block instead of the guessed one" do
68
+ library.class.name.should == "PublicLibrary"
69
+ end
70
+ end
71
+ """
72
+
73
+ Scenario: Fakes which are classes
74
+ Then spec file with following content should pass:
75
+ """ruby
76
+ describe "library class fake" do
77
+ fake(:library, as: :class)
78
+
79
+ it "is a class" do
80
+ library.should be_a(Class)
81
+ end
82
+
83
+ it "has the same name as original class" do
84
+ library.name.should == Library.name
85
+ end
86
+
87
+ it "has same methods as original class" do
88
+ library.look_up('something')
89
+ end
90
+ end
91
+ """
92
+
93
+ Scenario: Fakes which are objects
94
+ Given pending
@@ -0,0 +1,90 @@
1
+ Feature: Return value contracts
2
+
3
+ Background:
4
+ Given a file named "foo.rb" with:
5
+ """ruby
6
+ class SessionController
7
+ def initialize(authentication_service)
8
+ @authentication_service = authentication_service
9
+ end
10
+
11
+ def create(params)
12
+ @authentication_service.authenticate(params[:login], params[:password])
13
+ :render_welcome
14
+ rescue
15
+ :render_error
16
+ end
17
+ end
18
+
19
+ class WrongPassword < StandardError
20
+ end
21
+
22
+ class AuthenticationService
23
+ def initialize(user_db)
24
+ @user_db = user_db
25
+ end
26
+
27
+ def authenticate(login, password)
28
+ unless @user_db[login] == Digest::SHA1.hexdigest(password)
29
+ raise WrongPassword
30
+ end
31
+ end
32
+ end
33
+ """
34
+ And a spec file named "session_controller_spec.rb" with:
35
+ """ruby
36
+ describe SessionController do
37
+ fake(:authentication_service)
38
+ let(:controller) { SessionController.new(authentication_service) }
39
+
40
+ it "logs in the user with valid data" do
41
+ stub(authentication_service).authenticate('foo', 'bar')
42
+
43
+ controller.create(login: 'foo', password: 'bar').should == :render_welcome
44
+ end
45
+
46
+ it "fails with invalid data" do
47
+ stub(authentication_service).authenticate('baz', 'bar') { raise WrongPassword }
48
+
49
+ controller.create(login: 'baz', password: 'bar').should == :render_error
50
+ end
51
+ end
52
+ """
53
+
54
+ Scenario: Fails when returned values differ
55
+ Then spec file with following content should fail:
56
+ """ruby
57
+ describe AuthenticationService do
58
+ verify_contract(:authentication_service)
59
+
60
+ it "logs in the user" do
61
+ service = AuthenticationService.new('foo' => Digest::SHA1.hexdigest('bar'))
62
+ expect {
63
+ service.authenticate('foo', 'bar')
64
+ }.not_to raise_error
65
+ end
66
+ end
67
+ """
68
+
69
+ Scenario: Passes when interfaces match
70
+ Then spec file with following content should pass:
71
+ """ruby
72
+ describe AuthenticationService do
73
+ verify_contract(:authentication_service)
74
+
75
+ it "logs in the user" do
76
+ service = AuthenticationService.new('foo' => Digest::SHA1.hexdigest('bar'))
77
+ expect {
78
+ service.authenticate('foo', 'bar')
79
+ }.not_to raise_error
80
+ end
81
+
82
+ it "raises WrongPassword with incorrect credentials" do
83
+ service = AuthenticationService.new('foo' => Digest::SHA1.hexdigest('bar'))
84
+ expect {
85
+ service.authenticate('baz', 'bar')
86
+ }.to raise_error(WrongPassword)
87
+ end
88
+ end
89
+ """
90
+