blunt_stub_factory 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: b28dedc5ea8959a845e8b1aadc8476d40c386ed0
4
+ data.tar.gz: e0e64b1248c8e3e98a0e8fc96857eb9bf1938ff7
5
+ SHA512:
6
+ metadata.gz: e056ee77751634e4958a5c29be3cdb23afc5f6bf08e7a06ccbac632ee9ce4cfa1062e725276b758e2266d3624f4db980a423d5f59ca66d19c106620d2aa246e8
7
+ data.tar.gz: b4b26b7f052e4b9e91cc97553792b8d16462b7979be4b5c2055d05f092703dfb10fb0713abd3ab93311122db0a49079732f33e5cfb2f24a5b3c87f7ab09cabee
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in stub_factory.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 LFDM
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # StubFactory
2
+
3
+ A blunt StubFactory that helps to test tightly coupled code, but handle with care: This is not a best practice. If you find yourself relying on this a lot, you might have to rethink your design.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'stub_factory'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install stub_factory
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ require 'stub_factory'
23
+
24
+ Class A
25
+ attr_reader :test, :test2
26
+
27
+ def initialize
28
+ @test = "a value"
29
+ @test2 = "another value"
30
+ end
31
+
32
+ def a_method
33
+ "original return"
34
+ end
35
+ end
36
+ ```
37
+
38
+ StubFactory provides a method to bypass the constructor of an object and set it's instance variables by force.
39
+
40
+ ```ruby
41
+ a = A.new_stub(vars: { test: "overwritten" })
42
+ b = A.new
43
+
44
+ a.test
45
+ # => "overwritten"
46
+ b.test
47
+ # => "original value"
48
+ ```
49
+
50
+ Default as well as custom templates to overwrite variables can be defined - StubFactory automatically looks for such statements
51
+ in your spec/factories folder.
52
+ ```ruby
53
+ StubFactory.define_template(:a) do
54
+ { test2 = "template value" }
55
+ end
56
+
57
+ StubFactory.define_template(:other) do
58
+ { test2 = "custom value" }
59
+ end
60
+
61
+ # a new stub tries to look up a template by his class name by default
62
+ a = A.new_stub
63
+ a.test2
64
+ # => "template value"
65
+
66
+ # default template overwritten with custom template
67
+ b = A.new_stub(template: :custom)
68
+ b.test2
69
+ # => "custom value"
70
+
71
+ # if template is passed with a value of nil, no template will be used
72
+ c = A.new_stub(template: nil)
73
+ c.test2
74
+ # => "another value"
75
+ ```
76
+
77
+ Method return values can be stubbed.
78
+ ```ruby
79
+ a = A.new_stub(methods: { a_method: "overwritten method" }
80
+ b = A.new
81
+
82
+ a.a_method
83
+ # => "overwritten method"
84
+ b.a_method
85
+ # => "original return"
86
+ ```
87
+
88
+ For ease of use, helper methods can be defined when they are included in your RSpec configuarion.
89
+ Place define_helper statements in your spec/support/helpers folder.
90
+ ```ruby
91
+ RSpec.configure do |config|
92
+ config.include StubFactory::Helpers
93
+ end
94
+
95
+ StubFactory.define_helper(:a, :A) do
96
+ { vars: { test: 1 }, methods: { a_method: 2 } }
97
+ end
98
+ # creates a method stub_a, which translates to A.new_stub(vars: { test: 1 }, methods: { a_method: 2 })
99
+
100
+ # given a defined template, the helper will automatically refer to it
101
+ StubFactory.define_template(:foo) do
102
+ { test: 1 }
103
+ end
104
+
105
+ StubFactory.define_helper(:foo, :A) do
106
+ { vars: { test2: 2 } }
107
+ end
108
+
109
+ a = stub_foo
110
+ a.class
111
+ # => A
112
+ a.test
113
+ # => 1
114
+ a.test2
115
+ # => 2
116
+
117
+ # all default values can be overwritten
118
+ a = stub_foo(vars: { test2: "bypassed" })
119
+ a.test2
120
+ # => "bypassed"
121
+ ```
122
+ ## Contributing
123
+
124
+ 1. Fork it
125
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
126
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
127
+ 4. Push to the branch (`git push origin my-new-feature`)
128
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.rspec_opts = '-f d --color'
6
+ end
7
+
8
+ task :default => :spec
@@ -0,0 +1,4 @@
1
+ module StubFactory
2
+ class TemplateError < ArgumentError; end
3
+ class HelperError < ArgumentError; end
4
+ end
@@ -0,0 +1,10 @@
1
+ module StubFactory
2
+ module Helpers
3
+ # Namespace for methods created by StubFactory.define_helper.
4
+ # Include this module in RSpec to make use of 'em, e.g:
5
+ #
6
+ # RSpec.configure do |config|
7
+ # config.include StubFactory::Helpers
8
+ # end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module StubFactory
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,121 @@
1
+ require 'stub_factory/version'
2
+ require 'stub_factory/exceptions'
3
+ require 'stub_factory/helpers'
4
+
5
+ module StubFactory
6
+ @stub_factory_paths = %w{ spec/factories }
7
+ @stub_factory_helpers_paths = %w{ spec/support/helpers }
8
+ @templates = {}
9
+ @helpers = []
10
+
11
+ class << self
12
+
13
+ ####### Template Handing #######
14
+
15
+ def define_template(template_name)
16
+ tn = template_name.to_sym
17
+ raise TemplateError, "Template already defined" if template_defined?(tn)
18
+ raise TemplateError, "Templates need to be defined with a block" unless block_given?
19
+ values = yield
20
+ raise TemplateError, "Block must contain a Hash" unless values.kind_of?(Hash)
21
+ @templates[tn] = values
22
+ end
23
+
24
+ def template_defined?(template)
25
+ return unless template
26
+ @templates.has_key?(template.to_sym)
27
+ end
28
+
29
+ def template_for(template)
30
+ @templates[template.to_sym]
31
+ end
32
+
33
+ ####### Helper Handling #######
34
+
35
+ def define_helper(helper, klass)
36
+ raise HelperError, "A helper for #{helper} has already been defined" if helper_defined?(helper)
37
+ @helpers << helper.to_sym
38
+
39
+ Helpers.class_eval <<-STR
40
+ def stub_#{helper}(vars: {}, methods: {})
41
+ #{klass}.new_stub(vars: vars, methods: methods, template: :#{helper})
42
+ end
43
+ STR
44
+ end
45
+
46
+ def helper_defined?(helper)
47
+ @helpers.include?(helper.to_sym)
48
+ end
49
+
50
+ ####### Requiring Files #######
51
+
52
+ def recursive_require(rel_paths)
53
+ rel_paths.each do |rel_path|
54
+ require_path(rel_path)
55
+ end
56
+ end
57
+
58
+ def require_path(rel_path)
59
+ path = File.expand_path(rel_path)
60
+
61
+ if File.exists?(path)
62
+ require "#{path}" if File.file?(path)
63
+ Dir["#{path}/*"].each { |file| require_path(file) }
64
+ end
65
+ end
66
+ end
67
+
68
+ ####### Custom Load Paths - currently not enabled #######
69
+
70
+ #def add_factory_path(path)
71
+ # @stub_factory_paths << path
72
+ #end
73
+
74
+ #def add_helpers_path(path)
75
+ # @stub_factory_helpers_paths << path
76
+ #end
77
+
78
+ recursive_require(@stub_factory_paths)
79
+ recursive_require(@stub_factory_helpers_paths)
80
+
81
+ ####### Public Method #######
82
+
83
+ def new_stub(vars: {}, methods: {}, template: to_underscored_symbol(self.name))
84
+ obj = allocate
85
+
86
+ if StubFactory.template_defined?(template)
87
+ vars = StubFactory.template_for(template).merge(vars)
88
+ end
89
+
90
+ set_instance_variables(obj, vars)
91
+ override_methods(obj, methods)
92
+ obj
93
+ end
94
+
95
+ private
96
+
97
+ def set_instance_variables(obj, vars)
98
+ vars.each do |var, val|
99
+ obj.instance_variable_set("@#{var}", val)
100
+ end
101
+ end
102
+
103
+ def override_methods(obj, methods)
104
+ methods.each do |meth, val|
105
+ obj.send(:define_singleton_method, meth) do
106
+ val
107
+ end
108
+ end
109
+ end
110
+
111
+ def to_underscored_symbol(class_name)
112
+ # Namespace::TestClass to :namespace__test_class
113
+ res = class_name.to_s.dup
114
+ res.gsub!(/([a-z])([A-Z])/) { "#{$1}_#{$2}" }
115
+ res.gsub!(/::/, "__")
116
+ res.downcase.to_sym
117
+ end
118
+ module_function :to_underscored_symbol
119
+ end
120
+
121
+ class Class; include StubFactory; end
@@ -0,0 +1,3 @@
1
+ StubFactory.define_template(:required_template) do
2
+ { test: 11 }
3
+ end
@@ -0,0 +1,145 @@
1
+ require 'stub_factory'
2
+
3
+ # Methods defined by .define_helper will not work without this:
4
+ RSpec.configure do |config|
5
+ config.include StubFactory::Helpers
6
+ end
7
+
8
+ describe StubFactory do
9
+ before :all do
10
+ # the attr reader is set for convenience
11
+ class A; attr_reader :test; end
12
+ end
13
+
14
+ describe ".define_template" do
15
+ after :each do
16
+ # delete the just created template because it would persist
17
+ StubFactory.instance_variable_get(:@templates).delete(:test)
18
+ end
19
+
20
+ it "defines a template" do
21
+ StubFactory.define_template(:test) { {} }
22
+ StubFactory.template_defined?(:test).should be_true
23
+ end
24
+
25
+ it "templates can only be defined once" do
26
+ StubFactory.define_template(:test) { {} }
27
+ expect { StubFactory.define_template(:test) { {} } }.to raise_error(StubFactory::TemplateError)
28
+ end
29
+
30
+ it "templates need to be defined with a block" do
31
+ expect { StubFactory.define_template(:test).to raise_error(StubFactory::TemplateError) }
32
+ end
33
+ end
34
+
35
+ describe ".define_helper" do
36
+ it 'defines helper methods - shortcuts #stub_#{helper} that use a specific template (first argument) on a new stub of a given class (second argument)' do
37
+ StubFactory.define_template(:helper) { { test: 13 } }
38
+ StubFactory.define_helper(:helper, :A)
39
+
40
+ stub_helper.should be_an_instance_of A
41
+ stub_helper.test.should == 13
42
+ end
43
+
44
+ it "helpers cannot be defined twice" do
45
+ StubFactory.define_helper(:helper2, :A)
46
+ expect { StubFactory.define_helper(:helper2, :A) }.to raise_error(StubFactory::HelperError)
47
+ end
48
+
49
+ it "helpers can be defined in files - default path is spec/support/helpers" do
50
+ # required_helper is defined in #spec/support/helper_test.rb
51
+ stub_required_helper.should be_an_instance_of A
52
+ end
53
+ end
54
+
55
+ describe "#new_stub" do
56
+ it "returns a new instance" do
57
+ A.new_stub.should be_an_instance_of A
58
+ end
59
+
60
+ it "takes variable hash and turns it to instance variables" do
61
+ o = A.new_stub(vars: { test: 1 })
62
+ o.test.should == 1
63
+ end
64
+
65
+ context "when a default template exists" do
66
+ StubFactory.define_template(:a) do
67
+ { test: 5 }
68
+ end
69
+
70
+ it "instantiates with default values of a template, deriving from class name" do
71
+ A.new_stub.test.should == 5
72
+ end
73
+
74
+ it "overrides template when instantiated with vars hash" do
75
+ o = A.new_stub(vars: { test: 2 })
76
+ o.test.should_not == 1
77
+ o.test.should == 2
78
+ end
79
+
80
+ it "disables template set to nil" do
81
+ o = A.new_stub(template: nil)
82
+ o.test.should be_nil
83
+ end
84
+
85
+ it "templates can be defined in files - their default path is spec/factories" do
86
+ # required_template is defined in #spec/factories/template_test.rb
87
+ A.new_stub(template: :required_template).test.should == 11
88
+ end
89
+ end
90
+
91
+ context "when a custom template exists" do
92
+ StubFactory.define_template(:esse) do
93
+ { test: 12 }
94
+ end
95
+
96
+ it "takes custom template as argument" do
97
+ o = A.new_stub(template: :esse)
98
+ o.test.should == 12
99
+ end
100
+
101
+ it "custom templates can be overridden" do
102
+ o = A.new_stub(template: :esse, vars: { test: 1 })
103
+ o.test.should == 1
104
+ end
105
+ end
106
+
107
+ context "when methods need to be overridden" do
108
+ class A
109
+ def test_method
110
+ 12
111
+ end
112
+ end
113
+
114
+ it "leaves methods intact when not overwritten by methods hash" do
115
+ A.new_stub.test_method.should == 12
116
+ end
117
+
118
+ it "overrides methods with methods hash" do
119
+ o = A.new_stub(methods: { test_method: 1 })
120
+ o.test_method.should == 1
121
+ end
122
+
123
+ it "other instances' methods are not overwritten by methods hash - it happens on a singleton level" do
124
+ a = A.new_stub(methods: { test_method: 1 })
125
+ b = A.new_stub(methods: { test_method: 2 })
126
+ c = A.new_stub
127
+
128
+ a.test_method.should == 1
129
+ b.test_method.should == 2
130
+ c.test_method.should == 12
131
+ end
132
+ end
133
+
134
+ context "how default template lookup works" do
135
+ it "takes class name of self and returns an underscored symobl, namespaces are marked with double underscore" do
136
+ module TestNamespace
137
+ class TestClass; end
138
+ end
139
+
140
+ class_name = TestNamespace::TestClass.new.class.name
141
+ StubFactory.to_underscored_symbol(class_name).should == :test_namespace__test_class
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1 @@
1
+ StubFactory.define_helper(:required_helper, :A)
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'stub_factory/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "blunt_stub_factory"
8
+ spec.version = StubFactory::VERSION
9
+ spec.authors = ["LFDM"]
10
+ spec.email = ["1986gh@gmail.com"]
11
+ spec.description = %q{Simple StubFactory for rspec}
12
+ spec.summary = %q{Simple StubFactory for rspec, that can help with tightly coupled code}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: blunt_stub_factory
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - LFDM
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
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: rspec
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: Simple StubFactory for rspec
56
+ email:
57
+ - 1986gh@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - lib/stub_factory.rb
68
+ - lib/stub_factory/exceptions.rb
69
+ - lib/stub_factory/helpers.rb
70
+ - lib/stub_factory/version.rb
71
+ - spec/factories/template_test.rb
72
+ - spec/lib/stub_factory_spec.rb
73
+ - spec/support/helpers/helper_test.rb
74
+ - stub_factory.gemspec
75
+ homepage: ''
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.0.3
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Simple StubFactory for rspec, that can help with tightly coupled code
99
+ test_files:
100
+ - spec/factories/template_test.rb
101
+ - spec/lib/stub_factory_spec.rb
102
+ - spec/support/helpers/helper_test.rb
103
+ has_rdoc: