KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Хэл Фултон - Программирование на языке Ruby

Хэл Фултон - Программирование на языке Ruby

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Хэл Фултон, "Программирование на языке Ruby" бесплатно, без регистрации.
Перейти на страницу:

Есть еще несколько утверждений, но эти применяются чаще всего и отвечают почти всем потребностям. Дополнительную информацию можно найти в онлайновой документации на сайте http://ruby-doc.org.

Имеется еще метод flunk, который всегда завершается неудачно. Можно считать, что это некий вид заглушки.

Если при запуске тестового файла вы ничего специально не указываете, то по умолчанию вызывается консольный исполнитель тестов. Это возвращает нас к старой доброй технологии 1970-х годов. Имеются и другие исполнители, например графический Test::Unit::UI::GTK::TestRunner. Любой исполнитель тестов можно вызвать, обратившись к его методу run, которому передается специальный параметр, описывающий набор тестов:

class MyTests < Test::Unit::TestCase

 # ...

end


# Явное указание исполнителя тестов...

runner = Test::Unit::UI::Console::TestRunner

runner.run(MyTests)

Параметром может быть любой объект, обладающий методом suite, который возвращает объект, представляющий комплект тестов. Что все это означает?

Познакомимся к понятием комплекта тестов ближе. Оказывается, комплект тестов может состоять из набора тестов или набора подкомплектов. Следовательно, можно сгруппировать тесты так, что будет прогоняться либо только один набор, либо сразу все.

Пусть, например, есть три набора тестов, и вы хотите прогнать их как единый комплект. Можно было бы поступить так:

require 'test/unit/testsuite'


require 'tc_set1'

require 'tc_set2'

require 'ts_set3'


class TS_MyTests

 def self.suite

  mysuite = Test::Unit::TestSuite.new

  mysuite << TC_Set1.suite

  mysuite << TC_Set2.suite

  mysuite << TS_Set3.suite

  return mysuite

 end

end


Test::Unit::UI::Console::TestRunner.run(TS_MyTests)

Но такая сложность ни к чему. Имея отдельные наборы тестов, библиотека Test::Unit в состоянии просмотреть пространство объектов и объединить их все в один комплект. Поэтому следующий код тоже будет работать (и даже вызывать подразумеваемый по умолчанию исполнитель тестов):

require 'test/unit'


require 'tc_set1'

require 'tc_set2'

require 'ts_set3'

Библиотека Test::Unit располагает и другими возможностями, а в дальнейшем, вероятно, будет усовершенствована. Самую свежую информацию ищите в сети.

16.2. Комплект инструментов ZenTest

Этот великолепный инструментарий написал Райан Дэвис (Ryan Davis). Основной инструмент (zentest) — это исполняемая программа, которая генерирует файл с тестами на основе анализа вашего кода.

Тестируемый класс (class under test — CUT) служит основой тестового класса (test class — ТС). На каждом уровне области видимости в начало имени класса добавляется строка Test, а в начало имени метода — строка test_. Иногда имена методов приходится «подправлять», например в случае с методом == (к имени которого нельзя добавлять никакой префикс) или если имя метода оканчивается на ?, ! или =. В листинге 16.2 приведен пример подлежащего тестированию кода:

Листинг 16.2. Класс, подлежащий тестированию

class Alpha


 class Beta


  attr_accessor :foo, :bar


  def initialize

  end


  def foo?

   @foo

  end


 end


 def initialize

 end


 def process

 end


 def process!

 end


 def ==(other)

 end


 def ===(other)

 end

end

После запуска команды zentest file.rb >tfile.rb получится файл, показанный в листинге 16.3.

Листинг 16.3. Результат работы ZenTest

# Code Generated by ZenTest v. 3.2.0

# classname: asrt / meth = ratio%

# Alpha::Beta: 0 / 7 = 0.00%


require 'test/unit' unless defined? $ZENTEST and $ZENTEST


class TestAlpha < Test::Unit::TestCase

 def test_process

  raise NotImplementedError, 'Need to write test_process'

 end


 def test_process_bang

  raise NotImplementedError, 'Need to write test_process_bang'

 end

end


module TestAlpha

 class TestBeta < Test::Unit::TestCase

  def test_bar

   raise NotImplementedError, 'Need to write test_bar'

  end


  def test_bar_equals

   raise NotImplementedError, 'Need to write test_bar_equals'

  end


  def test_foo

   raise NotImplementedError, 'Need to write test_foo'

  end


  def test_foo_eh

   raise NotImplementedError, 'Need to write test_foo_eh'

  end


  def test_foo_equals

   raise NotImplementedError, 'Need to write test_foo_equals'

  end

 end

end


# Number of errors detected: 9

Обратите внимание, что каждый тестовый метод возбуждает исключение (предложение raise). Идея в том, что все тесты завершаются неудачно, пока вы явно не напишете код.

Исходный файл почему-то не включается в тестовый. Можно поместить в начало тестового файла директиву require 'file' или эквивалентную ей (предварительно затребовав test/unit). Тогда тестовый код увидит определения ваших классов.

В командной строке можно указать и второй параметр. Если добавить код в тестируемый класс, то тестовые классы окажутся устаревшими. Чем обновлять их вручную, можно сгенерировать только «обновления»:

zentest file.rb tfile.rb >tfile2.rb

В комплект входит еще одна полезная программа: unit_diff. Рассмотрим простое утверждение assert_equal ("foo", "bar"). Оно приводит к печати следующего сообщения:

 1) Failure:

testme(Foo) [(irb):7]:

<"foo"> expected but was

<"bar">.

Тут все просто и понятно. Но предположим, что каждая из переданных строк (string) состояла из нескольких строчек (line), а различие начиналось только в седьмой строчке. Программа unit_diff как раз призвана навести порядок в таком плохо читаемом тексте. Она работает аналогично утилите diff, имеющейся в UNIX; вызывать ее следует как фильтр после обычной тестовой программы.

ruby testfile.rb | unit_diff

Программа понимает следующие флаги:

-h Справка о порядке запуска

-v Номер версии

-b Не считать различными фрагменты, различающиеся только по количеству

   пробелов

-c Выполнять контекстное сравнение

-k Не удалять временные файлы

-l Включать в дельту номера строк

-u Выполнять унифицированное сравнение

Программа autotest наблюдает за всеми вашими комплектами тестов и запускает те, которые были недавно изменены. Она предназначена для тех лентяев, которым трудно даже ввести имя файла для прогона тестов.

Для пользования этим инструментом нужно соблюдать некоторые соглашения об именах. Правила простые:

• все тесты должны находиться в каталоге test;

• имена всех файлов должны начинаться с Test_;

• имена классов должны начинаться с Test;

• подлежащий тестированию код должен находиться в каталоге lib;

• файлам в каталоге lib должны соответствовать файлы в каталоге test (их имена, конечно, должны начинаться с test_).

Будучи запущена, программа autotest прогоняет тесты по мере их обновления. Если какой-то тест завершается неудачно, она будет прогонять его снова и снова, пока вы не исправите ошибку. Она начнет «сверху», если нажать комбинацию клавиш Ctrl+C, и завершится, если нажать Ctrl+C во второй раз.

Программа multiruby позволяет тестировать код относительно разных версий Ruby. Она входит в комплект ZenTest, но пока еще работает не очень стабильно и плохо документирована.

16.3. Работа с отладчиком Ruby

Честно говоря, отладчик Ruby не особенно популярен. Лично я им не пользуюсь и встречал не так уж много людей, которые с ним работали. Но сознавать, что он есть, приятно. Ниже приводится краткое описание работы с ним.

Для вызова отладчика нужно просто затребовать библиотеку debug — например, в командной строке:

ruby -rdebug rayfile.rb

В ответ на приглашение вида (rdb:1) вы можете вводить различные команды, например list для получения текста всей программы или ее части, step для пошагового исполнения метода и т.д. Некоторые команды перечислены в таблице 16.1 (полужирным шрифтом набраны сокращения).


Таблица 16.1. Наиболее употребительные команды отладчика

Команда Описание break Установить точку прерывания или получить их список. delete Удалить все или некоторые точки прерывания. catch Установить точку перехвата или получить их список. step Вход внутрь метода. next Перейти к следующей строке (без захода внутрь метода). help Справка (вывести список всех команд). quit Выйти из отладчика.

В листинге 16.4 приведен код простой программы (даже слишком простой, чтобы ее отлаживать).

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*