Эквивалентен nUnit TestCase в Ruby 1.9.2 Test :: Unit - PullRequest
2 голосов
/ 06 апреля 2011

Когда я решил изучить Ruby некоторое время назад, я также решил, что начну использовать модульные тесты и методологию TDD. Я начал использовать Test :: Unit и написал пару очень маленьких классов, чтобы почувствовать модульное тестирование в целом и Ruby и Test :: Unit в частности.

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

Код выглядит так:

def test_2_inserted_return_true
    actual = @prime_generator.is_prime?(2)
    assert_equal(true, actual)
  end

  def test_3_inserted_return_true
      actual = @prime_generator.is_prime?(3)
      assert_equal(true, actual)
    end

  def test_5_inserted_return_true
    actual = @prime_generator.is_prime?(5)
    assert_equal(true, actual)
  end

Что довольно ужасно с СУХОЙ точки зрения. То, что я хотел бы, это что-то похожее на TestCase nUnit.

Примерно так:

[TestCase(2.5d, 2d, Result=1.25d)]
[TestCase(-2.5d, 1d, Result = -2.5d)]
public double ValidateDivision(double numerator, double denominator)
{
    var myClass = new MyClass();
    return myClass.Divide(numerator,denominator);
}

Я пробовал поискать в Google, но не смог найти ничего о Test :: Unit. Я нашел некоторые на RSpec и Selenium, но это мне не очень помогает. Я тоже попытался поискать здесь, но ничего не смог найти.

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

Итак, мой вопрос: возможно ли провести управляемое данными тестирование с помощью Test :: Unit в Ruby (1.9.2)? Если нет, то какие фреймворки могут это сделать?

Ответы [ 3 ]

4 голосов
/ 06 апреля 2011

Давайте не будем забывать о хороших старых циклах:

def test_that_the_first_few_primes_are_detected_as_prime
  [2, 3, 5, 7, 11, 13, 17].each do |p|
    assert @primality_tester.prime?(p)
  end
end

Некоторые люди используют метапрограммирование для определения отдельных методов тестирования, но в этом случае я думаю, что это излишне:

[2, 3, 5, 7, 11, 13, 17].each do |p|
  define_method :"test_that_#{p}_is_detected_as_prime" do
    assert @primality_tester.prime?(p)
  end
end

Вообще, я не думаю, что тесты должны быть сухими.Они должны быть DAMP (описательные и значимые фразы).В конце концов, тесты - это ваша спецификация и ваша документация, и их читают люди, которые могут быть не знакомы с Ruby или вообще с программированием.Поэтому я даже не уверен, что ваш исходный пример плох, особенно если вы немного очистите его, как я делал выше:

def test_that_2_is_detected_as_prime
  assert @primality_tester.prime?(2)
end

def test_that_3_is_detected_as_prime
  assert @primality_tester.prime?(3)
end

def test_that_5_is_detected_as_prime
  assert @primality_tester.prime?(5)
end

Вот что я сделал:

  • Переименуйте тесты: теперь имя теста формирует законченное предложение, и оно не просто повторяет то, что делает тест.
  • Используйте assert вместо assert_equal: проверка на равенство trueв любом случае почти никогда не бывает хорошей идеей, и assert уже проверяет, что результат правдив, так зачем беспокоиться?
  • Переименовать @prime_generator в @primality_tester, поскольку, ну, это не генерирует простые числа , он только проверяет, является ли число простым.
  • Переименуйте is_prime? в prime?, поскольку вопрос уже подразумевается под знаком вопроса
  • И последнее, но не менее важное: исправьте форматирование, поскольку форматирование не только несовместимо со стандартными соглашениями о кодировании Ruby, но даже не согласуется с самими

Тем не менее, лучшее решение IMO будет выглядеть примерно так:

def test_that_the_first_few_primes_are_detected_as_prime
  assert @primality_tester.prime?(2)
  assert @primality_tester.prime?(3)
  assert @primality_tester.prime?(5)
end

Там есть дублирование, но именно дублирование необходимо для того, чтобы тест был читабельным и произносимым.DRY - хороший принцип для производственного кода, который развивается и расширяется, но для тестов DRY всегда должен быть сбалансирован с DAMP.(Возможно, имеет смысл написать собственное утверждение, но я сомневаюсь в этом. По крайней мере, я не могу придумать хорошее название для него, которое всегда является подсказкой.)

Полностью другой подход будет основываться на проверке свойств, подобный QuickCheck Haskell или Pex .NET.Имеется порт QuickCheck для Ruby, который называется RushCheck , но он не поддерживается с 2006 года, и обслуживание ушло всего пару недель назад, и еще предстоит проделать большую работу, чтобы ускорить его в последние годы.версии Ruby.

2 голосов
/ 07 апреля 2011

Вы должны проверить rspec для модульного тестирования:

require 'prime'

describe "Numbers List" do
  [2, 3, 5, 7, 11, 13, 17].each do |i|
    it "#{i} is prime" do
      i.prime?
    end
  end
end

текущий урожай:

scratch-1.9.2> rspec -cfn primes.rb 

Numbers List
  2 is prime
  3 is prime
  5 is prime
  7 is prime
  11 is prime
  13 is prime
  17 is prime

Finished in 0.00146 seconds
7 examples, 0 failures
0 голосов
/ 15 мая 2013

Я сделал это с помощью метапрограммирования, используя несколько примеров, которые я нашел в блоге Джея Филдса.Работал отлично, но вызов def_each должен был быть сделан в качестве первой строки моего файла тестового примера.Надеюсь, этот пример кому-нибудь поможет, хотелось бы увидеть этот ответ, но узнать о define_method было довольно круто:)

def self.def_each(method_names, &block)
 method_names.each do |method_name|
  method_name_fixed="test_"+method_name     
  define_method method_name_fixed do
    instance_exec method_name, &block
   end
 end
end

@@servers = ["pixeltmp01.fetchback.com","pixeltmp02.fetchback.com","pixeltmp03.fetchback.com"]

# generate test methods using fixtures and any other testcase-specific data
def_each @@servers do |method_name|
 @fb.withPixelServer(method_name)
 self.LandingPixelM
end
...