• #fail
Маркировка (Tagging) тестов
Теги — это способ организовать спецификации в группы, чтобы можно было выполнить их подмножество. Подобно фокусировке спецификации, теги применяются к блокам #describe
#it
через аргумент tags
следующим образом:require "spec"
describe "tags" do
it "tag a", tags: "a" do
end
it "tag b", tags: "b" do
end
end
Отсюда вы можете использовать опцию --tag
crystal spec
, чтобы контролировать, какие из них будут выполняться, как описано здесь:• --tag 'a' --tag 'b'
b
.• --tag '~a' --tag '~b'
b
.• --tag 'a' --tag '~b'
b
.Последняя команда может выглядеть так: crystal spec --tag 'a'
Осмеяние (Mocking)
Предыдущий пример с методом #add не имел никаких внешних зависимостей, но помните в
NotificationEmitter
типом аргумента конструктора, а не использовали его непосредственно в методе #process
? Тип NotificationEmitter
является зависимостью типа Processor
.Причина, по которой мы сделали его аргументом конструктора, заключается в том, что он следует нашим принципам проектирования
Давайте посмотрим на упрощенный пример здесь:
module TransformerInterface
abstract def transform(value : String) : String
end
struct ShoutTransformer
include Transformerinterface
def transform(value : String) : String
value.upcase
end
end
class Processor
def initialize(@transformer : Transformerinterface =
ShoutTransformer.new); end
def process(value : String) : String
@transformer.transform value
end
end
puts Processor.new.process "foo"
Здесь у нас есть тип интерфейса Transformer
ShoutTransformer
, которая преобразует значение в верхний регистр. Затем у нас есть тип Processor
, который использует тип интерфейса Transformer
как часть своего метода #process
, по умолчанию использующий преобразователь крика. Запуск этой программы приведет к выводу FOO
на ваш терминал.Поскольку мы хотим протестировать наш тип Processor
class MockTransformer
include Transformerinterface
getter transform_arg_value : String? = nil
def transform(value : String) : String
@transform_arg_value = value
end
end
Он реализует тот же API, что и другие, но фактически не преобразует значение, а просто предоставляет его через переменную экземпляра. Затем мы могли бы использовать это в тесте следующим образом, обязательно потребовав также Processor
MockTransformer
, если они не определены в одном файле:require "spec"
describe Processor do
describe "#process" do
it "processes" do