Разработка, основанная на специфицировании поведения (BDD), — один из краеугольных камней философии Ruby.
Очень удачной реализацией BDD является всем знакомый RSpec. Одной из замечательных черт RSpec является его расширяемость.
Так, мы используем RSpec совместно с Factory Girl (хотя стоило бы перейти на Machinist), RR (прекрасный каркас для заглушек), Spork и недавно перешли с Shoulda на Remarkable.
Естественно, захотелось сразу сделать наши спеки более простыми для понимания. Например, мы хотим проверять в спеках наличие определений обратного вызова.
Хорошим способом сделать это является создание нового «ожидателя» (matcher).
Основная логика заключается в методе is_valid?, который проверяет соответствие субьекта тестирования нашим ожиданиям.
Также потребуется расширить файл локали, добавив в него информацию о нашем «ожидателе».
И добавить require на наш файл matchers.rb в spec_helper.
И теперь можно легко и просто описывать наши ожидания.
______________________
Очень удачной реализацией BDD является всем знакомый RSpec. Одной из замечательных черт RSpec является его расширяемость.
Так, мы используем RSpec совместно с Factory Girl (хотя стоило бы перейти на Machinist), RR (прекрасный каркас для заглушек), Spork и недавно перешли с Shoulda на Remarkable.
Естественно, захотелось сразу сделать наши спеки более простыми для понимания. Например, мы хотим проверять в спеках наличие определений обратного вызова.
Хорошим способом сделать это является создание нового «ожидателя» (matcher).
Основная логика заключается в методе is_valid?, который проверяет соответствие субьекта тестирования нашим ожиданиям.
- module Scalaxy
- module Matchers
- class CallbackPresenceMatcher < Remarkable::Base
- arguments :chain, :callback
- assertion :is_valid?
- protected
- def is_valid?
- instance = @subject.kind_of?(Class) ? @subject.new : @subject
- chain_name = "#{@chain}_callback_chain".to_sym
- return false unless instance.kind_of?(ActiveSupport::Callbacks)
- return false unless instance.class.respond_to?(@chain)
- return false unless instance.class.respond_to?(chain_name)
- return false if instance.class.send(chain_name).select { |c| c.method == @callback }.empty?
- true
- end
- end
- # Matches for presence of specified callback inside specified callback chain.
- # should_callback_presence :after_run, :notify_people
- def callback_presence(*args)
- CallbackPresenceMatcher.new(*args).spec(self)
- end
- end
- end
- Remarkable.include_matchers!(Scalaxy, ActiveSupport::TestCase)
Также потребуется расширить файл локали, добавив в него информацию о нашем «ожидателе».
- en:
- scalaxy:
- callback_presence:
- description: 'Checks for presence of {{callback}} in specified callback chain {{chain}}.'
- expectations:
- is_valid: "to be valid when {{callback}} in {{chain}}"
И добавить require на наш файл matchers.rb в spec_helper.
И теперь можно легко и просто описывать наши ожидания.
- class Thing < ActiveRecord::Base
- ## Callbacks
- define_callbacks :after_run
- after_run :notify_people
- end
- describe Thing do
- should_callback_presence :after_run, :notify_people
- end
______________________