blunt_stub_factory 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.
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: