Hi all, I was wondering about the class used when rails receives file uploads. Sometimes it appears to be a File, and other times it is a StringIO. Also it has methods such as original_filename that don''t appear to belong to either of these classes. I ask because I''m trying to work out how to test my fil upload related models and controllers. Is there some standardised way of creating a file upload mock object? Many thanks in advance. CHEERS> SAM
On Fri, Jan 06, 2006 at 04:20:00AM +0900, Sam Joseph wrote:> I was wondering about the class used when rails receives file uploads. > Sometimes it appears to be a File, and other times it is a StringIO. > Also it has methods such as original_filename that don''t appear to > belong to either of these classes. I ask because I''m trying to work out > how to test my fil upload related models and controllers. > > Is there some standardised way of creating a file upload mock object? > > Many thanks in advance.Here''s some code for testing file uploads. This has some bits that are specific to the implementation so you can''t just copy and paste this wholesale and expect it to work but perhaps it can provide some direction. In the test_helper.rb: module UploadedFile attr_accessor :original_filename, :content_type end def uploaded_file(contents, name, content_type) io = StringIO.new(contents) io.extend UploadedFile io.original_filename = name io.content_type = content_type io end def empty_trash! FileUtils.rm_rf(Dir["#{Upload.upload_root}/*"]) end def file_uploaded?(file_name) File.exists?(uploaded_file_path(file_name)) end def assert_file_uploaded(file_name) assert file_uploaded?(file_name) end def assert_file_not_uploaded(file_name) assert !file_uploaded?(file_name) end def assert_upload_equals(contents, file_name) assert_file_uploaded file_name assert_equal contents, IO.read(uploaded_file_path(file_name)) end def uploaded_file_path(file_name) namespace = Upload.namespace_directories(@controller.send(:account).id) File.join(Upload.upload_root, namespace, file_name) end The functional tests look something like this: def teardown empty_trash! end def test_basic_upload assert_difference_in_size(Upload) do upload = uploaded_file(''Rock out!'', ''nsync.mp3'', ''audio/mpg'') post :new, :upload => upload assert_file_uploaded ''nsync.mp3'' assert_not_nil assigns(:upload).upload_message end end def test_all_upload_metadata_set upload = uploaded_file(''La la la'', ''jason-in-shower.mp3'', ''audio/mpg'') post :new, :upload => upload record = assigns(:upload) assert_equal ''La la la''.size, record.byte_size assert_equal ''audio/mpg'', record.content_type assert_equal ''jason-in-shower.mp3'', record.name end And finally, though not central to testing the uploading specifically, here is assert_difference_in_size (which I pretty much use all the time everywhere): def assert_difference_in_size(object, methods = nil, difference = 1) methods ||= :count apply = Proc.new {|obj, methods| [*methods].inject(object) {|result, method| result.send(method)} } initial_value = apply.call(object, methods) yield assert_equal initial_value + difference, apply.call(object, methods) end def assert_no_difference_in_size(object, methods = nil, &block) assert_difference_in_size object, methods, 0, &block end Quack! marcel -- Marcel Molina Jr. <marcel@vernix.org>
Hi Marcel, Thanks - this is very helpful. I also wonder is this the way that rails itself handles incoming files, i.e. it takes a StringIO or File object and uses the extend operation to add meta-data? CHEERS> SAM Marcel Molina Jr. wrote:>On Fri, Jan 06, 2006 at 04:20:00AM +0900, Sam Joseph wrote: > > >Here''s some code for testing file uploads. This has some bits that are specific >to the implementation so you can''t just copy and paste this wholesale and >expect it to work but perhaps it can provide some direction. > >In the test_helper.rb: > > module UploadedFile > attr_accessor :original_filename, :content_type > end > > def uploaded_file(contents, name, content_type) > io = StringIO.new(contents) > io.extend UploadedFile > io.original_filename = name > io.content_type = content_type > io > end > > def empty_trash! > FileUtils.rm_rf(Dir["#{Upload.upload_root}/*"]) > end > > def file_uploaded?(file_name) > File.exists?(uploaded_file_path(file_name)) > end > > def assert_file_uploaded(file_name) > assert file_uploaded?(file_name) > end > > def assert_file_not_uploaded(file_name) > assert !file_uploaded?(file_name) > end > > def assert_upload_equals(contents, file_name) > assert_file_uploaded file_name > assert_equal contents, IO.read(uploaded_file_path(file_name)) > end > > def uploaded_file_path(file_name) > namespace = Upload.namespace_directories(@controller.send(:account).id) > File.join(Upload.upload_root, namespace, file_name) > end > >The functional tests look something like this: > > def teardown > empty_trash! > end > > def test_basic_upload > assert_difference_in_size(Upload) do > upload = uploaded_file(''Rock out!'', ''nsync.mp3'', ''audio/mpg'') > post :new, :upload => upload > assert_file_uploaded ''nsync.mp3'' > assert_not_nil assigns(:upload).upload_message > end > end > > def test_all_upload_metadata_set > upload = uploaded_file(''La la la'', ''jason-in-shower.mp3'', ''audio/mpg'') > post :new, :upload => upload > record = assigns(:upload) > assert_equal ''La la la''.size, record.byte_size > assert_equal ''audio/mpg'', record.content_type > assert_equal ''jason-in-shower.mp3'', record.name > end > >And finally, though not central to testing the uploading specifically, here is >assert_difference_in_size (which I pretty much use all the time everywhere): > > def assert_difference_in_size(object, methods = nil, difference = 1) > methods ||= :count > apply = Proc.new {|obj, methods| > [*methods].inject(object) {|result, method| result.send(method)} > } > initial_value = apply.call(object, methods) > yield > assert_equal initial_value + difference, apply.call(object, methods) > end > > def assert_no_difference_in_size(object, methods = nil, &block) > assert_difference_in_size object, methods, 0, &block > end > >Quack! >marcel > >
On Sun, Jan 08, 2006 at 08:18:38AM +0900, Sam Joseph wrote:> I also wonder is this the way that rails itself handles incoming files, > i.e. it takes a StringIO or File object and uses the extend operation to > add meta-data?Rails isn''t responsible for any of this actually. It is ruby''s cgi.rb that handles file uploads and creating an IO object with metadata. marcel -- Marcel Molina Jr. <marcel@vernix.org>
On Fri, Jan 06, 2006 at 04:20:00AM +0900, Sam Joseph wrote:> Hi all, > > I was wondering about the class used when rails receives file uploads. > Sometimes it appears to be a File, and other times it is a StringIO. > Also it has methods such as original_filename that don''t appear to > belong to either of these classes. I ask because I''m trying to work out > how to test my fil upload related models and controllers. > > Is there some standardised way of creating a file upload mock object? > > Many thanks in advance. > > CHEERS> SAMI do some basic file upload testing with this set up: http://rubyi.st/show/9 YMMV, of course, depending on the complexity you need. -Scott
Possibly Parallel Threads
- [LLVMdev] Interfacing llvm with a precise, relocating GC
- [LLVMdev] Interfacing llvm with a precise, relocating GC
- [LLVMdev] Interfacing llvm with a precise, relocating GC
- [LLVMdev] Interfacing llvm with a precise, relocating GC
- [LLVMdev] Interfacing llvm with a precise, relocating GC