def number_decomposition(number)
numl, num2 = number/2, number/2
while numl > 1 and num2 < number if prime?(num1) and prime?(num2)
return numl, num2
end
numl -= 1 num2 += 1 end
return nil end
if __FILE__ == $0
p number_decomposition(142)
end
Метод number_decomposition использует рассмотренный (стр. 10) нами ранее метод prime? (проверка числа на простоту).
Исходная программа была подготовлена к процессу тестирования. Метод number_decomposition возвращает полученный результат (вместо печати, который мы будем сравнивать с набором подготовленных шаблонов). Тело условного оператора в конце программы будет выполнено только в случае, если интерпретатору на выполнение будет передан данный файл с программой, при подключении этого файла командой require условие __FILE__ == $0 будет ложно.
Для тестирования создадим подкласс базовой библиотеки тестирования. Обратите внимание на стили наименований: имя такого класса должно начинаться с префикса Test, а имена тестирующих методов – с лексемы test. Каждый тест содержит набор сравнений – специальных функций, имя которых начинается со слова assert.
Метод assert получает два аргумента (второй – необязательный): логическое выражение и текстовое сообщение. Если логическое выражение окажется ложно, то программа добавит 1 к числу неуспешных проверок и выведет сообщение о неудаче. Кроме этого, будет напечатано текстовое сообщение, переданное методу в качестве второго аргумента. Метод assert_equal получает три аргумента (третий – необязательный): ожидаемое значение, сравниваемое значение (как правило результат работы тестируемой функции) и сообщение, которое будет выведено при несовпадении первого и второго аргументов. Метод assert_nil проверяет, является ли аргумент объектом nil.
# подключение библиотеки тестирования require "test/unit"
# подключение файла с программой require "number_decomposition4test.rb"
class TestNumberDecomposition < Test::Unit::TestCase def setup
# набор начальных действий выполняемых
# перед запуском каждого тестового случая. end
# проверка работоспособности функции prime? def test_prime?
assert(false == prime?(1)) assert false == prime?(10)
assert_equal(true, prime?(2), "Ошибка при проверке числа 2") assert_equal true, prime?(7), "Ошибка при проверке числа 7" assert_equal(true, prime?(103)) end
def test_number_decomposition
assert_nil(number_decomposition(2)) assert_equal([5, 5], number_decomposition(10)) assert_equal [7, 11], number_decomposition(18) assert_equal [97, 103], number_decomposition(200) end end
Вы можете добавлять в класс вспомогательные методы и использовать их в тестовых случаях, но только методы, начинающиеся с test, будут запущены во время выполнения теста! Тесты вызываются в том порядке, в котором они представлены в программе. Если в тестирующем классе присутствуют методы с именами setup и (или) teardown, то они будут выполнены соответственно перед запуском всех тестов и после их завершения.
Очень полезно писать тесты до начала программирования.
Посмотрим на результат работы данной программы. Его можно интерпретировать таким образом. Выполнено 2 теста (tests) и 9 сравнений (assertions). Обнаружено 0 сбоев (failures) и 0 ошибок (errors). Это означает, что программа теоретически работает и, наверное, все в порядке.
$ ruby test_number_decomposition.rb Loaded suite test_number_decomposition Started
Finished in 0.003189 seconds.
2 tests, 9 assertions, 0 failures, 0 errors $
Ради эксперимента искусственно внесем ошибку в метод prime?, сделав так, чтобы он считал единицу простым числом.
Запуск теста моментально обнаруживает ошибку, показав место, где произошел сбой – седьмую строку с выражением assert false == prime?(1) (отметим, что количество сбоев стало равным одному). Изучив тестовый случай, можно понять, где произошла ошибка и в чем причина. Теперь выполнять тесты стало очень легко.
$ ruby test_number_decomposition.rb Loaded suite test_number_decomposition Started.F
Finished in 0.061807 seconds.
1) Failure:
test_prime? (TestNumDecomposition) [test_number_decomposition.rb:7]: <false> is not true.
2 tests, 5 assertions, 1 failures, 0 errors $
Когда требуется ввести в программу новую функцию, начните с создания теста. Это не так странно, как может показаться. Когда вы пишите тест, то спрашиваете себя, что нужно сделать для добавления этой функции и как она должна работать.
3.2 Обработка исключительных ситуаций.
В большинстве современных языков программирования предусмотрена возможность работы с исключительными (особыми) ситуациями. В языке Ruby программисты могут работать как со встроенными ситуациями, так и с ситуациями, создаваемыми по указанию программиста при наличии того или иного события. Типичные встроенные ситуации – это «деление на ноль» (ZeroDivisionError) или «достижение конца файла» (EOFError).