A Reusable Builder Class for Ruby Testing

Posted by Liam McLennan on Geeks with Blogs See other posts from Geeks with Blogs or by Liam McLennan
Published on Tue, 23 Mar 2010 03:50:05 GMT Indexed on 2010/03/23 10:03 UTC
Read the original article Hit count: 551

Filed under:

My last post was about a class for building test data objects in C#. This post describes the same tool, but implemented in Ruby. The C# version was written first but I originally came up with the solution in my head using Ruby, and then I translated it to C#. The Ruby version was easier to write and is easier to use thanks to Ruby’s dynamic nature making generics unnecessary. 

Here are my example domain classes:

class Person
	attr_accessor :name, :age
	
	def initialize(name, age)
		@name = name
		@age = age
	end
	
end

class Property
	attr_accessor :street, :manager
	
	def initialize(street, manager)
		@street = street
		@manager = manager
	end
end

and the test class showing what the builder does:

class Test_Builder < Test::Unit::TestCase
	
	def setup
		@build = Builder.new	
		@build.configure({ 
			Property => lambda { Property.new '127 Creek St', @build.a(Person) },
			Person => lambda { Person.new 'Liam', 26 }			
		})
	end
	
	def test_create
		assert_not_nil @build
	end
	
	def test_can_get_a_person
		@person = @build.a(Person)
		assert_not_nil @person
		assert_equal 'Liam', @person.name
		assert_equal 26, @person.age
	end
	
	def test_can_get_a_modified_person
		@person = @build.a Person do |person|
			person.age = 999
		end
		assert_not_nil @person
		assert_equal 'Liam', @person.name
		assert_equal 999, @person.age
	end
	
	def test_can_get_a_different_type_that_depends_on_a_type_that_has_not_been_configured_yet
		@my_place = @build.a(Property)
		assert_not_nil @my_place
		assert_equal '127 Creek St', @my_place.street
		assert_equal @build.a(Person).name, @my_place.manager.name
	end
end

Finally, the implementation of Builder:

class Builder

	# defaults is a hash of Class => creation lambda
	def configure defaults
		@defaults = defaults
	end
	
	def a(klass)
		temp = @defaults[klass].call()
		yield temp if block_given?
		temp
	end

end

© Geeks with Blogs or respective owner