RSpec проти тесту :: Блок в рейки


15

Я ніколи не був впевнений у перевагах, які ви отримуєте, перейшовши на RSpec з Test :: Unit в Ruby on Rails (незважаючи на час від часу читаючи про RSpec).

Про що саме RSpec здається, що більшість проектів Rails використовує його?

(деякі приклади коду, що чітко вказують на переваги одного над іншим, були б дуже вдячні)


4
Тільки через рік я з огидою дивлюсь на Test :: Unit ... RSpec FTW!
Paweł Gościcki

Близькі дублікати на StackOverflow: RSpec vs Test :: Unit та RSpec vs.
Shoulda

Відповіді:


13

Це значною мірою питання смаку, і більшість інструментів для тестування, які варті їх солі, підтримують і те, і інше. Мої особисті переваги - це RSpec над Test :: Unit, оскільки а) вихід та компонування тестів фокусуються на тому, що повинен робити об'єкт, що перевіряється (на відміну від того, що є кодом), і b) кажучи "X слід Y" для мене більше сенсу, ніж «стверджувати, що X предикат Y».

Щоб дати вам деякий контекст для наведених вище пунктів, ось (досить надумане) порівняння вихідного / вихідного коду двох функціонально еквівалентних одиничних тестів, один написаний за допомогою RSpec, а другий за допомогою Test :: Unit.

Код, що перевіряється

class DeadError < StandardError; end

class Dog
  def bark
    raise DeadError.new "Can't bark when dead" if @dead
    "woof"
  end

  def die
    @dead = true
  end
end

Тест :: Одиниця

 require 'test/unit'
  require 'dog'

  class DogTest < Test::Unit::TestCase
    def setup
      @dog = Dog.new
    end

    def test_barks
      assert_equal "woof", @dog.bark    
    end

    def test_doesnt_bark_when_dead
      @dog.die
      assert_raises DeadError do
        @dog.bark
      end
    end
  end

RSpec

require 'rspec'
require 'dog'

describe Dog do
  before(:all) do
    @dog = Dog.new
  end

  context "when alive" do
    it "barks" do
      @dog.bark.should == "woof"
    end
  end

  context "when dead" do
    before do
      @dog.die
    end

    it "raises an error when asked to bark" do
      lambda { @dog.bark }.should raise_error(DeadError)
    end
  end
end

Тест :: Одиничний вихід (максимально повний)

Ξ code/examples → ruby dog_test.rb --verbose
Loaded suite dog_test
Started
test_barks(DogTest): .
test_doesnt_bark_when_dead(DogTest): .

Finished in 0.004937 seconds.

Вихід RSpec (формат документації)

Ξ code/examples → rspec -fd dog_spec.rb 

Dog
  when alive
    barks
  when dead
    raises an error when asked to bark

Finished in 0.00224 seconds
2 examples, 0 failures

2 tests, 2 assertions, 0 failures, 0 errors

PS Я думаю, що Берін (попередній респондент) суперечить ролям Огірка (який виріс в рамках проекту RSpec, але є незалежним) та RSpec. Огірок - це інструмент для автоматизованого тестування приймання у стилі BDD, тоді як RSpec - це бібліотека кодів для тестування, яка може бути і використовується на одиничному, інтеграційному та функціональному рівнях. Отже, використання RSpec не виключає тестування одиниць - це просто те, що ви називаєте свої тести на одиниці "специфікаціями".


Не очікував, що мені буде сумно, коли я приїхав сюди
Роман

3

Останнім часом здається, що огірок отримує більшу підтримку у громаді Рейлів. Ось короткий аргумент, який я почув з інтерв'ю з ведучим RSpec (зі старого Ruby on Rails Podcast).

У спритній спільноті (на той час) відбувся великий поштовх для тест-керованої розробки, наголос на тестуванні спочатку, щоб довести, що вам довелося щось змінити. З цим було щось філізофічно не так. По суті, тестування - це спосіб переконатися, що ваша реалізація правильна, тож як ви по-іншому думаєте про рушійну конструкцію? Провід RSpec припускав, що ви вказуєте спочатку, і чи не було б чудово, якби специфікація перевіряла результати вашої реалізації?

Просте перейменування assertв shouldдопомагає зосередити розум на правильному шляху до специфікації записи, і думати про дизайн. Однак це лише частина рівняння.

Що ще важливіше, оскільки багато віруючих TDD стверджували, що тести підтверджували дизайн, більшість документації в кращому випадку були поганими. Тести досить непрозорі для незнайомих розробників, які не знають мову. Вже тоді дизайн не відразу видно з читання більшості тестів.

Отже, як другорядна мета, RSpec розробив спосіб генерування письмової документації із специфікацій. Саме ця письмова специфікація дає RSpec перевагу перед простим Test :: Unit для управління дизайном програми. Навіщо писати щось не раз, коли можна одночасно документувати та перевіряти узгодженість дизайну?

Я розумію, що огірок, якому вдалося пізніше піти і засвоїти уроки з RSpec, робить кращу роботу над цією вторинною метою, не втрачаючи первинної мети (здатність перевірити реалізацію з специфікації). Огірок робить це з досить англійською, як API, що непрограмісти можуть розумно ривкати. Можливо, їм потрібна допомога програмістів для заповнення деяких визначень нових методів верифікації, але вона розроблена таким чином, щоб вона була розширюваною.

Підсумок полягає в тому, що RSpec / огірок взагалі не повинні замінювати одиничне тестування. Вони, можливо, краще підходять для документування та перевірки вашого дизайну - але є кілька тестів на реалізацію, які все ще потрібно зробити, особливо з тонкими помилками, які випливають із реалізації, а не дизайну програми. Це все ж зменшує кількість тестів, які вам доведеться написати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.