rspec-contracts 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ce4b2a2faf48c3f9f368745eed2e0a33243fe872
4
+ data.tar.gz: 8f01e23a2eed146f5bbe6407cd44fbaa51700cb8
5
+ SHA512:
6
+ metadata.gz: dbd6c1a8c64c9fcd1778ae4596abab1ed6f4d1e8d8015f376b6598ad6eb6ccf2670cb534e24c5149853886ca47620ac8f05964312f65f32e95fe5ed4d5dbf880
7
+ data.tar.gz: bad52385149dc5c04ca685fe0551ab9414ec17db7dbbb54faa42330e3d0ccdf9043fe32ebc4e5bc16227abe722874712178e2effbf85d4ec380c83c62e7cca8d
data/History.md ADDED
@@ -0,0 +1,4 @@
1
+ ### Version 0.0.1
2
+ 2014-3-4
3
+
4
+ * Show summary of unverified contracts after specs run
data/License.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Brian Auton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ ## Conjure
2
+
3
+ Automatic contract checking for your RSpec suite
4
+
5
+ ### Requirements
6
+
7
+ * Rspec 3.0.0.beta2
8
+
9
+ ### Getting Started
10
+
11
+ Install the rspec-contracts gem alongside rspec in your gemfile.
12
+
13
+ group :development, :test do
14
+ gem "rspec", "3.0.0.beta2"
15
+ gem "rspec-contracts"
16
+ end
17
+
18
+ Then update your bundle.
19
+
20
+ $ bundle
21
+
22
+ Define doubles using `contract_double`, providing the contract name as
23
+ the first argument.
24
+
25
+ user = contract_double(:user, email: "me@example.com")
26
+
27
+ Running the specs will then show a summary of unverified contracts.
28
+
29
+ $ rspec
@@ -0,0 +1,14 @@
1
+ require "rspec/core/example_group"
2
+ require "rspec/contracts/interface_proxy"
3
+
4
+ module RSpec
5
+ module Core
6
+ class ExampleGroup
7
+ def self.fulfill_contract(*interface_names)
8
+ interface_names.each do |interface_name|
9
+ Contracts::InterfaceProxy.create interface_name, described_class
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ require "rspec/mocks/test_double"
2
+ require "rspec/contracts/proxy"
3
+
4
+ module RSpec
5
+ module Contracts
6
+ class Double
7
+ include Mocks::TestDouble
8
+
9
+ def initialize(interface_name, *args)
10
+ @interface_name = interface_name
11
+ __initialize_as_test_double interface_name, *args
12
+ end
13
+
14
+ def __build_mock_proxy(order_group)
15
+ Proxy.new self, order_group, @interface_name
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ require "rspec/contracts/requirement"
2
+ require "rspec/contracts/requirement_view"
3
+
4
+ module RSpec
5
+ module Contracts
6
+ class Fulfillment
7
+ def initialize(requirement_group)
8
+ @requirement_group = requirement_group
9
+ end
10
+
11
+ def complete?
12
+ false
13
+ end
14
+
15
+ def unfulfilled_requirements
16
+ @requirement_group.requirements
17
+ end
18
+
19
+ def requirements_count
20
+ @requirement_group.requirements.count
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,38 @@
1
+ module RSpec
2
+ module Contracts
3
+ class FulfillmentView
4
+ def initialize(fulfillment)
5
+ @fulfillment = fulfillment
6
+ end
7
+
8
+ def render
9
+ @fulfillment.complete? ? render_complete : render_incomplete
10
+ end
11
+
12
+ def render_complete
13
+ "#{contracts_count} verified."
14
+ end
15
+
16
+ def render_incomplete
17
+ lines = unfulfilled_views
18
+ lines.unshift("WARNING: #{unfulfilled_views.count} of #{contracts_count} unverified.")
19
+ lines.join "\n"
20
+ end
21
+
22
+ def unfulfilled_views
23
+ @fulfillment.unfulfilled_requirements.map do |requirement|
24
+ RSpec::Contracts::RequirementView.new(requirement).render
25
+ end
26
+ end
27
+
28
+ def contracts_count
29
+ pluralize @fulfillment.requirements_count, "contract"
30
+ end
31
+
32
+ def pluralize(number, noun)
33
+ suffix = (number == 1) ? "" : "s"
34
+ "#{number} #{noun}#{suffix}"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ require "rspec/contracts/method_proxy"
2
+
3
+ module RSpec
4
+ module Contracts
5
+ class InterfaceProxy
6
+ def initialize(interface_name, proxied_class)
7
+ proxied_class.instance_methods.select{|m| proxyable_method? m}.each do |method_name|
8
+ MethodProxy.create interface_name, proxied_class, method_name
9
+ end
10
+ end
11
+
12
+ def proxyable_method?(method_name)
13
+ true
14
+ end
15
+
16
+ def self.create(*args)
17
+ new(*args)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ module RSpec
2
+ module Contracts
3
+ class MethodProxy
4
+ def self.create(*args)
5
+ new(*args)
6
+ end
7
+
8
+ private
9
+
10
+ def initialize(interface_name, proxied_class, method_name)
11
+ @interface_name = interface_name
12
+ @proxied_class = proxied_class
13
+ @method_name = method_name
14
+ install
15
+ end
16
+
17
+ def install
18
+ original_method = @proxied_class.instance_method @method_name
19
+ @proxied_class.send :define_method, @method_name do |*args|
20
+ original_method.bind(self).call(*args)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ require "rspec/contracts/double"
2
+
3
+ module RSpec
4
+ module Mocks
5
+ module ExampleMethods
6
+ def contract_double(*args)
7
+ ExampleMethods.declare_double Contracts::Double, *args
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,32 @@
1
+ require "rspec/mocks/proxy"
2
+ require "rspec/contracts/requirement"
3
+
4
+ module RSpec
5
+ module Contracts
6
+ class Proxy < Mocks::Proxy
7
+ def initialize(object, order_group, interface_name)
8
+ @interface_name = interface_name
9
+ super(object, order_group)
10
+ end
11
+
12
+ def add_stub(location, method_name, opts={}, &implementation)
13
+ create_requirement method_name
14
+ super
15
+ end
16
+
17
+ def add_simple_stub(method_name, *args)
18
+ create_requirement method_name, :return_value => args.first
19
+ super
20
+ end
21
+
22
+ def add_message_expectation(location, method_name, opts={}, &block)
23
+ create_requirement method_name
24
+ super
25
+ end
26
+
27
+ def create_requirement(method_name, options = {})
28
+ Requirement.create @interface_name, method_name, options
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ require "rspec/contracts/requirement_group"
2
+ require "rspec/contracts/requirement_view"
3
+
4
+ module RSpec
5
+ module Contracts
6
+ class Requirement
7
+ attr_reader :interface_name, :method_name, :arguments, :return_value
8
+
9
+ def initialize(interface_name, method_name, options = {})
10
+ @interface_name = interface_name
11
+ @method_name = method_name
12
+ @arguments = options[:arguments]
13
+ @return_value = options[:return_value]
14
+ end
15
+
16
+ def self.group
17
+ @group ||= RequirementGroup.new
18
+ end
19
+
20
+ def self.create(*args)
21
+ group.add new(*args)
22
+ end
23
+
24
+ def matches?(requirement)
25
+ [:interface_name, :method_name, :arguments, :return_value].select do |attribute|
26
+ requirement.send(attribute) != send(attribute)
27
+ end.empty?
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ module RSpec
2
+ module Contracts
3
+ class RequirementGroup
4
+ attr_accessor :requirements
5
+
6
+ def initialize
7
+ @requirements = []
8
+ end
9
+
10
+ def exists?(requirement)
11
+ @requirements.any?{|r| r.matches? requirement}
12
+ end
13
+
14
+ def add(requirement)
15
+ requirements << requirement unless exists? requirement
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ module RSpec
2
+ module Contracts
3
+ class RequirementView
4
+ def initialize(requirement)
5
+ @requirement = requirement
6
+ end
7
+
8
+ def render
9
+ arg_string = @requirement.arguments ? "()" : ""
10
+ return_string = @requirement.return_value ? "and return #{@requirement.return_value.inspect}" : ""
11
+ "Interface '#{@requirement.interface_name}' must respond to '#{@requirement.method_name}#{arg_string}' #{return_string}"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ module RSpec
2
+ module Contracts
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ require "rspec/contracts/core_syntax"
2
+ require "rspec/contracts/mocks_syntax"
3
+ require "rspec/contracts/fulfillment"
4
+ require "rspec/contracts/fulfillment_view"
5
+ require "rspec/contracts/requirement"
6
+ require "rspec/core"
7
+
8
+ RSpec.configure do |c|
9
+ c.after(:suite) do
10
+ requirement_group = RSpec::Contracts::Requirement.group
11
+ fulfillment = RSpec::Contracts::Fulfillment.new requirement_group
12
+ print "\n" + RSpec::Contracts::FulfillmentView.new(fulfillment).render
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-contracts
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Brian Auton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.0.beta2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.0.beta2
27
+ - !ruby/object:Gem::Dependency
28
+ name: guard-rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email:
57
+ - brianauton@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - History.md
63
+ - License.txt
64
+ - README.md
65
+ - lib/rspec/contracts.rb
66
+ - lib/rspec/contracts/core_syntax.rb
67
+ - lib/rspec/contracts/double.rb
68
+ - lib/rspec/contracts/fulfillment.rb
69
+ - lib/rspec/contracts/fulfillment_view.rb
70
+ - lib/rspec/contracts/interface_proxy.rb
71
+ - lib/rspec/contracts/method_proxy.rb
72
+ - lib/rspec/contracts/mocks_syntax.rb
73
+ - lib/rspec/contracts/proxy.rb
74
+ - lib/rspec/contracts/requirement.rb
75
+ - lib/rspec/contracts/requirement_group.rb
76
+ - lib/rspec/contracts/requirement_view.rb
77
+ - lib/rspec/contracts/version.rb
78
+ homepage: http://github.com/brianauton/rspec-contracts
79
+ licenses:
80
+ - MIT
81
+ metadata: {}
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: 1.3.6
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 2.2.2
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: Automatic contract checking for your RSpec suite
102
+ test_files: []