Статьи

Сделайте свои рубиновые тесты чище с Minitest и musta

Снимок экрана 2014-06-15 10.38.59

Еще до RSpec и Cucumber существовала базовая библиотека в Ruby под названием Test Unit . Это была просто основа для модульного тестирования кода. Однако, начиная с Ruby 1.9.3, Test Unit был заменен Minitest в качестве включенной среды тестирования для Ruby. В этой статье мы рассмотрим Minitest (поскольку он теперь заменил Test Unit) и преимущества musta-context , инфраструктуры Test::UnitMinitest

Предпосылки

  • Рубин (дух; текущий 2.1.2 будет лучшим)
  • Возможность запуска gem install GEM
  • Небольшое количество знаний о TDD, с разбрызгиванием BDD.

Разработка через тестирование (TDD) всегда была постоянным явлением в сообществе Ruby. Это ключевая концепция экстремального программирования и используется практически в каждом проекте Ruby. Создание модульных тестов с помощью Minitest очень просто, но для начала нам нужна библиотека Ruby для тестирования. Наша окончательная структура проекта будет выглядеть так:

 .
├── Gemfile
├── Gemfile.lock
├── Rakefile
├── lib
│   └── calculator.rb
└── test
    ├── test_calculator.rb
    ├── test_calculator_basic.rb
    └── test_helper.rb

Вы можете найти репо для этого проекта здесь .

Наша библиотека представляет собой калькулятор с двумя методами: addsubtract

 class Calculator
  def add(num1, num2)
    num1 + num2
  end

  def subtract(num1, num2)
    num1 - num2
  end
end

Чтобы протестировать эту библиотеку с помощью Minitest, создайте тестовый класс, который наследуется от Minitest::Test

 # file: test/test_calculator_basic.rb
  require 'minitest/autorun'
  require 'calculator' # don't worry, this works

  class TestCalculator < Minitest::Test

  end

Тесты внутри этого класса — это методы, которые начинаются с test_

 # file: test/test_calculator_basic.rb

require 'minitest/autorun'
require 'calculator'

class TestCalculator < Minitest::Test
  def setup
    @calc = Calculator.new
  end

  def test_proper_addition
    assert_equal 4, @calc.add(2, 2)
  end

  def test_proper_subtraction
    assert_equal 0, @calc.subtract(2, 2)
  end
end

Чтобы запустить этот тест, используйте следующую команду: $ ruby -I test:lib test/test_calculator_basic.rb Это может показаться немного повторяющимся, особенно если вы планируете использовать CI-сервер, поэтому мы можем использовать простую задачу Rake для автоматизации.

 # file: Rakefile
require 'rake/testtask'

Rake::TestTask.new do |task|
  task.libs << %w(test lib)
  task.pattern = 'test/test_*.rb'
end

task :default => :test

Теперь тесты запускаются простым вызовом rakerake test Это должно дать нам следующий вывод:

 Run options: --seed 41508

# Running:

..

Finished in 0.001047s, 1910.2197 runs/s, 1910.2197 assertions/s.

2 runs, 2 assertions, 0 failures, 0 errors, 0 skips

Как видите, наши тесты пройдены. Давайте добавим еще немного …

 # file: lib/test_calculator_basic.rb
require 'minitest/autorun'
require 'calculator'

class TestCalculator < Minitest::Test
  def setup
    @calc = Calculator.new
  end

  # add
  def test_add
    assert_equal 4, @calc.add(2, 2)
  end

  def test_failing_add
     refute_equal 5, @calc.add(2, 2)
  end

  # subtract
  def test_subtract
    assert_equal 0, @calc.subtract(2, 2)
  end

  def test_failing_subtract
    refute_equal -1, @calc.subtract(2, 2)
  end
end

Результаты этого аналогичны последним.

 Run options: --seed 4571

# Running:

....

Finished in 0.001081s, 3700.2775 runs/s, 3700.2775 assertions/s.

4 runs, 4 assertions, 0 failures, 0 errors, 0 skips

Возможно, вы заметили, что методы тестирования становятся все более запутанными для чтения. Это потому, что вы ограничены_underscored_names_as_tests. Вот тут-то и должен появиться контекст контекстной рекламы . Хорошие ребята из сайта Thinkbot создали эту библиотеку, чтобы помочь предоставить контекст для модульных тестов. Вот вышеописанный тест, написанный в формате musta-context:

 by_underscored_names_as_tests

Если вы еще этого не сделали, запустите # file: lib/test_calculator.rb
require 'minitest/autorun'
require 'shoulda/context'
require 'calculator'

class TestCalculator < Minitest::Test
context 'a calculator' do
setup do # notice the difference
@calc = Calculator.new
end

should 'add two numbers properly' do
assert_equal 4, @calc.add(2, 2)
end

should 'not add incorrectly' do
refute_equal 5, @calc.add(2, 2)
end

should 'subtract two numbers properly' do
assert_equal 0, @calc.subtract(2, 2)
end

should 'not subtract incorrectly' do
refute_equal -1, @calc.subtract(2, 2)
end
end
end

Как видите, тесты гораздо более читабельны. Человек может читать тесты следующим образом: gem install shoulda-context Например, первый тест можно прочитать так: context: should 'do something' Это гораздо более выразительно, чем в предыдущем примере. Тесты теперь кажутся более Ruby-esque.

Расширение: Выход

Если вы следовали вместе с примерами кода, то можете заметить, что результаты теста не так хороши, как результаты RSpec или Cucumber. Чтобы исправить это, мы можем использовать маленький драгоценный камень под названием minitest-reporters .

Во-первых, мы собираемся разделить наши тесты немного больше. Если у вас есть опыт работы с Rails и тестированием, то вы, вероятно, использовали a calculator should add two numbers properly Мы можем сделать то же самое в нашем проекте, просто создав файл в нашей test_helper.rbtest_helper.rb

Внутри test_helper.rbrequire

 # file: test/test_helper.rb
require 'minitest/autorun'
require 'shoulda/context'

Обратите внимание, что мы не включили require 'calculator' Это сделано потому, что мы могли бы расширить нашу библиотеку в какой-то момент за пределы класса Calculator Поскольку не все, что мы тестируем в нашей библиотеке, нужно будет включать calculatortest_helper.rb

Наш тестовый файл калькулятора должен выглядеть примерно так:

 # file: test/test_calculator.rb
require 'test_helper'
require 'calculator'

# ... lots of tests ...

Чтобы настроить minitest-reporters с нашей новой настройкой, сначала установите gem ( gem install minitest-reporters Теперь снова откройте test_helper.rb

 # file: test/test_helper.rb
require 'minitest/autorun'
require 'minitest/reporters' # requires the gem
require 'shoulda/context'

Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new # spec-like progress

Если мы запустим тесты ( ruby -I test:lib test/test_calculator.rbrake test

 Started

TestCalculator
  test: a calculator should subtract two numbers properly.       PASS (0.00s)
  test: a calculator should not add incorrectly.                 PASS (0.00s)
  test: a calculator should add two numbers properly.            PASS (0.00s)
  test: a calculator should not subtract incorrectly.            PASS (0.00s)

Finished in 0.00141s
4 tests, 4 assertions, 0 failures, 0 errors, 0 skips

Гораздо читабельнее и имеет цвет! Обратите внимание, что формат такой же, как и при чтении тестов для человека. Так и должно быть.

Вывод

Тестирование не только рекомендуется, но и практически необходимо при работе над проектом Ruby. Такие инструменты, как musta-context , помогут вам облегчить этот процесс. Мы рассмотрели основы Minitest, автоматизированное тестирование, контекст «следует» и причудливый (цветной, читаемый человеком) вывод. Если вы хотите узнать больше, проверьте эти ссылки: