carpenter 0.1.0

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.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format Fuubar
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in carpenter.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Alexander Kern
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,143 @@
1
+ Carpenter
2
+ =========
3
+
4
+ Description
5
+ -----------
6
+
7
+ Carpenter provides syntax sugar for using the [Test Data Builder][tdb-pattern]
8
+ pattern in Ruby testing frameworks. It complements [FactoryGirl][factory-girl]
9
+ and mock objects.
10
+
11
+ [tdb-pattern]: http://c2.com/cgi/wiki?TestDataBuilder
12
+ [factory-girl]: https://github.com/thoughtbot/factory_girl
13
+
14
+ Why?
15
+ ----
16
+
17
+ Sometimes, instantiating a test object is really ugly. For example, [Value
18
+ Objects][value-objects] will very often have long declarations.
19
+
20
+ Webbed::Method.new("GET", :safe => true, :idempotent => true, :allows_request_entity => false, :allows_response_entity => true)
21
+
22
+ Wouldn't it be nice if we could put this ugliness in a separate file? Carpenter
23
+ allows you to define "builders" which can be reused in different test files.
24
+
25
+ # in spec/builders/method.rb
26
+ Carpenter.define do
27
+ builder :get_method do
28
+ Webbed::Method.new("GET", :safe => true, :idempotent => true, :allows_request_entity => false, :allows_response_entity => true)
29
+ end
30
+ end
31
+
32
+ # in spec/webbed/method_spec.rb
33
+ Carpenter(:get_method) # => a new Webbed::Method
34
+
35
+ This pattern looks similar to FactoryGirl; however, Carpenter is *not* a
36
+ substitute for FactoryGirl and its alternatives. FactoryGirl was designed to
37
+ generate ActiveRecord models. Carpenter was designed to generate any kind of
38
+ Ruby object. Prefer FactoryGirl over Carpenter whenever possible.
39
+
40
+ Carpenter is also *not* a substitute for mock objects. Build objects using Carpenter
41
+ if they are the object currently under test. Use mocks or stubs if you are not
42
+ testing the object, but instead testing one of its associates.
43
+
44
+ [value-objects]: http://c2.com/cgi/wiki?ValueObject
45
+
46
+ Installation
47
+ ------------
48
+
49
+ First, install the gem.
50
+
51
+ gem install carpenter
52
+
53
+ For RSpec users, add the following to your `spec_helper.rb`:
54
+
55
+ require "carpenter"
56
+
57
+ Carpenter::BuilderLoader.load_all
58
+ RSpec.configure do |config|
59
+ config.include Carpenter::BuildDSL
60
+ end
61
+
62
+ For `Test::Unit` users, add the following to your `test_helper.rb`:
63
+
64
+ require "carpenter"
65
+
66
+ Carpenter::BuilderLoader.load_all
67
+ class Test::Unit::TestCase
68
+ include Carpenter::BuildDSL
69
+ end
70
+
71
+ Other testing frameworks should work with Carpenter if they support including a
72
+ Ruby module. All you have to do is call `Carpenter::BuilderLoader.load_all` and include
73
+ `Carpenter::BuildDSL` into the framework. Please submit a GitHub if there are
74
+ any issues with some frameworks.
75
+
76
+ Usage
77
+ -----
78
+
79
+ By default, Carpenter loads all the files from `test/builders` and
80
+ `spec/builders`. I'd suggest making a builder file for each class that you
81
+ build. Each file should be wrapped in a `Carpenter.define` block like so:
82
+
83
+ # in spec/builders/my_object.rb
84
+ Carpenter.define do
85
+ # Your builders go here.
86
+ end
87
+
88
+ You can define builders using the `#builder` method. It takes a symbol as the
89
+ name of the builder and a block as the actual builder. Here's a really simple
90
+ builder that will make a new instance of `MyObject` with some arguments:
91
+
92
+ # in spec/builders/my_object.rb
93
+ Carpenter.define do
94
+ builder :my_object do
95
+ MyObject.new(:foo, :bar)
96
+ end
97
+ end
98
+
99
+ Builders also can take an optional hash of options to let you configure the
100
+ test data a bit.
101
+
102
+ # in spec/builders/my_object.rb
103
+ Carpenter.define do
104
+ builder :my_object do |options|
105
+ MyObject.new(options[:foo], options[:bar])
106
+ end
107
+ end
108
+
109
+ Builders can be named whatever you want and return whatever you want. They're
110
+ essentially methods. So, this is just as valid as the last example, [albeit a
111
+ bit confusing][confusing]:
112
+
113
+ # in spec/builders/abraham_lincoln.rb
114
+ Carpenter.define do
115
+ builder :abraham_lincoln_quote do
116
+ "The trouble with quotes on the Internet is that you can never know if they are genuine."
117
+ end
118
+ end
119
+
120
+ To use your builders in your tests, just use the `#Carpenter` method with the
121
+ name of the builder and (optionally) a hash of options.
122
+
123
+ # in spec/my_object_spec.rb
124
+ describe MyObject do
125
+ it "can be created" do
126
+ Carpenter(:my_object).should_not be_nil
127
+ end
128
+ end
129
+
130
+ You can add more builder load directories by adding them to the builder
131
+ loader's builder paths before loading the builders.
132
+
133
+ Carpenter::BuilderLoader.builder_paths << "spec/custom_builder_dir"
134
+ Carpenter::BuilderLoader.load_all
135
+
136
+ [confusing]: http://www.comedyshack.co.za/wp-content/uploads/2011/02/trouble-with-quotes-on-internet.png
137
+
138
+ License
139
+ -------
140
+
141
+ Released under the MIT License. See the [LICENSE][license] file for details.
142
+
143
+ [license]: https://github.com/CapnKernul/carpenter/blob/develop/LICENSE
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "carpenter/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "carpenter"
7
+ s.version = Carpenter::VERSION
8
+ s.authors = ["Alexander Kern"]
9
+ s.email = ["alex@kernul.com"]
10
+ s.homepage = "https://github.com/CapnKernul/carpenter"
11
+ s.summary = %q{The Test Data Builder pattern for Ruby.}
12
+ s.description = %q{Tiny gem for specifying test data for arbitrary objects in Ruby.}
13
+
14
+ s.rubyforge_project = "carpenter"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "rspec", "~> 2.7"
22
+ s.add_development_dependency "rake", "~> 0.9"
23
+ s.add_development_dependency "fuubar", "0.0.6"
24
+ end
@@ -0,0 +1,29 @@
1
+ require "carpenter/version"
2
+
3
+ module Carpenter
4
+ def self.builders
5
+ @builders ||= {}
6
+ end
7
+
8
+ def self.define_builder(name, &builder)
9
+ builders[name] = builder
10
+ end
11
+
12
+ def self.clear
13
+ @builders = {}
14
+ end
15
+
16
+ def self.build(name, options = {})
17
+ builder = builders[name]
18
+ builder.call(options)
19
+ end
20
+
21
+ def self.define(&block)
22
+ dsl = Carpenter::DefineDSL.new
23
+ dsl.instance_eval(&block)
24
+ end
25
+ end
26
+
27
+ require "carpenter/build_dsl"
28
+ require "carpenter/define_dsl"
29
+ require "carpenter/builder_loader"
@@ -0,0 +1,7 @@
1
+ module Carpenter
2
+ module BuildDSL
3
+ def Carpenter(*args)
4
+ Carpenter.build(*args)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ module Carpenter
2
+ module BuilderLoader
3
+ class << self
4
+ attr_accessor :builder_paths
5
+ end
6
+
7
+ self.builder_paths = %w{test/builders spec/builders}
8
+
9
+ def self.builder_absolute_paths
10
+ builder_paths.map { |p| File.expand_path(p) }
11
+ end
12
+
13
+ def self.load_all
14
+ builder_absolute_paths.each do |p|
15
+ load_path(p) if File.directory?(p)
16
+ end
17
+ end
18
+
19
+ def self.load_path(path)
20
+ Dir[File.join(path, "**", "*.rb")].each do |f|
21
+ load f
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ module Carpenter
2
+ class DefineDSL
3
+ def builder(*args, &builder)
4
+ Carpenter.define_builder(*args, &builder)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Carpenter
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,27 @@
1
+ require "spec_helper"
2
+
3
+ describe Carpenter::BuildDSL do
4
+ let(:builder) { lambda {} }
5
+ let(:dsl) do
6
+ klass = Class.new
7
+ klass.send(:include, Carpenter::BuildDSL)
8
+ klass.new
9
+ end
10
+
11
+ before do
12
+ Carpenter.define_builder(:test, &builder)
13
+ end
14
+
15
+ describe "#Carpenter" do
16
+ it "calls the builder" do
17
+ builder.should_receive(:call)
18
+ dsl.Carpenter(:test)
19
+ end
20
+
21
+ it "returns the built object" do
22
+ builder.stub(:call).and_return("I'm practically asleep.")
23
+ result = dsl.Carpenter(:test)
24
+ result.should == "I'm practically asleep."
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,45 @@
1
+ require "spec_helper"
2
+
3
+ describe Carpenter::BuilderLoader do
4
+ describe ".builder_paths" do
5
+ it "has 3 paths by default" do
6
+ Carpenter::BuilderLoader.should have(2).builder_paths
7
+ end
8
+ end
9
+
10
+ describe ".builder_absolute_paths" do
11
+ it "has the absolute paths of the builder paths" do
12
+ Carpenter::BuilderLoader.should have(2).builder_absolute_paths
13
+ end
14
+ end
15
+
16
+ describe ".load_all" do
17
+ before do
18
+ Carpenter::BuilderLoader.builder_paths << "spec/fixtures/builders"
19
+ end
20
+
21
+ it "loads each builder in each directory" do
22
+ Carpenter::BuilderLoader.load_all
23
+ A_INCLUDED.should be_true
24
+ B_INCLUDED.should be_true
25
+ end
26
+
27
+ after do
28
+ Object.send(:remove_const, :A_INCLUDED)
29
+ Object.send(:remove_const, :B_INCLUDED)
30
+ end
31
+ end
32
+
33
+ describe ".load_path" do
34
+ it "loads each builder in the directory" do
35
+ Carpenter::BuilderLoader.load_path("spec/fixtures/builders")
36
+ A_INCLUDED.should be_true
37
+ B_INCLUDED.should be_true
38
+ end
39
+
40
+ after do
41
+ Object.send(:remove_const, :A_INCLUDED)
42
+ Object.send(:remove_const, :B_INCLUDED)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,16 @@
1
+ require "spec_helper"
2
+
3
+ describe Carpenter::DefineDSL do
4
+ let(:dsl) { Carpenter::DefineDSL.new }
5
+
6
+ describe "#builder" do
7
+ it "creates a builder" do
8
+ dsl.builder(:test) do
9
+ :foo
10
+ end
11
+
12
+ result = Carpenter.build(:test)
13
+ result.should == :foo
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,59 @@
1
+ require "spec_helper"
2
+
3
+ describe Carpenter do
4
+ let(:define_block) { lambda {} }
5
+ let(:builder) { lambda {} }
6
+
7
+ before do
8
+ Carpenter.define_builder(:test, &builder)
9
+ end
10
+
11
+ describe "#define" do
12
+ it "exeutes the block in a new DefineDSL object" do
13
+ Carpenter.define do
14
+ builder :foo do
15
+ :bar
16
+ end
17
+ end
18
+
19
+ result = Carpenter.build(:foo)
20
+ result.should == :bar
21
+ end
22
+ end
23
+
24
+ describe "#define_builder" do
25
+ it "defines a new builder" do
26
+ Carpenter.builders[:test].should == builder
27
+ end
28
+ end
29
+
30
+ describe "#clear" do
31
+ it "removes all builders" do
32
+ Carpenter.clear
33
+ Carpenter.should have(0).builders
34
+ end
35
+ end
36
+
37
+ describe "#build" do
38
+ context "when provided options" do
39
+ it "calls the builder with the options" do
40
+ options = double("options")
41
+ builder.should_receive(:call).with(options)
42
+ Carpenter.build(:test, options)
43
+ end
44
+ end
45
+
46
+ context "when not provided options" do
47
+ it "calls the builder with an empty options hash" do
48
+ builder.should_receive(:call).with({})
49
+ Carpenter.build(:test)
50
+ end
51
+ end
52
+
53
+ it "returns the result of the builder" do
54
+ builder.stub(:call).and_return("I'm tired.")
55
+ result = Carpenter.build(:test)
56
+ result.should == "I'm tired."
57
+ end
58
+ end
59
+ end
@@ -0,0 +1 @@
1
+ A_INCLUDED = true
@@ -0,0 +1 @@
1
+ B_INCLUDED = true
@@ -0,0 +1,11 @@
1
+ require "bundler/setup"
2
+ require "rspec/autorun"
3
+ require "carpenter"
4
+
5
+ Dir["spec/support/**/*.rb"].each { |f| require File.expand_path(f) }
6
+
7
+ RSpec.configure do |config|
8
+ config.after do
9
+ Carpenter.clear
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: carpenter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Alexander Kern
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-12-23 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70355091736740 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.7'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70355091736740
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &70355091726220 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '0.9'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70355091726220
36
+ - !ruby/object:Gem::Dependency
37
+ name: fuubar
38
+ requirement: &70355091725060 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - =
42
+ - !ruby/object:Gem::Version
43
+ version: 0.0.6
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70355091725060
47
+ description: Tiny gem for specifying test data for arbitrary objects in Ruby.
48
+ email:
49
+ - alex@kernul.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - .rspec
56
+ - Gemfile
57
+ - LICENSE
58
+ - README.md
59
+ - Rakefile
60
+ - carpenter.gemspec
61
+ - lib/carpenter.rb
62
+ - lib/carpenter/build_dsl.rb
63
+ - lib/carpenter/builder_loader.rb
64
+ - lib/carpenter/define_dsl.rb
65
+ - lib/carpenter/version.rb
66
+ - spec/carpenter/build_dsl_spec.rb
67
+ - spec/carpenter/builder_loader_spec.rb
68
+ - spec/carpenter/define_dsl_spec.rb
69
+ - spec/carpenter_spec.rb
70
+ - spec/fixtures/builders/a.rb
71
+ - spec/fixtures/builders/b.rb
72
+ - spec/spec_helper.rb
73
+ homepage: https://github.com/CapnKernul/carpenter
74
+ licenses: []
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project: carpenter
93
+ rubygems_version: 1.8.10
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: The Test Data Builder pattern for Ruby.
97
+ test_files:
98
+ - spec/carpenter/build_dsl_spec.rb
99
+ - spec/carpenter/builder_loader_spec.rb
100
+ - spec/carpenter/define_dsl_spec.rb
101
+ - spec/carpenter_spec.rb
102
+ - spec/fixtures/builders/a.rb
103
+ - spec/fixtures/builders/b.rb
104
+ - spec/spec_helper.rb
105
+ has_rdoc: