dfl-factories-and-workers 0.0.2

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/CHANGELOG ADDED
@@ -0,0 +1,10 @@
1
+ * [10/14/2008] - 0.0.2 (gem release)
2
+
3
+ Fixed problem with rails/init.rb
4
+
5
+
6
+ * [08/05/2008] - 0.0.1 (gem release)
7
+
8
+ Initial release as a gem.
9
+
10
+ Removed some Rails specific code, but the gem is still dependent on activerecord.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2007-2008 Nathan Herald, David Lowenfels and Jonathan Barket
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,149 @@
1
+ = Credits
2
+
3
+ Originally written by Nathan Herald @ Myobie.com
4
+
5
+ Feature enhancements by David Lowenfels @ InternautDesign.com
6
+
7
+ Minor improvements by Jonathan Barket
8
+
9
+ == Get It
10
+
11
+ Add it as a gem dependency
12
+
13
+ config.gem 'dfl-factories-and-workers', :lib => 'factories-and-workers', :source => 'http://gems.github.com'
14
+
15
+ Or install it as a gem manually
16
+
17
+ sudo gem install dfl-factories-and-workers
18
+
19
+ Or grab the source
20
+
21
+ git clone git://github.com/dfl/factories-and-workers.git
22
+
23
+ =The Factory
24
+
25
+ The Factory idea was inspired completely by Dan Manges' blog post "Fixin' Fixtures with Factory" @ http://www.dcmanges.com/blog/38
26
+
27
+
28
+ The Factory is a module that has three methods for each model: +build_model+, +create_model+ and +valid_model_attributes+.
29
+ ( For semantic purposes, +default_model_attributes+ is also available as an alias to +valid_model_attributes+. )
30
+
31
+ These methods create objects in a valid state, with default attributes and associations. When using the +create_model+ and +build_model+ methods, you can pass in a hash to override any of the default attributes if needed.
32
+ Typically, you should create a file named 'factories.rb' in either the spec or test directory in your project to declare factory methods and default attributes.
33
+ It will be loaded during plugin initialization (see init.rb). You could also explicitly require it from test_helper.rb
34
+
35
+ A minimal factories.rb file:
36
+
37
+ include FactoriesAndWorkers::Factory # mixin to Object, which is especially useful for script/console work; season to taste.
38
+
39
+ factory :user, :name => "default name"
40
+
41
+ This would define methods named +build_user+, +create_user+, and +valid_user_attributes+ to be available in any Object in the project.
42
+ If you wanted to override the default valid attributes, you could call:
43
+ create_user( :name => "a different name" )
44
+
45
+
46
+ A more complicated example:
47
+
48
+ factory :role, :title => "role title"
49
+
50
+ factory :user, {
51
+ :first_name => "Joe",
52
+ :last_name => "Momma",
53
+ :password => "$UNIQ(7)", # the $UNIQ(n) magic variable interpolates to a unique string of length n
54
+ :login => "user_$COUNT", # the $COUNT magic variable interpolates to an incremental number, beginning with 1
55
+ :role => :belongs_to_model,
56
+ :created_at => lambda { Time.zone.now - 7 } # lazy evaluation: will be called on object instantiation rather than factory definition
57
+ } do |u| # code to be called in after_initialize hook
58
+ u.email = "#{u.first_name}.#{u.last_name}@example.com".downcase
59
+ end
60
+
61
+ factory :order, {
62
+ :quantity => 5,
63
+ :price => 500,
64
+ :user => :belongs_to_model
65
+ :number => lambda { increment! :foo } # increment a counter by arbitrary key
66
+ }
67
+
68
+ factory :special_order, {
69
+ :kind => 'Special'
70
+ }, :class => Order, :chain => lambda{ valid_order_attributes } # reverse merges with valid_order_attributes
71
+
72
+
73
+ A value of :belongs_to_model on an attribute adds logic to call +create_+ or +build_+, appropriately.
74
+ For example:
75
+ valid_user_attributes # assigns :role => build_role
76
+ build_user # assigns :role => build_role
77
+
78
+ create_user # assigns :role => create_role
79
+ valid_user_attributes(true) # assigns :role => create_role
80
+ In this way, models are not saved to the database unnecessarily.
81
+
82
+ Note that if you pass a foreign key attribute as a build or create override, the corresponding default object will not be constructed.
83
+ For example:
84
+ create_user( :role_id => 1 ) # will not call create_role.
85
+
86
+
87
+ Two helper methods are available to be used in lambda blocks:
88
+ * increment!( key ) -- increments a global counter keyed on a symbol or string
89
+ * uniq( length ) -- returns a random string
90
+
91
+
92
+ There is also a rake task to automagically generate template factories from your models.
93
+ rake factory:generate # will print templates for all AR models
94
+ rake factory:generate MODEL=user # will print template for user model
95
+
96
+
97
+ =The FactoryWorker
98
+
99
+ The FactoryWorker is a work in progress.
100
+
101
+ If you create a file named 'factory_workers.rb' in either your spec or test directory, you can define snippets of code that can be ran at anytime, anywhere in your tests (this may not be true in the future, I may limit where it can be run, iono).
102
+
103
+ A factory worker is defined as so:
104
+
105
+ factory_worker :name do
106
+ # any ruby code you want
107
+ end
108
+
109
+ Then, in your tests you can call 'worker :name' to run the ruby code contained in the worker.
110
+
111
+ It can be useful for populating the database with objects:
112
+
113
+ factory_worker :salable_and_non_salable_products do
114
+ create_variant( :sku => "1" )
115
+ create_variant( :sku => "2" )
116
+ create_variant( :sku => "3", :in_stock => false )
117
+ create_variant( :sku => "4", :in_stock => false )
118
+ end
119
+
120
+ The +create_variant+ method would provided by my factory setup, and creates a valid product with associated colors, sizes, and other options that I need. Now, I have 4 products in the database, 2 are in stock and 2 are not. So, in my test: find(:salable).length.should == 2
121
+
122
+ And it does.
123
+
124
+ Similar to rake task dependencies, you can chain workers together like this:
125
+
126
+ factory_worker :first do
127
+ puts "I am first"
128
+ end
129
+
130
+ factory_worker :second => :first do
131
+ puts "I am second"
132
+ end
133
+
134
+ factory_worker :third => :second do
135
+ puts "I am third"
136
+ end
137
+
138
+ If you call 'worker :third', it should output:
139
+
140
+ I am first
141
+ I am second
142
+ I am third
143
+
144
+ You can also chain workers like this:
145
+ factory_worker :several => [ :first, :second ]
146
+
147
+ and even add dependencies to the chain in further statements
148
+ factory_worker :several => [ :third ]
149
+
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the factories-and-workers plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the factorires-and-workers plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'factories-and-workers'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README.rdoc')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ require "factories-and-workers"
2
+ require File.dirname(__FILE__)+"/rails/init.rb" if defined?(RAILS_ENV)
@@ -0,0 +1,4 @@
1
+ require 'active_support/core_ext' # for returning() and HashWithIndifferentAccess
2
+ require 'factories-and-workers/factory_builder'
3
+ require 'factories-and-workers/factory_worker'
4
+ require 'factories-and-workers/factory_generator'
@@ -0,0 +1,112 @@
1
+ require 'digest/sha1'
2
+
3
+ module FactoriesAndWorkers
4
+
5
+ module Factory
6
+ def self.included( base )
7
+ base.extend ClassMethods
8
+ end
9
+
10
+ module ClassMethods
11
+ def factory( kind, default_attrs, opts={}, &block )
12
+ FactoryBuilder.new( kind, default_attrs, opts, self, &block )
13
+ end
14
+
15
+ # creates a random hex string, converts it to hexatridecimal, and truncates to desired length (max 30)
16
+ def uniq len=10
17
+ Digest::SHA1.hexdigest("#{rand(1<<64)}/#{Time.now.to_f}/#{Process.pid}").to_i(16).to_s(36)[1..len]
18
+ end
19
+
20
+ @@factory_counter = Hash.new(0)
21
+ def increment! counter
22
+ @@factory_counter[ counter.to_s ] += 1
23
+ end
24
+
25
+ @@factory_initializers = {}
26
+ def factory_initializers
27
+ @@factory_initializers
28
+ end
29
+ end
30
+
31
+ # factory methods are defined as class methods; this delegation will allow them to also be called as instance methods
32
+ def method_missing method, *args, &block
33
+ if self.class.respond_to?( method )
34
+ self.class.send method, *args, &block
35
+ else
36
+ super
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ class FactoryBuilder
43
+ def initialize( factory, default_attrs, opts, from_klass, &block )
44
+ raise ArgumentError, ":chain must be a lambda block!" if opts[:chain] && !opts[:chain].is_a?( Proc )
45
+ opts.reverse_merge!( :class => factory )
46
+
47
+ ar_klass = ActiveRecord.const_get( opts[:class].to_s.classify )
48
+ from_klass.factory_initializers[ factory ] = block if block_given?
49
+
50
+ # make the valid attributes method
51
+ valid_attrs_method = :"valid_#{factory}_attributes"
52
+ Factory::ClassMethods.send :define_method, valid_attrs_method do |*args|
53
+ action = args.first.is_a?( TrueClass ) ? :create : :build
54
+ attrs = default_attrs.symbolize_keys
55
+ attr_overrides = args.extract_options!
56
+ attrs.merge!( attr_overrides.symbolize_keys ) if attr_overrides
57
+ attrs.reverse_merge!( opts[:chain].call ) if opts[:chain]
58
+ attrs.each_pair do |key, value|
59
+ if attr_overrides.keys.include?(:"#{key}_id")
60
+ attrs.delete(key) # if :#{model}_id is overridden, then remove :#{model} and don't evaluate the lambda block
61
+ else
62
+ attrs[key] = case value
63
+ when Proc
64
+ value.call # evaluate lambda blocks
65
+ when :belongs_to_model
66
+ send( :"#{action}_#{key}" ) # create or build model dependencies, if none are found in the db
67
+ when String # interpolate magic variables
68
+ value.gsub( /\$UNIQ\((\d+)\)/ ){ from_klass.uniq( $1.to_i ) }.
69
+ gsub( '$COUNT', from_klass.increment!( :"#{ar_klass}_#{key}" ).to_s )
70
+ else
71
+ value
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ # make the valid attribute method, which only fetches a single attribute
78
+ valid_attr_method = :"valid_#{factory}_attribute"
79
+ Factory::ClassMethods.send :define_method, valid_attr_method do |arg|
80
+ return unless arg.is_a?( Symbol )
81
+ base = default_attrs.dup
82
+ base.reverse_merge!( opts[:chain].call ) if opts[:chain]
83
+ returning base[ arg ] do |value|
84
+ value = value.call if value.is_a?( Proc ) # evaluate lambda if needed
85
+ end
86
+ end
87
+
88
+ # alias default_*_attributes to valid_*_attributes, for semantic equivalency
89
+ Factory::ClassMethods.send :alias_method, valid_attrs_method.to_s.gsub('valid','default').to_sym, valid_attrs_method
90
+ Factory::ClassMethods.send :alias_method, valid_attr_method.to_s.gsub('valid','default').to_sym, valid_attr_method
91
+
92
+
93
+ after_initialize_block = from_klass.factory_initializers[ factory ]
94
+
95
+ # make the create method
96
+ Factory::ClassMethods.send :define_method, :"create_#{factory}" do |*args|
97
+ ar_klass.create!( self.send( valid_attrs_method, true, args.first ) ) do |obj|
98
+ after_initialize_block.call( obj ) if after_initialize_block
99
+ end
100
+ end
101
+
102
+ # make the build method
103
+ Factory::ClassMethods.send :define_method, :"build_#{factory}" do |*args|
104
+ ar_klass.new( self.send( valid_attrs_method, false, args.first ) ) do |obj|
105
+ after_initialize_block.call( obj ) if after_initialize_block
106
+ end
107
+ end
108
+
109
+ end #initialize
110
+ end
111
+
112
+ end
@@ -0,0 +1,49 @@
1
+ module Factory
2
+
3
+ IGNORED_COLUMNS = %w[ id created_at updated_at created_on updated_on ]
4
+
5
+ def self.generate_template arg
6
+ model = arg.classify.constantize
7
+ columns = {}
8
+ model.columns.each do |col|
9
+ key = col.name
10
+ if key =~ /^(.+)_id$/
11
+ columns[ $1.to_sym ] = :belongs_to_model
12
+ else
13
+ columns[ key.to_sym ] = { :type => col.type, :default => col.default }
14
+ end unless IGNORED_COLUMNS.include?( key )
15
+ end
16
+
17
+ template = "\nfactory :#{model.to_s.underscore}, {\n"
18
+ columns.each_pair do |name, val|
19
+ template += " :#{name} => #{ default_for( val ) },\n"
20
+ end
21
+ template += "}\n\n"
22
+ end
23
+
24
+ protected
25
+
26
+ def self.default_for val
27
+ case val
28
+ when :belongs_to_model
29
+ return val.inspect
30
+ when Hash
31
+ # return val[:default] if val[:default] # not sure if this works?
32
+ case val[:type]
33
+ when :integer
34
+ 123
35
+ when :string, :text
36
+ "SomeString".inspect
37
+ when :float
38
+ 1.23
39
+ when :date
40
+ "lambda{ 7.days.from_now }"
41
+ when :datetime
42
+ "lambda{ 12.hours.from_now }"
43
+ when :boolean
44
+ val[:default] || false
45
+ end
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,60 @@
1
+ module FactoriesAndWorkers
2
+
3
+ module Worker
4
+ def worker( worker_name )
5
+ FactoryWorker.find_and_work worker_name
6
+ end
7
+
8
+ def self.included( base )
9
+ base.extend ClassMethods
10
+ end
11
+
12
+ module ClassMethods
13
+ def factory_worker( worker, &block )
14
+ FactoryWorker.new( worker, &block )
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ class FactoryWorker
21
+ @@workers = HashWithIndifferentAccess.new
22
+
23
+ def initialize( worker, &block )
24
+ case worker
25
+ when Hash
26
+ @dependencies = [ *worker.values.first ]
27
+ @worker = worker.keys.first
28
+ when Symbol, String
29
+ @worker = worker
30
+ else
31
+ raise ArgumentError, "I don't know how to make a factory worker out of '#{worker.inspect}'"
32
+ end
33
+
34
+ @block = block if block_given?
35
+ @@workers[ @worker ] = self
36
+ end
37
+
38
+ def self.find_and_work( worker_name )
39
+ raise ArgumentError, "There is no factory worker named '#{worker_name.to_s}' available" unless @@workers.include?(worker_name.to_s)
40
+ @@workers[ worker_name ].work
41
+ end
42
+
43
+ def work
44
+ @dependencies.each{ |w| self.class.find_and_work( w ) } if @dependencies
45
+ surface_errors{ @block.call( self ) } if @block
46
+ end
47
+
48
+ def surface_errors
49
+ yield
50
+ rescue Object => error
51
+ puts
52
+ puts "There was an error working the factory worker '#{@worker}':", error.inspect
53
+ puts
54
+ puts error.backtrace
55
+ puts
56
+ exit!
57
+ end
58
+ end
59
+
60
+ end
@@ -0,0 +1,18 @@
1
+ desc "Generate factory templates from database schema; takes optional MODEL= argument"
2
+
3
+ namespace :factory do
4
+
5
+ task :generate do
6
+ require File.join( RAILS_ROOT, 'config', 'environment' )
7
+
8
+ if arg = ENV['model'] || ENV['MODEL']
9
+ puts Factory.generate_template( arg )
10
+ else
11
+ all_models = Dir.glob( File.join( RAILS_ROOT, 'app', 'models', '*.rb') ).map{|path| path[/.+\/(.+).rb/, 1] }
12
+ all_models.select{|m| m.classify.constantize < ActiveRecord::Base}.each do |model|
13
+ puts Factory.generate_template( model )
14
+ end
15
+ end
16
+ end
17
+
18
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'fileutils'
2
+
3
+ # config.after_initialize do
4
+ %w(spec/factories.rb spec/factory_workers.rb test/factories.rb test/factory_workers.rb).each do |file|
5
+ path = File.join(Dir.pwd, file)
6
+ require path if File.exists?(path)
7
+ end
8
+ # end
@@ -0,0 +1,6 @@
1
+ class Monkey < ActiveRecord::Base
2
+ attr_accessor :unique, :counter, :number
3
+
4
+ belongs_to :pirate
5
+ validates_presence_of :name
6
+ end
@@ -0,0 +1,3 @@
1
+ class Pirate < ActiveRecord::Base
2
+ has_one :monkey
3
+ end
@@ -0,0 +1,3 @@
1
+ class User < ActiveRecord::Base
2
+ attr_accessor :first_name, :last_name, :email
3
+ end
data/test/db/schema.rb ADDED
@@ -0,0 +1,17 @@
1
+ ActiveRecord::Schema.define do
2
+
3
+ create_table :monkeys do |t|
4
+ t.column :name, :string
5
+ end
6
+
7
+ create_table :pirates do |t|
8
+ t.column :catchphrase, :string
9
+ t.column :monkey_id, :integer
10
+ t.column :created_on, :datetime
11
+ t.column :updated_on, :datetime
12
+ end
13
+
14
+ create_table :users do |t|
15
+ end
16
+
17
+ end
data/test/factories.rb ADDED
@@ -0,0 +1,18 @@
1
+ include FactoriesAndWorkers::Factory
2
+
3
+ factory :monkey, {
4
+ :name => "George",
5
+ :unique => "$UNIQ(10)",
6
+ :counter => "$COUNT",
7
+ :number => lambda{ increment! :foo }
8
+ }
9
+
10
+ factory :pirate, {
11
+ :catchphrase => "Ahhrrrr, Matey!",
12
+ :monkey => :belongs_to_model,
13
+ :created_on => lambda{ 1.day.ago }
14
+ }
15
+
16
+ factory :ninja_pirate, {
17
+ :catchphrase => "(silent)"
18
+ }, :class => Pirate, :chain => lambda{ valid_pirate_attributes( :monkey => nil ) }
@@ -0,0 +1,146 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/test_helper")
2
+
3
+ class FactoryBuilderTest < Test::Unit::TestCase
4
+
5
+ def metaclass; class << self; self; end; end
6
+
7
+ def test_unknown_factory_raises_error
8
+ e = assert_raises(NameError) do
9
+ metaclass.class_eval do
10
+ factory :foo, {}
11
+ end
12
+ end
13
+ assert_equal "uninitialized constant ActiveRecord::Foo", e.message
14
+ end
15
+
16
+ def test_factory_with_initializer
17
+ metaclass.class_eval do
18
+ factory :user, {
19
+ :first_name => "Joe",
20
+ :last_name => "Blow"
21
+ } do |u| u.email = "#{u.first_name}.#{u.last_name}@example.com".downcase end
22
+ end
23
+ assert_equal "joe.doe@example.com", build_user( :last_name => 'Doe' ).email
24
+ end
25
+
26
+ def test_build_monkey_does_not_save
27
+ assert_difference "Monkey.count", 0 do
28
+ build_monkey
29
+ end
30
+ end
31
+
32
+ def test_create_monkey_does_save
33
+ assert_difference "Monkey.count", 1 do
34
+ create_monkey
35
+ end
36
+ end
37
+
38
+ def test_valid_monkey_attributes
39
+ assert_equal( {:name => "George"}, remove_variability( valid_monkey_attributes ) )
40
+ end
41
+
42
+ def test_valid_pirate_attributes_without_create_parents
43
+ assert_difference "Monkey.count", 0 do
44
+ valid_pirate_attributes( false )
45
+ end
46
+ end
47
+
48
+ def test_valid_pirate_attributes_with_create_parents
49
+ assert_difference "Monkey.count", 1 do
50
+ valid_pirate_attributes( true )
51
+ end
52
+ end
53
+
54
+ def test_valid_attribute__does_not_evaluate_other_attributes
55
+ assert_difference "Monkey.count", 0 do
56
+ assert_equal "Ahhrrrr, Matey!", valid_pirate_attribute(:catchphrase)
57
+ end
58
+ end
59
+
60
+ def test_build_pirate
61
+ assert_difference "Pirate.count", 0 do
62
+ assert_difference "Monkey.count", 0 do
63
+ build_pirate
64
+ end
65
+ end
66
+ end
67
+
68
+ def test_create_pirate_evaluates_lambda
69
+ assert_difference "Pirate.count", 1 do
70
+ assert_difference "Monkey.count", 1 do
71
+ @pirate = create_pirate
72
+ end
73
+ end
74
+ assert_equal @pirate.created_on.to_s, 1.day.ago.to_s
75
+ sleep 1
76
+ assert_not_equal create_pirate.updated_on.to_s, @pirate.updated_on.to_s
77
+ end
78
+
79
+ def test_ninja_pirate_is_silent_and_has_no_monkey
80
+ assert_difference "Pirate.count", 1 do
81
+ assert_difference "Monkey.count", 0 do
82
+ @pirate = create_ninja_pirate
83
+ end
84
+ end
85
+ assert_equal "(silent)", @pirate.catchphrase
86
+ end
87
+
88
+ def test_overridden_attributes
89
+ @phil = create_monkey( :name => "Phil" )
90
+ assert_not_equal valid_monkey_attribute(:name), @phil.name, "default monkey name should be overridden"
91
+
92
+ assert_difference "Pirate.count", 0 do
93
+ assert_difference "Monkey.count", 0 do
94
+ @pirate = build_pirate( :monkey => @phil, :catchphrase => "chunky bacon!" )
95
+ end
96
+ end
97
+ assert_not_equal valid_pirate_attribute(:catchphrase), @pirate.catchphrase, "default pirate catchphrase should be overridden"
98
+ assert_equal "Phil", @pirate.monkey.name
99
+ assert_equal "George", build_pirate.monkey.name
100
+ end
101
+
102
+ def test_overridden_attribute_id_will_not_evaluate_lambda_for_model_creation
103
+ assert_difference "Monkey.count", 0 do
104
+ @pirate = build_pirate( :monkey_id => 1 )
105
+ end
106
+ end
107
+
108
+ def test_uniq_interpolation
109
+ a = build_monkey.unique
110
+ assert_equal 10, a.size
111
+
112
+ b = build_monkey.unique
113
+ assert_equal 10, b.size
114
+
115
+ assert_not_equal a, b
116
+ end
117
+
118
+ def test_count_interpolation_not_interfered_with_by_external_counter
119
+ assert_difference "build_monkey.counter.to_i", 1 do
120
+ increment!(:foo)
121
+ end
122
+ end
123
+
124
+ def test_increment!
125
+ a = build_monkey.number
126
+ assert_equal a+1, build_monkey.number
127
+ assert_equal a+2, increment!(:foo)
128
+ assert_equal a+3, build_monkey.number
129
+ end
130
+
131
+ def test_default_attributes_alias
132
+ hash1 = remove_variability( valid_monkey_attributes )
133
+ hash2 = remove_variability( default_monkey_attributes )
134
+ assert_equal hash1, hash2
135
+ end
136
+
137
+ protected
138
+
139
+ def remove_variability hash
140
+ variable_attributes = [:unique, :counter, :number]
141
+ returning hash do
142
+ variable_attributes.each{ |a| hash.delete(a) }
143
+ end
144
+ end
145
+
146
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/test_helper")
2
+
3
+ class FactoryWorkerTest < Test::Unit::TestCase
4
+ include FactoriesAndWorkers::Worker
5
+
6
+ factory_worker :one do
7
+ @@foo = "one!"
8
+ end
9
+
10
+ factory_worker :two => :one do
11
+ @@foo += " two!"
12
+ end
13
+
14
+ factory_worker :three do
15
+ @@foo += " three!"
16
+ end
17
+
18
+ factory_worker :count => [ :one, :two ]
19
+ factory_worker :count => [ :three ]
20
+
21
+ def test_worker
22
+ worker :one
23
+ assert_equal "one!", @@foo
24
+ end
25
+
26
+ def test_worker_with_dependencies
27
+ worker :two
28
+ assert_equal "one! two!", @@foo
29
+ end
30
+
31
+ def test_worker_with_dependencies_2
32
+ worker :count
33
+ assert_equal "one! two! three!", @@foo
34
+ end
35
+
36
+ end
@@ -0,0 +1,43 @@
1
+ $:.reject!{ |e| e.include? 'TextMate' }
2
+
3
+ require "test/unit"
4
+
5
+ plugin_root = File.join(File.dirname(__FILE__), "..")
6
+ app_root = File.join(plugin_root, "..", "..", "..")
7
+
8
+ ENV["RAILS_ENV"] = "test"
9
+
10
+ # pull in some basic Rails bits, but not our whole app, yo
11
+ require File.expand_path(File.join(app_root, "config", "boot"))
12
+ $:.unshift(File.expand_path(File.join(plugin_root, "lib")))
13
+
14
+ # initialize the plugin
15
+ require plugin_root + "/init"
16
+
17
+ # pull in just what we need from Rails
18
+ %w( active_record active_support ).each { |f| require f }
19
+
20
+
21
+ # we'll use a totally standalone db for our testing
22
+ options = { :adapter => "sqlite3", :timeout => 500, :database => ":memory:" }
23
+
24
+ # establish the connection manually
25
+ ActiveRecord::Base.establish_connection(options)
26
+
27
+ # ...and provide some connection data so that fixtures will work
28
+ ActiveRecord::Base.configurations = { :sqlite3 => options }
29
+
30
+ # kickstart
31
+ ActiveRecord::Base.connection
32
+
33
+ # create our test schema
34
+ ActiveRecord::Migration.verbose = false
35
+ require File.expand_path(File.join(plugin_root, "test", "db", "schema"))
36
+
37
+ # pull in our test AR::B models
38
+ models = Dir.glob(File.join(plugin_root, "test", "app", "models", "*.rb"))
39
+ models.each { |m| require File.expand_path(m) }
40
+
41
+
42
+ # load the factories
43
+ require File.join( plugin_root, 'test', 'factories' )
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dfl-factories-and-workers
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Nathan Herald
8
+ - David Lowenfels
9
+ - Jonathan Barket
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+
14
+ date: 2008-10-14 00:00:00 -07:00
15
+ default_executable:
16
+ dependencies: []
17
+
18
+ description: Fixtures replacement
19
+ email: david@internautdesign.com
20
+ executables: []
21
+
22
+ extensions: []
23
+
24
+ extra_rdoc_files:
25
+ - README.rdoc
26
+ files:
27
+ - README.rdoc
28
+ - CHANGELOG
29
+ - LICENSE
30
+ - init.rb
31
+ - Rakefile
32
+ - lib/factories-and-workers
33
+ - lib/factories-and-workers.rb
34
+ - lib/factories-and-workers/factory_builder.rb
35
+ - lib/factories-and-workers/factory_generator.rb
36
+ - lib/factories-and-workers/factory_worker.rb
37
+ - lib/tasks
38
+ - lib/tasks/generate_factories.rake
39
+ - rails
40
+ - rails/init.rb
41
+ - test/app
42
+ - test/app/models
43
+ - test/app/models/monkey.rb
44
+ - test/app/models/pirate.rb
45
+ - test/app/models/user.rb
46
+ - test/db
47
+ - test/db/schema.rb
48
+ - test/factories.rb
49
+ - test/factory_builder_test.rb
50
+ - test/factory_worker_test.rb
51
+ - test/test_helper.rb
52
+ has_rdoc: true
53
+ homepage: http://blog.internautdesign.com/2008/6/4/factories-and-workers-plugin
54
+ post_install_message:
55
+ rdoc_options: []
56
+
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ requirements: []
72
+
73
+ rubyforge_project:
74
+ rubygems_version: 1.2.0
75
+ signing_key:
76
+ specification_version: 2
77
+ summary: Fixtures replacement
78
+ test_files: []
79
+