В этом посте мы рассмотрим юнит-тестирование (модульное тестирование).
Идея юнит-тестирования заключается в написании тестового кода, который проверяет ваш живой код.
Так почему люди пишут юнит-тесты?
Как вы узнаете, работает ли ваш код? Вы фактически понятия не имеете, пока не запустите его и не получите ожидаемые результаты.
Это особенно верно для Ruby, который является динамическим языком. В языке статического типа, таком как Java, если вы делаете опечатку, ваш редактор, вероятно, скажет вам об этом.
Еще одна причина для написания модульных тестов — когда вы хотите отрефакторить ваш код и быть уверенным, что вы ничего не сломали.
Для этого нужно добавить юнит-тесты. Когда у вас есть юнит-тесты, которые выполняются успешно, вы можете знать, что все работает как надо.
Другая причина для написания тестов заключается в том, что они могут послужить документацией для других разработчиков.
Test::Unit
Ruby очень серьезно относится к тестированию и предоставляет для этого фреймворк Test::Unit.
В Ruby 1.8 Unit::Test был загружен лишними библиотеками, которые включали много ненужного кода.
Ruby 1.9 уменьшил Test::Unit до необходимого минимума.
Новый фреймворк был официально назван MiniTest, хотя на него можно по-прежнему ссылаться под старым названием.
Обзор Test::Unit
- Test::Unit входит в семью XUnit (наряду с JUnit, CppUnit)
- Основная идея — расширение Test::Unit::TestCase
- Перед именем метода приставляется
test_
- Если один из методов не удается, другие продолжают проверяться (это хорошая вещь)
- Можно использовать методы
setup()
иteardown()
для установки поведения, которое будет выполняться перед каждым тест-методом
Давайте посмотрим на реальный пример. Скажем, вы пишите калькулятор.
class Calculator
attr_reader :name
def initialize(name)
@name = name
end
def add(one, two)
one - two # скажем, вы допустили ошибку здесь (- вместо +)
end
def subtract(one, two)
one + two # и в этом методе
end
def divide(one, two)
one / two
end
end
Тестируем:
require 'test/unit'
require_relative 'calculator.rb'
class CalculatorTest < Test::Unit::TestCase
def setup
@calc = Calculator.new('test')
end
def test_addition
assert_equal 4, @calc.add(2,2)
end
def test_subtraction
assert_equal 2, @calc.subtract(4,2)
end
def test_division
assert_equal 2, @calc.divide(4,2)
end
end
Когда вы выполните тест, вы увидите череду ошибок:
Если исправить наши ошибки, тест будет полностью доволен.
Также можно попробовать протестировать деление на ноль, в этом случае мы ожидаем, что наша программа должна выдать исключение.
require 'test/unit'
require_relative 'calculator.rb'
class CalculatorTest < Test::Unit::TestCase
def setup
@calc = Calculator.new('test')
end
def test_divide_by_zero
assert_raise ZeroDivisionError do
@calc.divide(1, 0)
end
end
end
С этим наш калькулятор должен справиться, так что этот тест покажет успех.