Manfred Stienstra,
29 Apr 2008, 12:14 in testing (edit).
Have you ever wanted to test multiple writes to $stderr? Mocking frameworks aren’t good at that, instead you can write a simple class to record method calls.
class Receptor
require 'singleton'
include Singleton
attr_accessor :messages
def initialize
@messages = []
end
def method_missing(*attrs)
self.messages << attrs
end
end
$stderr = Receptor.instance
And in your tests:
messages = Receptor.instance.messages
assert messages.include?(['puts', "[!] Error!"])
assert messages.include?(['puts', "[?] Couldn't find preferences file."])
Norbert Crombach,
17 Jul 2007, 08:26 in ruby on rails, testing, and broken (edit).
For those of you on Edge Rails, since changeset [7189] appears to have broken the current acts_as_paranoid we’ve been getting some test errors. There’s a quick patch I wrote available in this Pastie, but because scope_out is now recommended by Rick Olson himself this should only be seen as a migration path. Hopefully this will save you some trouble.
Manfred Stienstra,
03 May 2007, 17:40 in ruby on rails and testing (edit).
We had a little Code to Test Ratio showdown at the office today, probably because there was a woman present. It got me wondering what the Code to Test Ratio for other people is. So everybody, please post the CTTR of your current project in the comments.
Note: in Rails you can find your CTTR with rake stats.
Manfred Stienstra,
26 Apr 2007, 10:56 in ruby on rails and testing (edit).
When you’re testing uploads with attachment_fu, your files end up in RAILS_ROOT/public by default. This is not very handy because they might override your carefully uploaded bunny pictures in development. You can easily solve this by overriding the full_filename method on your attachment model. Let’s assume you have something like this.
class Asset < ActiveRecord::Base
belongs_to :post
has_attachment :content_type => :image, :storage => :file_system
end
Then you can add the following to the file your tests are defined in:
class Asset
def full_filename(thumbnail = nil)
file_system_path = (thumbnail ? thumbnail_class : self).attachment_options[:path_prefix].to_s
File.join(Dir::tmpdir(), file_system_path, *partitioned_path(thumbnail_name_for(thumbnail)))
end
end
This will make your files get written to /tmp/public. If you have multiple tests that have to override the attachment class, it’s probably best to put it in a separate file.
Manfred Stienstra,
07 Mar 2007, 15:53 in ruby on rails and testing (edit).
As you may have noticed OpenStruct#id always returns the object id of the OpenStruct instance, even when you set id.
>> o = OpenStruct.new :id => 2
=> #<OpenStruct id=2>
>> o.id
(irb):4: warning: Object#id will be deprecated; use Object#object_id
=> 9850940
Fortunately there is a simple way around this.
OpenStruct.__send__(:define_method, :id) { @table[:id] }
Now OpenStruct behaves like we want.
>> o.id
=> 2
Note that hash and object_id still work fine. You probably want to keep in mind that we’ve redefined the default OpenStruct behaviour and it might cause problems elsewhere.
Manfred Stienstra,
02 Feb 2006, 13:58 in ruby on rails and testing (edit).
In the past I usually tested the feeds a Rails application generated by writing a functional test that checked the HTTP status code and matched certain strings in the feed using a regular expression. If that checked out I hand-tested the feed using the online feedvalidator. Needless to say, this became very cumbersome after a few times, especially for one of our projects that generates a whole list of different feeds depending on the state of the account. Time to add validation to the functional tests.
Unfortunately the feedvalidator is (not yet) written in Ruby, so we have to do system calls to a python script to validate. I installed the feedvalidator in the script directory, which looked like the correct place to put this. A protected method on the testcase makes sure we can easily test feeds.
def validate_feed(content)
validate = File.dirname(__FILE__) + '/../../script/feedvalidator/validate.py'
path = Pathname.new(File.dirname(__FILE__) + '/../tmp')
Tempfile.open('feed', path.cleanpath) do |tmpfile|
tmpfile.write(content)
tmpfile.flush
result = `#{validate} #{tmpfile.path} A`
unless result =~ /No errors or warnings/
raise "Feed did not validate: #{result}"
end
end
end
So now the testcases looks like this:
def test_atom
get :atom
validate_feed @response.body
assert_equal 'application/atom+xml', @response.headers['Content-Type']
end
Note that this validates the feeds on level ‘A’ which only tests for MUST directives. For completeness you should probably still test either with the online validator or temporarily set the validation to ‘AA’ or even ‘AAA’.
Rumor has it that if you validate your feeds at ‘AAA’ level Mark Pilgrim will come to your house and crown you Prins of the Feeds. Lucky lucky!
Manfred Stienstra,
09 Dec 2005, 10:55 in ruby on rails and testing (edit).
Test are supposed to be run often, but they only get run if they’re easy to run. When you create a plugin in your Ruby on Rails project, it doens’t get run by default.
And that’s not very easy now, is it? Fortunately there is a standard task to run the plugin tests, which is called `test_plugins’. How do we get this task to run all the time?
RoR allows us to specify our own tasks in /lib/tasks, so we’re going to add a file called `test_plugins_by_default.rake’ to this directory, and we put the following in the file:
desc "Run test:plugins by default."
task :default do
namespace 'test' do
Rake::Task[:plugins].invoke
end
end
Very well sir, but why does this work? The Rake User Guide tells us that a task that is declared multiple times, cumulatively adds it’s actions to the task. So ‘test_plugins’ will now be run in the default task.