factory_grabber 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +14 -0
- data/Manifest +14 -0
- data/README.md +159 -0
- data/Rakefile +14 -0
- data/factory_grabber.gemspec +30 -0
- data/init.rb +1 -0
- data/lib/dbfile +0 -0
- data/lib/factory_grabber.rb +176 -0
- data/lib/spec/database_setup.rb +9 -0
- data/lib/spec/dbfile +0 -0
- data/lib/spec/factories.rb +9 -0
- data/lib/spec/grab_spec.rb +170 -0
- data/lib/spec/performance_test.rb +22 -0
- data/lib/spec/spec_helper.rb +7 -0
- data/lib/spec/user.rb +4 -0
- metadata +84 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
Version 1.0.3
|
3
|
+
- Added support for virtual attributes
|
4
|
+
|
5
|
+
Version 1.0.1
|
6
|
+
- Re-wrote README as Markdown
|
7
|
+
|
8
|
+
Version 1.0.1 released Tuesday 15th September [Gavin Morrice]
|
9
|
+
- Removed the NumberMethods. Instead of dynamically creating a method for each number, ghost methods are 'created' using method_missing.
|
10
|
+
- Updated README
|
11
|
+
- Updated Rdoc
|
12
|
+
- Added support for 'a' and 'an': Grab.an_author
|
13
|
+
|
14
|
+
Version 1.0.0 released Sunday 13th September [Gavin Morrice]
|
data/Manifest
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
Manifest
|
3
|
+
README.md
|
4
|
+
Rakefile
|
5
|
+
init.rb
|
6
|
+
lib/dbfile
|
7
|
+
lib/factory_grabber.rb
|
8
|
+
lib/spec/database_setup.rb
|
9
|
+
lib/spec/dbfile
|
10
|
+
lib/spec/factories.rb
|
11
|
+
lib/spec/grab_spec.rb
|
12
|
+
lib/spec/performance_test.rb
|
13
|
+
lib/spec/spec_helper.rb
|
14
|
+
lib/spec/user.rb
|
data/README.md
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
Factory Grabber
|
2
|
+
==============
|
3
|
+
|
4
|
+
Factory grabber speeds up your tests by grabbing the nearest appropriate database records to suit your needs.
|
5
|
+
|
6
|
+
The idea is simple: most of the time, when using factories, you don't really care about the specific attributes, you just need a database record to play with. factory_grabber will _'grab'_ a matching record from the database if available or create any extra records if required. Less inserts to the database means faster tests.
|
7
|
+
|
8
|
+
At the moment, only "factory_girl":http://github.com/thoughtbot/factory_girl by thoughtbot is supported. If you'd like to see more factories supported please let me know (gavin@handyrailstips.com)
|
9
|
+
|
10
|
+
To install:
|
11
|
+
===========
|
12
|
+
|
13
|
+
|
14
|
+
As a gem:
|
15
|
+
---------
|
16
|
+
|
17
|
+
sudo gem install git://github.com/GavinM/factory_grabber.git
|
18
|
+
|
19
|
+
# environment.rb
|
20
|
+
config.gem "thoughtbot-factory_girl", :lib => "factory_girl"
|
21
|
+
config.gem "factory_grbber", :version => ">=1.0.2", :lib => false
|
22
|
+
|
23
|
+
As a plugin:
|
24
|
+
------------
|
25
|
+
script/plugin install git://github.com/GavinM/factory_grabber.git
|
26
|
+
|
27
|
+
|
28
|
+
Important:
|
29
|
+
----------
|
30
|
+
|
31
|
+
To benefit from this gem, set use_transactional_fixtures=() to false in *spec_helper.rb*
|
32
|
+
|
33
|
+
Spec::Runner.configure do |config|
|
34
|
+
config.use_transactional_fixtures = false
|
35
|
+
config.use_instantiated_fixtures = false
|
36
|
+
config.fixture_path = RAILS_ROOT + '/spec/fixtures/'
|
37
|
+
end
|
38
|
+
|
39
|
+
Example Usage
|
40
|
+
=============
|
41
|
+
|
42
|
+
First, add the following line to *spec_helper.rb* or *test_helper.rb*:
|
43
|
+
|
44
|
+
require "factory_grabber"
|
45
|
+
|
46
|
+
Then, in your tests/specs:
|
47
|
+
|
48
|
+
# to grab 1 comment:
|
49
|
+
@comment = Grab.a_comment
|
50
|
+
|
51
|
+
# to grab 1 article:
|
52
|
+
@article = Grab.an_article
|
53
|
+
|
54
|
+
#to grab 4 users named "John Smith":
|
55
|
+
@users = Grab.four_users(:first_name => "John", :last_name => "Smith")
|
56
|
+
|
57
|
+
#to grab 73 users with standard factory attributes:
|
58
|
+
@users = Grab.seventy_three_users
|
59
|
+
|
60
|
+
Practical examples:
|
61
|
+
===================
|
62
|
+
|
63
|
+
In a controller spec...
|
64
|
+
describe "GET /posts/1" do
|
65
|
+
|
66
|
+
integrate_views
|
67
|
+
|
68
|
+
before do
|
69
|
+
# will create a record with these attributes if required, if not it will find the existing record
|
70
|
+
@post = Grab.one_post :title => "This is my first post", :body => "This is the post body"
|
71
|
+
end
|
72
|
+
|
73
|
+
def do_get
|
74
|
+
get :show, :id => @post
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should show the post title" do
|
78
|
+
do_get
|
79
|
+
response.should include_text(/This is my first post/)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should show the post body" do
|
83
|
+
do_get
|
84
|
+
response.should include_text(/This is the post body/)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
describe "GET /posts?page=1" do
|
91
|
+
|
92
|
+
# testing pagination
|
93
|
+
|
94
|
+
integrate_views
|
95
|
+
|
96
|
+
before do
|
97
|
+
# ensures there are at least eleven Post records
|
98
|
+
# if there are less than eleven, new posts are created
|
99
|
+
# if there are eleven or more no posts are created
|
100
|
+
Grab.eleven_posts
|
101
|
+
end
|
102
|
+
|
103
|
+
def do_get
|
104
|
+
get :index, :page => 1
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should find the latest 10 posts" do
|
108
|
+
do_get
|
109
|
+
assigns[:posts].should == Post.find(:all, :order => "created_at DESC", :limit => 10)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
At the moment, all numbers between one and ninety_nine are supported. The general syntax for Grab methods is:
|
115
|
+
|
116
|
+
Grab.[number_in_words]_[factory_name]
|
117
|
+
|
118
|
+
Performance gains
|
119
|
+
==================
|
120
|
+
|
121
|
+
Here's a quick example of the possible performance gains:
|
122
|
+
<pre>
|
123
|
+
Rehearsal --------------------------------------------------------------
|
124
|
+
Create 50 new factories 0.130000 0.200000 0.330000 ( 6.785332)
|
125
|
+
Grab 50 separate factories 0.320000 0.020000 0.340000 ( 0.332814)
|
126
|
+
Grab 50 factories at once 0.010000 0.000000 0.010000 ( 0.012414)
|
127
|
+
----------------------------------------------------- total: 0.680000sec
|
128
|
+
|
129
|
+
user system total real
|
130
|
+
Create 50 new factories 0.100000 0.200000 0.300000 ( 6.354282)
|
131
|
+
Grab 50 separate factories 0.300000 0.000000 0.300000 ( 0.310373)
|
132
|
+
Grab 50 factories at once 0.020000 0.000000 0.020000 ( 0.011400)
|
133
|
+
</pre>
|
134
|
+
|
135
|
+
(These results can be produced for your own environment by running the file "performance_test.rb" in factory_grabber/lib/spec/performance_test.rb)
|
136
|
+
|
137
|
+
Known Issues
|
138
|
+
============
|
139
|
+
|
140
|
+
At the moment, existing factories are found calling the model name. If your factory names do not match the name of the models then new factories will be created each time.
|
141
|
+
eg.
|
142
|
+
|
143
|
+
Factory(:admin_user, :class => :user) do |f|
|
144
|
+
f.username("admin_user")
|
145
|
+
f.admin(true)
|
146
|
+
# ... etc ...
|
147
|
+
end
|
148
|
+
|
149
|
+
Grab.an_admin_user # => will not find records from the database.
|
150
|
+
|
151
|
+
Feedback
|
152
|
+
========
|
153
|
+
|
154
|
+
This project is still an infant - if the Ruby community find it useful I plan on adding a lot more. Please send any ideas/feedback to gavin@handyrailstips.com
|
155
|
+
|
156
|
+
|
157
|
+
Free to upload, edit, share, fork etc.<br />
|
158
|
+
[Gavin Morrice](http://gavinmorrice.com)<br />
|
159
|
+
[www.handyrailstips.com](:http://handyrailstips.com/tips/20)
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake"
|
3
|
+
require "echoe"
|
4
|
+
|
5
|
+
Echoe.new("factory_grabber", "1.0.3") do |p|
|
6
|
+
p.description = "Grab or create factories for faster Functional/Integration testing"
|
7
|
+
p.url = "http://github.com/gavinM/factory_grabber"
|
8
|
+
p.author = "Gavin Morrice"
|
9
|
+
p.email = "gavin@handyrailstips.com"
|
10
|
+
p.ignore_pattern = ["tmp/*", "script/*", "dbfile"]
|
11
|
+
p.development_dependencies = []
|
12
|
+
end
|
13
|
+
|
14
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{factory_grabber}
|
5
|
+
s.version = "1.0.3"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Gavin Morrice"]
|
9
|
+
s.date = %q{2009-09-17}
|
10
|
+
s.description = %q{Grab or create factories for faster Functional/Integration testing}
|
11
|
+
s.email = %q{gavin@handyrailstips.com}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "README.md", "lib/dbfile", "lib/factory_grabber.rb", "lib/spec/database_setup.rb", "lib/spec/dbfile", "lib/spec/factories.rb", "lib/spec/grab_spec.rb", "lib/spec/performance_test.rb", "lib/spec/spec_helper.rb", "lib/spec/user.rb"]
|
13
|
+
s.files = ["CHANGELOG", "Manifest", "README.md", "Rakefile", "init.rb", "lib/dbfile", "lib/factory_grabber.rb", "lib/spec/database_setup.rb", "lib/spec/dbfile", "lib/spec/factories.rb", "lib/spec/grab_spec.rb", "lib/spec/performance_test.rb", "lib/spec/spec_helper.rb", "lib/spec/user.rb", "factory_grabber.gemspec"]
|
14
|
+
s.homepage = %q{http://github.com/gavinM/factory_grabber}
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Factory_grabber", "--main", "README.md"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{factory_grabber}
|
18
|
+
s.rubygems_version = %q{1.3.5}
|
19
|
+
s.summary = %q{Grab or create factories for faster Functional/Integration testing}
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
+
s.specification_version = 3
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
26
|
+
else
|
27
|
+
end
|
28
|
+
else
|
29
|
+
end
|
30
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "factory_grabber"
|
data/lib/dbfile
ADDED
Binary file
|
@@ -0,0 +1,176 @@
|
|
1
|
+
# load active support if not in Rails
|
2
|
+
require "activesupport" unless defined?(ActiveSupport::Inflector)
|
3
|
+
require "factory_girl"
|
4
|
+
module FactoryGrabber
|
5
|
+
|
6
|
+
class NotANumberError < NoMethodError;end
|
7
|
+
|
8
|
+
module Grab
|
9
|
+
|
10
|
+
# numbers 1 to 9
|
11
|
+
UNITS = {
|
12
|
+
"one" => 1,
|
13
|
+
"two" => 2,
|
14
|
+
"three" => 3,
|
15
|
+
"four" => 4,
|
16
|
+
"five" => 5,
|
17
|
+
"six" => 6,
|
18
|
+
"seven" => 7,
|
19
|
+
"eight" => 8,
|
20
|
+
"nine" => 9}
|
21
|
+
|
22
|
+
# numbers 10 to 19
|
23
|
+
TEENS = {
|
24
|
+
"ten" => 10,
|
25
|
+
"eleven" => 11,
|
26
|
+
"twelve" => 12,
|
27
|
+
"thirteen" => 13,
|
28
|
+
"fourteen" => 14,
|
29
|
+
"fifteen" => 15,
|
30
|
+
"sixteen" => 16,
|
31
|
+
"seventeen" => 17,
|
32
|
+
"eighteen" => 18,
|
33
|
+
"nineteen" => 19}
|
34
|
+
|
35
|
+
# tens from 20 to 90
|
36
|
+
TENS = {
|
37
|
+
"twenty" => 20,
|
38
|
+
"thirty" => 30,
|
39
|
+
"forty" => 40,
|
40
|
+
"fifty" => 50,
|
41
|
+
"sixty" => 60,
|
42
|
+
"seventy" => 70,
|
43
|
+
"eighty" => 80,
|
44
|
+
"ninety" => 90}
|
45
|
+
|
46
|
+
# define an empty hash
|
47
|
+
ALL_NUMBERS = {}
|
48
|
+
|
49
|
+
# add each number between 1 and 19 to ALL_NUMBERS
|
50
|
+
UNITS.merge(TEENS).each { |name, value| ALL_NUMBERS[name] = value }
|
51
|
+
|
52
|
+
TENS.each do |name, value|
|
53
|
+
# add each ten from 20 to 90 to ALL_NUMBERS
|
54
|
+
ALL_NUMBERS[name] = value
|
55
|
+
# add each remaining number to ALL_NUMBERS
|
56
|
+
UNITS.each { |unit_name, unit_value| ALL_NUMBERS["#{name}_#{unit_name}"] = value + unit_value }
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
# remove unnecessary methods from Grab class
|
61
|
+
instance_methods.each do |m|
|
62
|
+
undef_method m unless m.to_s =~ /method_missing|respond_to?|^__/
|
63
|
+
end
|
64
|
+
|
65
|
+
# add singleton class methods
|
66
|
+
class << self
|
67
|
+
|
68
|
+
# methods called to Grab are not really methods, they're ghost methods.
|
69
|
+
# If method_missing cannot identify the number and the factory to be created it will pass
|
70
|
+
# this up the chain to Object. @name is the method name called (symbol) and options is the hash of
|
71
|
+
# options passed to the method.
|
72
|
+
def method_missing(name, options = {})
|
73
|
+
@options = options
|
74
|
+
@parts_in_name = name.to_s.split("_")
|
75
|
+
|
76
|
+
# replace 'a' or 'an' with 'one'
|
77
|
+
if @parts_in_name.first == "a" || @parts_in_name.first == "an"
|
78
|
+
@parts_in_name.delete_at(0)
|
79
|
+
@parts_in_name.unshift("one")
|
80
|
+
end
|
81
|
+
# rejoins the name with 'a' and 'an' replaced with 'one'
|
82
|
+
@name = @parts_in_name.join("_")
|
83
|
+
|
84
|
+
# check the options if there are any
|
85
|
+
unless @options.empty?
|
86
|
+
check_options_against_database
|
87
|
+
end
|
88
|
+
|
89
|
+
# results to be returned
|
90
|
+
@results = []
|
91
|
+
|
92
|
+
if @should_create_new
|
93
|
+
number.times { @results << create_factory }
|
94
|
+
else
|
95
|
+
# create new records if there is not a sufficient amount in the database
|
96
|
+
required_records ? required_records.times { create_factory } : nil
|
97
|
+
|
98
|
+
# find and return the desired records
|
99
|
+
@results = klass_name_constant.all(:conditions => @options, :limit => number)
|
100
|
+
end
|
101
|
+
# return a single record if only one exists
|
102
|
+
@results.size == 1 ? @results.first : @results
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
# checks the database columns to ensure options are all database columns
|
108
|
+
# if they are not (in the case of virtual attributes) a new factory should be created
|
109
|
+
def check_options_against_database
|
110
|
+
# extract the keys from the options hash as strings
|
111
|
+
option_keys = @options.stringify_keys.keys
|
112
|
+
# fetch the names of the Class's database table columns
|
113
|
+
klass_columns = klass_name_constant.columns.collect { |c| c.name }
|
114
|
+
# @should create new will be true if there are any option keys that are not in db table
|
115
|
+
@should_create_new = !!option_keys.detect { |opt| !klass_columns.include?(opt) }
|
116
|
+
end
|
117
|
+
|
118
|
+
# returns the number part of the method name eg. nineteen
|
119
|
+
def number_name
|
120
|
+
@number_name = if UNITS.include?(@parts_in_name.first) || TEENS.include?(@parts_in_name.first)
|
121
|
+
@parts_in_name.first
|
122
|
+
elsif TENS.include?(@parts_in_name.first)
|
123
|
+
UNITS.include?(@parts_in_name[1]) ? @parts_in_name[0..1].join("_") : @parts_in_name.first
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# returns the number as an integer
|
128
|
+
def number
|
129
|
+
@number = ALL_NUMBERS[number_name]
|
130
|
+
raise NotANumberError, "#{@name} contains an invalid number" unless @number
|
131
|
+
@number
|
132
|
+
end
|
133
|
+
|
134
|
+
# returns the klass name of the
|
135
|
+
def klass_name
|
136
|
+
@name.to_s.scan(/#{number_name}_(.+)/)
|
137
|
+
ActiveSupport::Inflector.singularize($1)
|
138
|
+
end
|
139
|
+
|
140
|
+
# returns the name of the factory as a symbol.
|
141
|
+
# Eg. Grab.four_hippos (would return :hippo)
|
142
|
+
def klass_name_symbol
|
143
|
+
klass_name.to_sym
|
144
|
+
end
|
145
|
+
|
146
|
+
# returns the name of the factory as a Constant.
|
147
|
+
# Eg. Grab.four_hippos (would return :hippo)
|
148
|
+
def klass_name_constant
|
149
|
+
klass_name.classify.constantize
|
150
|
+
end
|
151
|
+
|
152
|
+
# TODO rewrite this to accept various factory gems
|
153
|
+
def create_factory
|
154
|
+
Factory(klass_name_symbol, @options)
|
155
|
+
end
|
156
|
+
|
157
|
+
# returns the number of records required minus the number of records available. If there are enough
|
158
|
+
# records already it will return nil (so we can call <tt>required_records ? do_this : do_that</tt> )
|
159
|
+
def required_records
|
160
|
+
result = (number - number_of_existing_records)
|
161
|
+
result > 0 ? result : nil
|
162
|
+
end
|
163
|
+
|
164
|
+
# finds the number appropriate records already in the database.
|
165
|
+
# if klass_name_constant is not a recognised class then this returns 0
|
166
|
+
def number_of_existing_records
|
167
|
+
return 0 unless defined?(klass_name_constant)
|
168
|
+
klass_name_constant.all(:conditions => @options).count
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
include FactoryGrabber
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
ActiveRecord::Base.establish_connection :adapter => "sqlite3", :database => "dbfile"
|
3
|
+
|
4
|
+
ActiveRecord::Base.connection.create_table :users, :force => true do |t|
|
5
|
+
t.string :first_name
|
6
|
+
t.string :last_name
|
7
|
+
t.string :email
|
8
|
+
t.boolean :admin
|
9
|
+
end
|
data/lib/spec/dbfile
ADDED
Binary file
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/spec_helper"
|
2
|
+
|
3
|
+
describe Grab do
|
4
|
+
|
5
|
+
describe "Grabbing 'a' or 'an' record" do
|
6
|
+
|
7
|
+
it "should return one record if number is 'a'" do
|
8
|
+
@user = Grab.a_user
|
9
|
+
@user.is_a?(User).should be_true
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should return one record if number is 'an'" do
|
13
|
+
@user = Grab.an_user
|
14
|
+
@user.is_a?(User).should be_true
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "Grabbing various number combinations" do
|
20
|
+
|
21
|
+
it "should return the record if number is one" do
|
22
|
+
@user = Grab.one_user
|
23
|
+
@user.is_a?(User).should be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should grab the correct number of records each time" do
|
27
|
+
# random number between 1 and 99
|
28
|
+
# running these specs hundreds of times (which I have) means that each number will be tested
|
29
|
+
random_number = (rand * 99).ceil
|
30
|
+
# return the number name eg. sixty_one
|
31
|
+
random_name = Grab::ALL_NUMBERS.invert[random_number]
|
32
|
+
@users = Grab.send("#{random_name}_users")
|
33
|
+
@users.size.should == random_number
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "Grabbing existing records" do
|
39
|
+
|
40
|
+
before do
|
41
|
+
Factory :user unless User.all.any?
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should not create a new record if there is one present" do
|
45
|
+
lambda { Grab.one_user }.should_not change { User.count }
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "Grabbing non-existing records" do
|
51
|
+
|
52
|
+
before do
|
53
|
+
User.destroy_all
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should create a new record" do
|
57
|
+
lambda { Grab.one_user }.should change { User.count }.by(1)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "Grabbing a mixture of existing and non-existing records" do
|
63
|
+
|
64
|
+
before do
|
65
|
+
User.destroy_all
|
66
|
+
2.times { Factory :user }
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should only create one extra record" do
|
70
|
+
lambda { Grab.three_users }.should change { User.count }.by(1)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "Grabbing factories with virtual attributes" do
|
76
|
+
# Attributes such as password can be set when creating factories but may not have a corresponding
|
77
|
+
# column on the database (ie. they are virtual attributes)
|
78
|
+
# In such cases, to ensure the record has the desired attributes, a new factory should be created
|
79
|
+
it "should create a new factory if attributes are not all in the database" do
|
80
|
+
Factory(:user, :password => "password")
|
81
|
+
lambda { @user = Grab.one_user(:password => "password") }.should change { User.count }.by(1)
|
82
|
+
@user.is_a?(User).should be_true
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
describe :number_name do
|
88
|
+
|
89
|
+
it "should return the correct number if it's a unit" do
|
90
|
+
Grab.one_user
|
91
|
+
Grab.send(:number_name).should == 'one'
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should return the correct number if it's a teen'" do
|
95
|
+
Grab.eleven_users
|
96
|
+
Grab.send(:number_name).should == 'eleven'
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should return the correct number if it's a double-digit" do
|
100
|
+
Grab.twenty_one_users
|
101
|
+
Grab.send(:number_name).should == 'twenty_one'
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should return the correct number if it's a ten" do
|
105
|
+
Grab.twenty_users
|
106
|
+
Grab.send(:number_name).should == 'twenty'
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
describe :number do
|
112
|
+
|
113
|
+
it "should return the correct number if it's a unit" do
|
114
|
+
Grab.four_users
|
115
|
+
Grab.send(:number).should == 4
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should return the correct number if it's a teen'" do
|
119
|
+
Grab.twelve_users
|
120
|
+
Grab.send(:number).should == 12
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should return the correct number if it's a double-digit" do
|
124
|
+
Grab.twenty_one_users
|
125
|
+
Grab.send(:number).should == 21
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should return the correct number if it's a ten" do
|
129
|
+
Grab.twenty_users
|
130
|
+
Grab.send(:number).should == 20
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
describe :klass_name do
|
136
|
+
|
137
|
+
it "should return the name of the factory class as a constant if available" do
|
138
|
+
Grab.one_user
|
139
|
+
Grab.send(:klass_name).should == "user"
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
describe :klass_name_constant do
|
145
|
+
|
146
|
+
it "should return the class name as a constant" do
|
147
|
+
Grab.one_user
|
148
|
+
Grab.send(:klass_name_constant).should == User
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
describe :required_records do
|
154
|
+
|
155
|
+
before do
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should return nil if no records are required" do
|
159
|
+
count = User.count
|
160
|
+
if count < 4
|
161
|
+
(4 - count).times { Factory(:user) }
|
162
|
+
end
|
163
|
+
Grab.three_users
|
164
|
+
Grab.send(:required_records).should be_nil
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/spec_helper"
|
2
|
+
require "benchmark"
|
3
|
+
|
4
|
+
# runs a quick benchmark to compare the two
|
5
|
+
Benchmark.bmbm do |test|
|
6
|
+
test.report("Create 50 new factories") do
|
7
|
+
50.times { Factory :user, :first_name => "John", :admin => false }
|
8
|
+
end
|
9
|
+
|
10
|
+
until User.count >= 50
|
11
|
+
Factory :user, :last_name => "Smith", :admin => true
|
12
|
+
end
|
13
|
+
|
14
|
+
test.report("Grab 50 separate factories") do
|
15
|
+
50.times { Grab.one_user :last_name => "Smith", :admin => true }
|
16
|
+
end
|
17
|
+
|
18
|
+
test.report("Grab 50 factories at once") do
|
19
|
+
Grab.fifty_users :last_name => "Smith", :admin => true
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/lib/spec/user.rb
ADDED
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: factory_grabber
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gavin Morrice
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-09-17 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Grab or create factories for faster Functional/Integration testing
|
17
|
+
email: gavin@handyrailstips.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- CHANGELOG
|
24
|
+
- README.md
|
25
|
+
- lib/dbfile
|
26
|
+
- lib/factory_grabber.rb
|
27
|
+
- lib/spec/database_setup.rb
|
28
|
+
- lib/spec/dbfile
|
29
|
+
- lib/spec/factories.rb
|
30
|
+
- lib/spec/grab_spec.rb
|
31
|
+
- lib/spec/performance_test.rb
|
32
|
+
- lib/spec/spec_helper.rb
|
33
|
+
- lib/spec/user.rb
|
34
|
+
files:
|
35
|
+
- CHANGELOG
|
36
|
+
- Manifest
|
37
|
+
- README.md
|
38
|
+
- Rakefile
|
39
|
+
- init.rb
|
40
|
+
- lib/dbfile
|
41
|
+
- lib/factory_grabber.rb
|
42
|
+
- lib/spec/database_setup.rb
|
43
|
+
- lib/spec/dbfile
|
44
|
+
- lib/spec/factories.rb
|
45
|
+
- lib/spec/grab_spec.rb
|
46
|
+
- lib/spec/performance_test.rb
|
47
|
+
- lib/spec/spec_helper.rb
|
48
|
+
- lib/spec/user.rb
|
49
|
+
- factory_grabber.gemspec
|
50
|
+
has_rdoc: true
|
51
|
+
homepage: http://github.com/gavinM/factory_grabber
|
52
|
+
licenses: []
|
53
|
+
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options:
|
56
|
+
- --line-numbers
|
57
|
+
- --inline-source
|
58
|
+
- --title
|
59
|
+
- Factory_grabber
|
60
|
+
- --main
|
61
|
+
- README.md
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
version:
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: "1.2"
|
75
|
+
version:
|
76
|
+
requirements: []
|
77
|
+
|
78
|
+
rubyforge_project: factory_grabber
|
79
|
+
rubygems_version: 1.3.5
|
80
|
+
signing_key:
|
81
|
+
specification_version: 3
|
82
|
+
summary: Grab or create factories for faster Functional/Integration testing
|
83
|
+
test_files: []
|
84
|
+
|