machinist 2.0.0.beta2 → 2.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.
- data/.gitignore +6 -5
- data/Gemfile +2 -8
- data/Gemfile.lock +47 -0
- data/README.markdown +228 -18
- data/Rakefile +5 -20
- data/VERSION +1 -1
- data/lib/generators/machinist/install/install_generator.rb +10 -12
- data/lib/generators/machinist/install/templates/machinist.rb.erb +0 -3
- data/lib/machinist.rb +0 -12
- data/lib/machinist/active_record/blueprint.rb +0 -25
- data/lib/machinist/blueprint.rb +1 -1
- data/lib/machinist/lathe.rb +3 -4
- data/lib/machinist/machinable.rb +2 -8
- data/lib/machinist/version.rb +3 -0
- data/machinist.gemspec +20 -71
- data/spec/active_record_spec.rb +9 -36
- data/spec/blueprint_spec.rb +10 -8
- data/spec/exceptions_spec.rb +2 -2
- data/spec/inheritance_spec.rb +6 -6
- data/spec/machinable_spec.rb +6 -6
- data/spec/spec_helper.rb +0 -4
- metadata +103 -30
- data/lib/machinist/configuration.rb +0 -32
- data/lib/machinist/shop.rb +0 -52
- data/lib/machinist/warehouse.rb +0 -36
- data/spec/shop_spec.rb +0 -94
- data/spec/warehouse_spec.rb +0 -24
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
machinist (2.0.0.beta2)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
activemodel (3.0.9)
|
10
|
+
activesupport (= 3.0.9)
|
11
|
+
builder (~> 2.1.2)
|
12
|
+
i18n (~> 0.5.0)
|
13
|
+
activerecord (3.0.9)
|
14
|
+
activemodel (= 3.0.9)
|
15
|
+
activesupport (= 3.0.9)
|
16
|
+
arel (~> 2.0.10)
|
17
|
+
tzinfo (~> 0.3.23)
|
18
|
+
activesupport (3.0.9)
|
19
|
+
arel (2.0.10)
|
20
|
+
builder (2.1.2)
|
21
|
+
diff-lcs (1.1.2)
|
22
|
+
i18n (0.5.0)
|
23
|
+
mysql (2.8.1)
|
24
|
+
rake (0.9.2)
|
25
|
+
rcov (0.9.9)
|
26
|
+
rdoc (3.6.1)
|
27
|
+
rspec (2.6.0)
|
28
|
+
rspec-core (~> 2.6.0)
|
29
|
+
rspec-expectations (~> 2.6.0)
|
30
|
+
rspec-mocks (~> 2.6.0)
|
31
|
+
rspec-core (2.6.4)
|
32
|
+
rspec-expectations (2.6.0)
|
33
|
+
diff-lcs (~> 1.1.2)
|
34
|
+
rspec-mocks (2.6.0)
|
35
|
+
tzinfo (0.3.28)
|
36
|
+
|
37
|
+
PLATFORMS
|
38
|
+
ruby
|
39
|
+
|
40
|
+
DEPENDENCIES
|
41
|
+
activerecord
|
42
|
+
machinist!
|
43
|
+
mysql
|
44
|
+
rake
|
45
|
+
rcov
|
46
|
+
rdoc
|
47
|
+
rspec
|
data/README.markdown
CHANGED
@@ -2,23 +2,36 @@
|
|
2
2
|
|
3
3
|
*Fixtures aren't fun. Machinist is.*
|
4
4
|
|
5
|
-
|
6
|
-
- [What's new in Machinist 2](http://wiki.github.com/notahat/machinist/machinist-2)
|
7
|
-
- [Installation](http://wiki.github.com/notahat/machinist/installation)
|
8
|
-
- [Documentation](http://wiki.github.com/notahat/machinist/getting-started)
|
9
|
-
- [Google group](http://groups.google.com/group/machinist-users)
|
10
|
-
- [Issue tracker](http://github.com/notahat/machinist/issues)
|
5
|
+
Machinist 2 is **still in beta**!
|
11
6
|
|
7
|
+
If you're using Rails 3, you'll want to give Machinist 2 a go, but be aware
|
8
|
+
that the documentation is still patchy.
|
12
9
|
|
13
|
-
|
10
|
+
That said, have a look at [the
|
11
|
+
specs](https://github.com/notahat/machinist/tree/master/spec), starting with
|
12
|
+
[the spec for
|
13
|
+
Machinable](https://github.com/notahat/machinist/blob/master/spec/machinable_spec.rb).
|
14
|
+
No, really, have a look. I wrote this code to be read, and the specs do a
|
15
|
+
pretty clean job of documenting what it all does.
|
14
16
|
|
15
|
-
|
17
|
+
If, on the other hand, you want the tried, tested, and well-documented official
|
18
|
+
release version of Machinist, [then go with Machinist
|
19
|
+
1](http://github.com/notahat/machinist/tree/1.0-maintenance).
|
20
|
+
|
21
|
+
- [Home page](http://github.com/notahat/machinist)
|
22
|
+
- [Google group](http://groups.google.com/group/machinist-users), for support
|
23
|
+
- [Bug tracker](http://github.com/notahat/machinist/issues), for reporting Machinist bugs
|
24
|
+
|
25
|
+
|
26
|
+
## Introduction
|
27
|
+
|
28
|
+
Machinist makes it easy to create objects for use in tests. It generates data
|
16
29
|
for the attributes you don't care about, and constructs any necessary
|
17
|
-
associated objects, leaving you to specify only the
|
18
|
-
|
30
|
+
associated objects, leaving you to specify only the fields you care about in
|
31
|
+
your test. For example:
|
19
32
|
|
20
|
-
describe Comment do
|
21
|
-
it "
|
33
|
+
describe Comment, "without_spam scope" do
|
34
|
+
it "doesn't include spam" do
|
22
35
|
# This will make a Comment, a Post, and a User (the author of the
|
23
36
|
# Post), generate values for all their attributes, and save them:
|
24
37
|
spam = Comment.make!(:spam => true)
|
@@ -34,7 +47,7 @@ You tell Machinist how to do this with blueprints:
|
|
34
47
|
User.blueprint do
|
35
48
|
username { "user#{sn}" } # Each user gets a unique serial number.
|
36
49
|
end
|
37
|
-
|
50
|
+
|
38
51
|
Post.blueprint do
|
39
52
|
author
|
40
53
|
title { "Post #{sn}" }
|
@@ -43,13 +56,208 @@ You tell Machinist how to do this with blueprints:
|
|
43
56
|
|
44
57
|
Comment.blueprint do
|
45
58
|
post
|
46
|
-
email { "commenter
|
59
|
+
email { "commenter#{sn}@example.com" }
|
47
60
|
body { "Lorem ipsum..." }
|
48
61
|
end
|
49
62
|
|
50
|
-
|
51
|
-
|
52
|
-
|
63
|
+
|
64
|
+
## Installation
|
65
|
+
|
66
|
+
### Upgrading from Machinist 1
|
67
|
+
|
68
|
+
See [the wiki](http://wiki.github.com/notahat/machinist/machinist-2).
|
69
|
+
|
70
|
+
### Rails 3
|
71
|
+
|
72
|
+
In your app's `Gemfile`, in the `group :test` section, add:
|
73
|
+
|
74
|
+
gem 'machinist', '>= 2.0.0.beta2'
|
75
|
+
|
76
|
+
Then run:
|
77
|
+
|
78
|
+
bundle
|
79
|
+
rails generate machinist:install
|
80
|
+
|
81
|
+
If you want Machinist to automatically add a blueprint to your blueprints file
|
82
|
+
whenever you generate a model, add the following to your `config/application.rb`
|
83
|
+
inside the Application class:
|
84
|
+
|
85
|
+
config.generators do |g|
|
86
|
+
g.fixture_replacement :machinist
|
87
|
+
end
|
88
|
+
|
89
|
+
### Rails 2
|
90
|
+
|
91
|
+
See [the wiki](http://wiki.github.com/notahat/machinist/rails-2).
|
92
|
+
|
93
|
+
|
94
|
+
## Usage
|
95
|
+
|
96
|
+
### Blueprints
|
97
|
+
|
98
|
+
A blueprint describes how to generate an object. The blueprint takes care of
|
99
|
+
providing attributes that your test doesn't care about, leaving you to focus on
|
100
|
+
just the attributes that are important for the test.
|
101
|
+
|
102
|
+
A simple blueprint might look like this:
|
103
|
+
|
104
|
+
Post.blueprint do
|
105
|
+
title { "A Post" }
|
106
|
+
body { "Lorem ipsum..." }
|
107
|
+
end
|
108
|
+
|
109
|
+
You can then construct a Post from this blueprint with:
|
110
|
+
|
111
|
+
Post.make!
|
112
|
+
|
113
|
+
When you call `make!`, Machinist calls `Post.new`, then runs through the
|
114
|
+
attributes in your blueprint, calling the block for each attribute to generate
|
115
|
+
a value. It then saves and reloads the Post. (It throws an exception if the
|
116
|
+
Post can't be saved.)
|
117
|
+
|
118
|
+
You can override values defined in the blueprint by passing a hash to make:
|
119
|
+
|
120
|
+
Post.make!(:title => "A Specific Title")
|
121
|
+
|
122
|
+
If you want to generate an object without saving it to the database, replace
|
123
|
+
`make!` with `make`.
|
124
|
+
|
125
|
+
|
126
|
+
### Unique Attributes
|
127
|
+
|
128
|
+
For attributes that need to be unique, you can call the `sn` method from
|
129
|
+
within the attribute block to get a unique serial number for the object.
|
130
|
+
|
131
|
+
User.blueprint do
|
132
|
+
username { "user-#{sn}" }
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
### Associations
|
137
|
+
|
138
|
+
If your object needs associated objects, you can generate them like this:
|
139
|
+
|
140
|
+
Comment.blueprint do
|
141
|
+
post { Post.make }
|
142
|
+
end
|
143
|
+
|
144
|
+
Calling `Comment.make!` will construct a Comment and its associated Post, and
|
145
|
+
save both.
|
146
|
+
|
147
|
+
Machinist is smart enough to look at the association and work out what sort of
|
148
|
+
object it needs to create, so you can shorten the above blueprint to:
|
149
|
+
|
150
|
+
Comment.blueprint do
|
151
|
+
post
|
152
|
+
end
|
153
|
+
|
154
|
+
If you want to override the value for post when constructing the comment, you
|
155
|
+
can do this:
|
156
|
+
|
157
|
+
post = Post.make(:title => "A particular title)
|
158
|
+
comment = Comment.make(:post => post)
|
159
|
+
|
160
|
+
|
161
|
+
For `has_many` and `has_and_belongs_to_many` associations, you can create
|
162
|
+
multiple associated objects like this:
|
163
|
+
|
164
|
+
Post.blueprint do
|
165
|
+
comments(3) # Makes 3 comments.
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
### Named Blueprints
|
170
|
+
|
171
|
+
Named blueprints let you define variations on an object. For example, suppose
|
172
|
+
some of your Users are administrators:
|
173
|
+
|
174
|
+
User.blueprint do
|
175
|
+
name { "User #{sn}" }
|
176
|
+
email { "user-#{sn}@example.com" }
|
177
|
+
end
|
178
|
+
|
179
|
+
User.blueprint(:admin) do
|
180
|
+
name { "Admin User #{sn}" }
|
181
|
+
admin { true }
|
182
|
+
end
|
183
|
+
|
184
|
+
Calling:
|
185
|
+
|
186
|
+
User.make!(:admin)
|
187
|
+
|
188
|
+
will use the `:admin` blueprint.
|
189
|
+
|
190
|
+
Named blueprints call the default blueprint to set any attributes not
|
191
|
+
specifically provided, so in this example the `email` attribute will still be
|
192
|
+
generated even for an admin user.
|
193
|
+
|
194
|
+
You must define a default blueprint for any class that has a named blueprint,
|
195
|
+
even if the default blueprint is empty.
|
196
|
+
|
197
|
+
|
198
|
+
### Blueprints on Plain Old Ruby Objects
|
199
|
+
|
200
|
+
Machinist also works with plain old Ruby objects. Let's say you have a class like:
|
201
|
+
|
202
|
+
class Post
|
203
|
+
extend Machinist::Machinable
|
204
|
+
|
205
|
+
attr_accessor :title
|
206
|
+
attr_accessor :body
|
207
|
+
end
|
208
|
+
|
209
|
+
You can blueprint the Post class just like anything else:
|
210
|
+
|
211
|
+
Post.blueprint do
|
212
|
+
title { "A title!" }
|
213
|
+
body { "A body!" }
|
214
|
+
end
|
215
|
+
|
216
|
+
And `Post.make` will construct a new Post.
|
217
|
+
|
218
|
+
|
219
|
+
### Other Tricks
|
220
|
+
|
221
|
+
You can refer to already assigned attributes when constructing a new attribute:
|
222
|
+
|
223
|
+
Post.blueprint do
|
224
|
+
author { "Author #{sn}" }
|
225
|
+
body { "Post by #{object.author}" }
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
## Compatibility
|
230
|
+
|
231
|
+
I've tested this with:
|
232
|
+
|
233
|
+
Ruby versions: 1.8.7, 1.9.2
|
234
|
+
Rails versions: 2.3, 3.0
|
235
|
+
|
236
|
+
It may well be happy with other versions too, but I'm not promising anything.
|
237
|
+
Compatibility patches are welcome.
|
238
|
+
|
239
|
+
|
240
|
+
## Developing
|
241
|
+
|
242
|
+
The Machinist specs and source code were written to be read, and I'm pretty
|
243
|
+
happy with them. Don't be afraid to have a look under the hood!
|
244
|
+
|
245
|
+
If you want to submit a patch:
|
246
|
+
|
247
|
+
- Fork the project.
|
248
|
+
- Make your feature addition or bug fix.
|
249
|
+
- Add tests for it. This is important so I don't break it in a
|
250
|
+
future version unintentionally.
|
251
|
+
- Commit, do not mess with rakefile, version, or history.
|
252
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
253
|
+
- Send me a pull request. Bonus points for topic branches.
|
254
|
+
|
255
|
+
|
256
|
+
## Status
|
257
|
+
|
258
|
+
In active use in a number of large Rails 2 apps.
|
259
|
+
|
260
|
+
Development has been sporadic, but is picking up again.
|
53
261
|
|
54
262
|
|
55
263
|
## Contributors
|
@@ -67,11 +275,13 @@ Other contributors include:
|
|
67
275
|
[Jeremy Grant](http://github.com/jeremygrant),
|
68
276
|
[Jon Guymon](http://github.com/gnarg),
|
69
277
|
[James Healy](http://github.com/yob),
|
278
|
+
[Ben Hoskings](http://github.com/benhoskings),
|
70
279
|
[Evan David Light](http://github.com/elight),
|
71
280
|
[Chris Lloyd](http://github.com/chrislloyd),
|
72
281
|
[Adam Meehan](http://github.com/adzap),
|
73
282
|
[Kyle Neath](http://github.com/kneath),
|
74
283
|
[Lawrence Pit](http://github.com/lawrencepit),
|
284
|
+
[Xavier Shay](http://github.com/xaviershay),
|
75
285
|
[T.J. Sheehy](http://github.com/tjsheehy),
|
76
286
|
[Roland Swingler](http://github.com/knaveofdiamonds),
|
77
287
|
[Gareth Townsend](http://github.com/quamen),
|
@@ -82,4 +292,4 @@ Thanks to Thoughtbot's [Factory
|
|
82
292
|
Girl](http://github.com/thoughtbot/factory_girl/tree/master). Machinist was
|
83
293
|
written because I loved the idea behind Factory Girl, but I thought the
|
84
294
|
philosophy wasn't quite right, and I hated the syntax.
|
85
|
-
|
295
|
+
|
data/Rakefile
CHANGED
@@ -1,25 +1,10 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'bundler'
|
3
|
-
Bundler.
|
3
|
+
Bundler::GemHelper.install_tasks
|
4
4
|
|
5
5
|
require 'rake'
|
6
6
|
require 'rspec/core/rake_task'
|
7
|
-
require '
|
8
|
-
|
9
|
-
begin
|
10
|
-
require 'jeweler'
|
11
|
-
Jeweler::Tasks.new do |gem|
|
12
|
-
gem.name = "machinist"
|
13
|
-
gem.summary = "Fixtures aren't fun. Machinist is."
|
14
|
-
gem.email = "pete@notahat.com"
|
15
|
-
gem.homepage = "http://github.com/notahat/machinist"
|
16
|
-
gem.authors = ["Pete Yandell"]
|
17
|
-
gem.has_rdoc = false
|
18
|
-
end
|
19
|
-
Jeweler::GemcutterTasks.new
|
20
|
-
rescue LoadError
|
21
|
-
puts "Jeweler not available. Install it with: gem install jeweler"
|
22
|
-
end
|
7
|
+
require 'rdoc/task'
|
23
8
|
|
24
9
|
|
25
10
|
RSpec::Core::RakeTask.new
|
@@ -30,13 +15,13 @@ RSpec::Core::RakeTask.new(:rcov) do |spec|
|
|
30
15
|
end
|
31
16
|
|
32
17
|
desc 'Run the specs.'
|
33
|
-
task :default => :
|
18
|
+
task :default => :rcov
|
34
19
|
|
35
20
|
|
36
|
-
|
21
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
37
22
|
rdoc.rdoc_dir = 'doc'
|
38
23
|
rdoc.title = 'Machinist'
|
39
|
-
rdoc.options << '--line-numbers'
|
24
|
+
rdoc.options << '--line-numbers'
|
40
25
|
rdoc.rdoc_files.include('lib')
|
41
26
|
end
|
42
27
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0
|
1
|
+
2.0
|
@@ -15,24 +15,15 @@ module Machinist
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def test_helper
|
18
|
-
if
|
19
|
-
inject_into_file("spec/spec_helper.rb", :after => "Rspec.configure do |config|\n") do
|
20
|
-
" # Reset the Machinist cache before each spec.\n" +
|
21
|
-
" config.before(:each) { Machinist.reset_before_test }\n\n"
|
22
|
-
end
|
23
|
-
else
|
18
|
+
if test_unit?
|
24
19
|
inject_into_file("test/test_helper.rb", :after => "require 'rails/test_help'\n") do
|
25
20
|
"require File.expand_path(File.dirname(__FILE__) + '/blueprints')\n"
|
26
21
|
end
|
27
|
-
inject_into_class("test/test_helper.rb", ActiveSupport::TestCase) do
|
28
|
-
" # Reset the Machinist cache before each test.\n" +
|
29
|
-
" setup { Machinist.reset_before_test }\n\n"
|
30
|
-
end
|
31
22
|
end
|
32
23
|
end
|
33
|
-
|
24
|
+
|
34
25
|
def cucumber_support
|
35
|
-
if
|
26
|
+
if cucumber?
|
36
27
|
template "machinist.rb.erb", "features/support/machinist.rb"
|
37
28
|
end
|
38
29
|
end
|
@@ -43,6 +34,13 @@ module Machinist
|
|
43
34
|
options[:test_framework].to_sym == :rspec
|
44
35
|
end
|
45
36
|
|
37
|
+
def test_unit?
|
38
|
+
options[:test_framework].to_sym == :test_unit
|
39
|
+
end
|
40
|
+
|
41
|
+
def cucumber?
|
42
|
+
options[:cucumber]
|
43
|
+
end
|
46
44
|
end
|
47
45
|
end
|
48
46
|
end
|