bogus 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+