RSpec: СУХОЙ способ проверить набор значений - PullRequest
5 голосов
/ 03 апреля 2011

У меня есть модель vote, в которой есть метод класса с именем score. По сути, я создал математическое уравнение в электронной таблице и пытаюсь воспроизвести его в рубине. Тем не менее, моя первая попытка не работает, поэтому мне действительно нужно добавить еще несколько тестов.

Я бы хотел проверить это, взяв из моей таблицы стопку входных и выходных значений и проверив каждое из них. Таким образом, в основном, тесты могут выглядеть так:

 inputs = [a,b,c] ... score.should == x
 inputs = [a,b,c,d] ... score.should == y
 inputs = [c,d] .... score.should == z

Однако самый короткий путь, который я нашел для написания этого в RSpec, - это дать пример для каждого случая, примерно так (упрощенный пример, но должен дать вам идею):

it "should have a score of X" do
  test_object = Votable.new(...)
  @user1.vote.create(:value=>##, :votable=>test_object)
  @user2.vote.create(:value=>##, :votable=>test_object)
  @user3.vote.create(:value=>##, :votable=>test_object)
  test_object.votes.score.should == X
end

Итак, вышеприведенное работает, но это загрузка текста для каждого примера, чтобы сгладить изломы и обеспечить хорошее покрытие тестами, я хотел бы запустить около 20 или около того тестовых случаев.

Итак, серьезно, должен быть более простой способ настроить это один раз, а затем протестировать кучу возможных комбинаций ввода / вывода, верно? Кто-нибудь может предложить СУХОЙ способ сделать такой тест в RSpec?

Спасибо!

Ответы [ 2 ]

5 голосов
/ 03 апреля 2011

Да, вы можете выполнить следующее метапрограммирование, чтобы запустить серию тестов в одном формате:

results = { x: ['a', 'b', 'c'], y: ['a','b','c','d'] }

results.each do |score, values|
  it "should have a score of #{score}" do
    test_object = Votable.new(...)
    values.each do |value|
      User.create(...).vote.create(value: value, votable: test_object)
    end
    test_object.votes.score.should == score
  end
end
0 голосов
/ 03 апреля 2011

@ Пан Томакос:

Ваш ответ вдохновил меня (поэтому я принял это!), Но на самом деле я создал что-то немного другое, вдохновленное вашим предложением выше.Я так доволен этим, что подумаю, что поделюсь этим, если это кому-нибудь пригодится.

Ранее в моей модели был такой метод:

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

Это сработало, но требует подсчетаголосов из базы данных, видя подсчет голосов с каждым возможным значением (-2, -1, +1, +2), а затем вычисляя счет по этим подсчетам.

Поскольку то, что мне нужно было проверить, не былоСпособность ActiveRecord находить и подсчитывать результаты запроса, но мой алгоритм преобразования этих подсчетов в счет я разделил на два метода, например так:

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

Так что теперь я могу просто протестировать метод compute_scoreбез необходимости создавать кучу фальшивых пользователей и фальшивых голосов для проверки алгоритма.Мой тест теперь выглядит следующим образом:

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

По моему мнению, это супер разборчиво, и если я спрашиваю RSpec для форматированного вывода, он читается достаточно хорошо для того, что он тестирует.

Надеюсь, этот методбудет полезен другим!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...