@Pan Thomakos:
Your answer inspired me (so I accepted it!), But I actually created something a little different from your suggestion above. I am so pleased that I thought I would share it if it would benefit anyone else.
My model used to have this method:
def self.score dd = where( :value => -2 ).count.to_f d = where( :value => -1 ).count.to_f u = where( :value => 1 ).count.to_f uu = where( :value => 2 ).count.to_f tot = dd + d + u + uu score = (((-5*dd)+(-2*d)+(2*u)+(5*uu))/(tot+4))*20 score.round(2) end
This worked, but it requires counting votes from the database, counting votes with each possible value (-2, -1, +1, +2), and then calculating points from these values.
Since I needed to check, there was no ActiveRecord ability to find and count query results, but my algorithm for turning these counters into an estimate, I divided this into two methods, for example:
def self.score dd = where( :value => -2 ).count d = where( :value => -1 ).count u = where( :value => 1 ).count uu = where( :value => 2 ).count self.compute_score(dd,d,u,uu) end def self.compute_score(dd, d, u, uu) tot = [dd,d,u,uu].sum.to_f score = [-5*dd, -2*d, 2*u, 5*uu].sum / [tot,4].sum*20.0 score.round(2) end
So now I can just test the compute_score method without creating a bunch of fake users and fake votes to test the algorithm. My test now looks like this:
describe "score computation" do def test_score(a,b,c,d,e) Vote.compute_score(a,b,c,d).should == e end it "should be correct" do test_score(1,0,0,0,-20.0) test_score(0,1,0,0,-8.0) test_score(0,0,1,0,8.0) test_score(0,0,0,1,20.0) test_score(0,0,10,100,91.23) test_score(0,6,60,600,92.78) test_score(0,20,200,2000,93.17) end end
In my opinion, this is super legible, and if I ask RSpec for formatted output, it will read well enough for what it is testing.
I hope this technique will be useful to others!