Прежде чем продолжить, давайте кратко рассмотрим несколько определений —
-
Тесты — это тестовые приложения, которые дают согласованный результат и доказывают, что приложение Rails делает то, что от него ожидается. Тесты разрабатываются одновременно с фактическим применением.
-
Утверждение — это одна строка кода, которая оценивает объект (или выражение) для ожидаемых результатов. Например — это значение = это значение? Это объект ноль?
-
Тестовый пример — это класс, унаследованный от Test :: Unit :: TestCase, содержащий стратегию тестирования , состоящую из контекстно-связанных тестов.
-
Набор тестов — это набор тестов. Когда вы запускаете набор тестов, он, в свою очередь, выполняет каждый принадлежащий ему тест.
Тесты — это тестовые приложения, которые дают согласованный результат и доказывают, что приложение Rails делает то, что от него ожидается. Тесты разрабатываются одновременно с фактическим применением.
Утверждение — это одна строка кода, которая оценивает объект (или выражение) для ожидаемых результатов. Например — это значение = это значение? Это объект ноль?
Тестовый пример — это класс, унаследованный от Test :: Unit :: TestCase, содержащий стратегию тестирования , состоящую из контекстно-связанных тестов.
Набор тестов — это набор тестов. Когда вы запускаете набор тестов, он, в свою очередь, выполняет каждый принадлежащий ему тест.
Рельсы Тестирование
Когда вы запускаете скрипт сценария помощника / generate для создания контроллеров и моделей , Rails генерирует среду для модульных и функциональных тестов. Вы можете получить довольно хорошее тестовое покрытие, заполнив фреймворк тестами для написанной вами функциональности. Есть два важных момента для тестирования в приложении Rails:
-
Тестирование моделей
-
Тестирование контроллеров
Тестирование моделей
Тестирование контроллеров
Этот урок кратко охватит оба тестирования. Итак, давайте создадим один testapp, чтобы понять концепцию.
C:\ruby> rails -d mysql testapp
Настройка базы данных
До сих пор мы использовали только базу данных разработки приложения Rails, но теперь вам нужно убедиться, что тестовая база данных также создана и соответствующие разделы вашего файла config / database.yml настроены правильно.
Давайте создадим базы данных для разработки и тестирования следующим образом:
mysql> create database testapp_test; Query OK, 1 row affected (0.01 sec) mysql> create database testapp_development; Query OK, 1 row affected (0.01 sec) mysql> use testapp_test; Database changed mysql> grant all privileges on testapp_test.* to 'root'@'localhost' identified by 'password'; Query OK, 0 rows affected (0.00 sec) mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec)
Конфигурирование database.yml
Настройте ваш config / database.yml следующим образом:
development: adapter: mysql encoding: utf8 database: testapp_development username: root password: password host: localhost test: adapter: mysql encoding: utf8 database: testapp_test username: root password: password host: localhost production: adapter: mysql encoding: utf8 database: testapp_production username: root password: password host: localhost
Генерация миграции
Предположим, у вас есть таблица, содержащая книги, включая их названия, цену и небольшое описание. Следующая миграция устанавливает эту таблицу —
testapp > ruby script/generate migration books
Теперь измените файл testapp / db / migrate / 20080616170315_books.rb следующим образом:
class Books < ActiveRecord::Migration def self.up create_table :books do |t| t.string :title, :limit => 32, :null => false t.float :price t.text :description t.timestamp :created_at end end def self.down drop_table :books end end
Теперь запустите миграцию следующим образом:
testapp > rake db:migrate
Это создаст таблицу книг в базе данных testapp_development. После этого нам нужно настроить тестовую базу данных с помощью команды rake следующим образом:
C:\ruby\testapp > rake db:test:clone_structure
Это клонирует базу данных testapp_development в базу данных testapp_test . Это означает, что все, что у вас есть в базе данных разработки, теперь у вас будут те же данные в тестовой базе данных.
Модели тестирования
Когда вы генерируете модель с помощью скрипта генерирования, Rails также генерирует скрипт модульного теста для модели в тестовом каталоге. Он также создает прибор , файл YAML, содержащий тестовые данные для загрузки в базу данных testapp_test. Это данные, по которым будут выполняться ваши юнит-тесты —
testapp > ruby script/generate model Book exists app/models/ exists test/unit/ exists test/fixtures/ create app/models/book.rb create test/unit/book_test.rb create test/fixtures/books.yml create db/migrate create db/migrate/20080616164236_create_books.rb
Когда вы пишете код в классах моделей, вы будете писать соответствующие тесты в этих файлах. Итак, давайте создадим две записи тестовой книги с использованием YAML в test / fixtures / books.yml следующим образом:
perl_cb: id: 1 title: 'Ruby Tutorial' price: 102.00 description : 'This is a nice Ruby tutorial' java_cb: id: 2 title: 'Java Programming' price: 62.00 description : 'Java Programming for the beginners'
Теперь давайте заменим существующий код в файле юнит-теста книги test / unit / book_test.rb следующим кодом —
require File.dirname(__FILE__) + '/../test_helper' class BookTest < ActiveSupport::TestCase fixtures :books def test_book perl_book = Book.new :title => books(:perl_cb).title, :price => books(:perl_cb).price, :description => books(:perl_cb).description, :created_at => books(:perl_cb).created_at assert perl_book.save perl_book_copy = Book.find(perl_book.id) assert_equal perl_book.title, perl_book_copy.title perl_book.title = "Ruby Tutorial" assert perl_book.save assert perl_book.destroy end end
Наконец, запустите метод теста следующим образом —
testapp > ruby test/unit/book_test.rb
Вот результат запуска успешного теста —
testapp > ruby test/unit/book_test_crud.rb Loaded suite ./test/unit/book_test Started . Finished in 0.0625 seconds. 1 tests, 4 assertions, 0 failures, 0 errors
Давайте проанализируем, что здесь произошло —
-
Метод BookTest начинается с создания нового объекта Book с использованием заголовка и других полей из первой записи в тексте fixture / books.yml. Полученный объект сохраняется в переменной экземпляра perl_book.
-
Первое утверждение проверяет, что сохранение объекта Book прошло успешно.
-
Затем объект book извлекается с использованием метода find и сохраняется в другой переменной экземпляра с именем perl_book_copy. Успешность этого поиска проверяется в следующем утверждении, в котором сравниваются заголовки обоих объектов книги. На данный момент мы проверили способность создавать и читать записи в базе данных.
-
Решение проверяет обновление, назначая новый заголовок объекту, сохраненному в perl_book, и затем подтверждает, что сохранение изменения прошло успешно.
-
Наконец, способность уничтожать объект Book проверяется.
Метод BookTest начинается с создания нового объекта Book с использованием заголовка и других полей из первой записи в тексте fixture / books.yml. Полученный объект сохраняется в переменной экземпляра perl_book.
Первое утверждение проверяет, что сохранение объекта Book прошло успешно.
Затем объект book извлекается с использованием метода find и сохраняется в другой переменной экземпляра с именем perl_book_copy. Успешность этого поиска проверяется в следующем утверждении, в котором сравниваются заголовки обоих объектов книги. На данный момент мы проверили способность создавать и читать записи в базе данных.
Решение проверяет обновление, назначая новый заголовок объекту, сохраненному в perl_book, и затем подтверждает, что сохранение изменения прошло успешно.
Наконец, способность уничтожать объект Book проверяется.
Вот как мы можем протестировать наши модели Rails.
Тестирование контроллеров
Тестирование контроллера также называется функциональным тестированием . Функциональное тестирование тестирует следующие типы функций контроллеров —
- Ответ перенаправлен как ожидалось?
- Предполагаемый шаблон отображается?
- Является ли маршрутизация ожидаемой?
- Содержит ли ответ ожидаемые теги?
Rails Framework поддерживает пять типов запросов —
- получить
- сообщение
- положил
- голова
- удалять
Чтобы написать функциональный тест, вам нужно смоделировать любой из пяти типов HTTP-запросов, которые будет обрабатывать ваш контроллер.
Тип запроса «get» и «post» наиболее часто используются при тестировании контроллера. Все эти методы принимают четыре аргумента —
- Действие контроллера
- Необязательный хэш параметров запроса
- Необязательный хэш сессии
- Дополнительный флэш-хэш
В этом уроке мы увидим, как использовать метод get для тестирования нашего контроллера. Вы можете проверить остальные методы аналогичным образом.
Когда вы генерируете контроллер с помощью generate, Rails создает скрипт функционального теста для контроллера следующим образом:
testapp > ruby script/generate controller Book exists app/controllers/ exists app/helpers/ create app/views/book exists test/functional/ create app/controllers/book_controller.rb create test/functional/book_controller_test.rb create app/helpers/book_helper.rb
Когда вы пишете код в классах контроллера, вы будете писать соответствующие тесты в этих файлах. Перед этим давайте определим наш список функций контроллера , покажем и ищем внутри app / controllers / book_controller.rb следующим образом:
class BookController < ApplicationController def list @book_pages, @books = paginate :books, :per_page => 10 end def show @book = Book.find(params[:id]) end def search @book = Book.find_by_title(params[:title]) if @book redirect_to :action => 'show', :id => @book.id else flash[:error] = 'No such book available' redirect_to :action => 'list' end end end
ПРИМЕЧАНИЕ. — Вам потребуется два шаблона представлений для метода показа и списка . Вы можете определить эти представления и протестировать их, но сейчас мы продолжим без определения этих представлений.
Теперь давайте повторно используем наш тестовый прибор, который находится в файле test / fixtures / books.yml, следующим образом:
perl_cb: id: 1 title: 'Ruby Tutorial' price: 102.00 description : 'This is a nice Ruby tutorial' java_cb: id: 2 title: 'Java Programming' price: 62.00 description : 'Java Programming for the beginners'
Добавьте следующие методы test_search_book и test_search_not_found в test / functions / book_controller_test.rb, чтобы проверить функциональность поискового действия контроллера книги.
require File.dirname(__FILE__) + '/../test_helper' require 'book_controller' # Re-raise errors caught by the controller. class BookController def rescue_action(e) raise e end end class BookControllerTest < Test::Unit::TestCase fixtures :books def setup @controller = BookController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new end def test_search_book get :search, :title => 'Ruby Tutorial' assert_not_nil assigns(:book) assert_equal books(:perl_cb).title, assigns(:book).title assert_valid assigns(:book) assert_redirected_to :action => 'show' end def test_search_not_found get :search, :title => 'HTML Tutorial' assert_redirected_to :action => 'list' assert_equal 'No such book available', flash[:error] end end
Теперь запустите ваши тесты следующим образом:
testapp > ruby test/functional/book_controller_test.rb
Это дает следующий вывод —
Loaded suite test/functional/book_controller_test Started .. Finished in 0.422 seconds. 2 tests, 7 assertions, 0 failures, 0 errors
Давайте проанализируем, что здесь произошло —
-
Метод настройки является методом по умолчанию для создания объектов контроллера, запроса и ответа. Они будут использоваться Rails внутри страны.
-
Первый тестовый метод test_search_book генерирует запрос get для действия поиска, передавая параметр title .
-
Следующие два утверждения подтверждают, что объект Book был сохранен в переменной экземпляра с именем @book и что объект проходит любые проверки Active Record, которые могут существовать.
-
Последнее утверждение в первом методе проверяет, что запрос был перенаправлен в действие show контроллера.
-
Второй метод test, test_search_not_found , выполняет еще один запрос get, но передает неверный заголовок
-
Первое утверждение проверяет, что было выполнено перенаправление на действие списка .
-
Если исходящие утверждения пройдены, во флэш- хэше должно быть сообщение, которое вы можете проверить с помощью assert_equal.
Метод настройки является методом по умолчанию для создания объектов контроллера, запроса и ответа. Они будут использоваться Rails внутри страны.
Первый тестовый метод test_search_book генерирует запрос get для действия поиска, передавая параметр title .
Следующие два утверждения подтверждают, что объект Book был сохранен в переменной экземпляра с именем @book и что объект проходит любые проверки Active Record, которые могут существовать.
Последнее утверждение в первом методе проверяет, что запрос был перенаправлен в действие show контроллера.
Второй метод test, test_search_not_found , выполняет еще один запрос get, но передает неверный заголовок
Первое утверждение проверяет, что было выполнено перенаправление на действие списка .
Если исходящие утверждения пройдены, во флэш- хэше должно быть сообщение, которое вы можете проверить с помощью assert_equal.
Чтобы получить больше информации об утверждениях, обратитесь к стандартной документации Rails .
Использование Rake для тестирования
Вы можете использовать утилиту rake для тестирования ваших приложений. Ниже приведен список нескольких важных команд.
$ rake test — тестирует все модульные и функциональные тесты (и интеграционные тесты, если они существуют).
$ rake test: functionals — Запустить все функциональные тесты.
$ rake test: units — Запустить все модульные тесты.
$ rake test: интеграция — запустить все интеграционные тесты.
$ rake test: plugins — Запустите все тесты в ./vendor/plugins/**/test.
$ rake test: недавно — запустить тесты для моделей и контроллеров, которые были изменены за последние 10 минут —
$ rake test: uncommitted — для проектов в Subversion запустите тесты на изменения, которые произошли в моделях и контроллерах с момента последней фиксации —