Implement `test_macro' recipe keyword
This commit is contained in:
parent
18b835b10e
commit
3c46c5bc61
52
features/recipe_test_macro.feature
Normal file
52
features/recipe_test_macro.feature
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
Feature: `test_macro' recipe keyword
|
||||||
|
|
||||||
|
Scenario: declares a new test keyword
|
||||||
|
Given a recipe with:
|
||||||
|
"""
|
||||||
|
test_macro :even? do |n|
|
||||||
|
n % 2 == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
[1, 2].each do |n|
|
||||||
|
task "test_macro-even-#{n}" do
|
||||||
|
condition { even? n }
|
||||||
|
echo n
|
||||||
|
end
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
When I successfully execute the recipe
|
||||||
|
Then the output must contain "2"
|
||||||
|
And the output must not contain "1"
|
||||||
|
|
||||||
|
@sshd
|
||||||
|
Scenario: has access to core tests
|
||||||
|
Given a recipe with:
|
||||||
|
"""
|
||||||
|
target 'some_host.test'
|
||||||
|
|
||||||
|
test_macro(:other_env?) { |k| env? k }
|
||||||
|
|
||||||
|
[:shell, :non_existent_var].each do |k|
|
||||||
|
task "test_macro-condition-#{k}" do
|
||||||
|
condition { other_env? k }
|
||||||
|
echo "#{k}_ok"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
When I successfully execute the recipe
|
||||||
|
Then the output must contain "shell_ok"
|
||||||
|
Then the output must not contain "non_existent_var_ok"
|
||||||
|
|
||||||
|
Scenario: has access to other tests declared with `test_macro'
|
||||||
|
Given a recipe with:
|
||||||
|
"""
|
||||||
|
test_macro(:one?) { |e| e == 1 }
|
||||||
|
test_macro(:one_alias?) { |e| one? e }
|
||||||
|
|
||||||
|
task :test_macro_macro do
|
||||||
|
condition { one_alias? 1 }
|
||||||
|
echo 'one_alias_ok'
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
When I successfully execute the recipe
|
||||||
|
Then the output must contain "one_alias_ok"
|
@ -16,6 +16,7 @@ require 'producer/core/actions/file_writer'
|
|||||||
|
|
||||||
# condition tests (need to be defined before the condition DSL)
|
# condition tests (need to be defined before the condition DSL)
|
||||||
require 'producer/core/test'
|
require 'producer/core/test'
|
||||||
|
require 'producer/core/tests/condition_test'
|
||||||
require 'producer/core/tests/file_contains'
|
require 'producer/core/tests/file_contains'
|
||||||
require 'producer/core/tests/has_dir'
|
require 'producer/core/tests/has_dir'
|
||||||
require 'producer/core/tests/has_env'
|
require 'producer/core/tests/has_env'
|
||||||
|
@ -2,9 +2,9 @@ module Producer
|
|||||||
module Core
|
module Core
|
||||||
class Condition
|
class Condition
|
||||||
class << self
|
class << self
|
||||||
def evaluate(env, &block)
|
def evaluate(env, *args, &block)
|
||||||
dsl = DSL.new(env, &block)
|
dsl = DSL.new(env, &block)
|
||||||
return_value = dsl.evaluate
|
return_value = dsl.evaluate *args
|
||||||
Condition.new(dsl.tests, return_value)
|
Condition.new(dsl.tests, return_value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -3,12 +3,21 @@ module Producer
|
|||||||
class Condition
|
class Condition
|
||||||
class DSL
|
class DSL
|
||||||
class << self
|
class << self
|
||||||
def define_test(keyword, klass)
|
def define_test(keyword, test)
|
||||||
define_method(keyword) do |*args|
|
{
|
||||||
@tests << klass.new(@env, *args)
|
keyword => false,
|
||||||
end
|
"no_#{keyword}" => true
|
||||||
define_method("no_#{keyword}") do |*args|
|
}.each do |kw, negated|
|
||||||
@tests << klass.new(@env, *args, negated: true)
|
define_method(kw) do |*args|
|
||||||
|
if test.respond_to? :call
|
||||||
|
args = [test, *args]
|
||||||
|
klass = Tests::ConditionTest
|
||||||
|
else
|
||||||
|
klass = test
|
||||||
|
end
|
||||||
|
t = klass.new(@env, *args, negated: negated)
|
||||||
|
@tests << t
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -29,8 +38,8 @@ module Producer
|
|||||||
@tests = []
|
@tests = []
|
||||||
end
|
end
|
||||||
|
|
||||||
def evaluate
|
def evaluate(*args)
|
||||||
instance_eval &@block
|
instance_exec *args, &@block
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -38,6 +38,10 @@ module Producer
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_macro(name, dsl: Condition::DSL, &block)
|
||||||
|
dsl.define_test(name, block)
|
||||||
|
end
|
||||||
|
|
||||||
def set(key, value)
|
def set(key, value)
|
||||||
env[key] = value
|
env[key] = value
|
||||||
end
|
end
|
||||||
|
23
lib/producer/core/tests/condition_test.rb
Normal file
23
lib/producer/core/tests/condition_test.rb
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
module Producer
|
||||||
|
module Core
|
||||||
|
module Tests
|
||||||
|
class ConditionTest < Test
|
||||||
|
def verify
|
||||||
|
condition.met?
|
||||||
|
end
|
||||||
|
|
||||||
|
def condition
|
||||||
|
Condition.evaluate(env, *condition_args, &condition_block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def condition_args
|
||||||
|
arguments.drop 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def condition_block
|
||||||
|
arguments.first
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -22,9 +22,9 @@ module Producer::Core
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe '.define_test' do
|
describe '.define_test' do
|
||||||
let(:some_test_class) { Test }
|
let(:some_test) { Test }
|
||||||
|
|
||||||
before { described_class.define_test(:some_test, some_test_class) }
|
before { described_class.define_test(:some_test, some_test) }
|
||||||
|
|
||||||
it 'defines a new test keyword' do
|
it 'defines a new test keyword' do
|
||||||
expect(dsl).to respond_to :some_test
|
expect(dsl).to respond_to :some_test
|
||||||
@ -41,19 +41,38 @@ module Producer::Core
|
|||||||
|
|
||||||
it 'registers the test with current env' do
|
it 'registers the test with current env' do
|
||||||
dsl.some_test
|
dsl.some_test
|
||||||
expect(dsl.tests.first.env).to be env
|
expect(dsl.tests.last.env).to be env
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'registers the test with given arguments' do
|
it 'registers the test with given arguments' do
|
||||||
dsl.some_test :some, :args
|
dsl.some_test :some, :args
|
||||||
expect(dsl.tests.first.arguments).to eq [:some, :args]
|
expect(dsl.tests.last.arguments).to eq [:some, :args]
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when given test is callable' do
|
||||||
|
let(:some_test) { proc {} }
|
||||||
|
|
||||||
|
before { dsl.some_test }
|
||||||
|
|
||||||
|
it 'registers a condition test' do
|
||||||
|
expect(dsl.tests.last).to be_a Tests::ConditionTest
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'registers the test with given block' do
|
||||||
|
expect(dsl.tests.last.condition_block).to be some_test
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'registers the test with given arguments' do
|
||||||
|
dsl.some_test :some, :args
|
||||||
|
expect(dsl.tests.last.condition_args).to eq [:some, :args]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when a negated test keyword is called' do
|
context 'when a negated test keyword is called' do
|
||||||
it 'registers a negated test' do
|
it 'registers a negated test' do
|
||||||
dsl.no_some_test
|
dsl.no_some_test
|
||||||
expect(dsl.tests.first).to be_negated
|
expect(dsl.tests.last).to be_negated
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -81,6 +100,15 @@ module Producer::Core
|
|||||||
it 'returns the value returned by the assigned block' do
|
it 'returns the value returned by the assigned block' do
|
||||||
expect(dsl.evaluate).to eq block.call
|
expect(dsl.evaluate).to eq block.call
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when arguments are given' do
|
||||||
|
let(:block) { proc { |e| throw e } }
|
||||||
|
|
||||||
|
it 'passes arguments as block parameters' do
|
||||||
|
expect { dsl.evaluate :some_argument }
|
||||||
|
.to throw_symbol :some_argument
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -102,6 +102,16 @@ module Producer::Core
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#test_macro' do
|
||||||
|
it 'defines the new test' do
|
||||||
|
condition_dsl = double 'condition dsl'
|
||||||
|
test_block = proc {}
|
||||||
|
expect(condition_dsl)
|
||||||
|
.to receive(:define_test).with(:some_test, test_block)
|
||||||
|
dsl.test_macro(:some_test, dsl: condition_dsl, &test_block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#set' do
|
describe '#set' do
|
||||||
it 'registers a key/value pair in env registry' do
|
it 'registers a key/value pair in env registry' do
|
||||||
dsl.set :some_key, :some_value
|
dsl.set :some_key, :some_value
|
||||||
|
55
spec/producer/core/tests/condition_test_spec.rb
Normal file
55
spec/producer/core/tests/condition_test_spec.rb
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
module Producer::Core
|
||||||
|
module Tests
|
||||||
|
describe ConditionTest do
|
||||||
|
let(:env) { double 'env' }
|
||||||
|
let(:block) { proc { true } }
|
||||||
|
let(:arguments) { [:some, :args] }
|
||||||
|
subject(:test) { described_class.new(env, block, *arguments) }
|
||||||
|
|
||||||
|
it_behaves_like 'test'
|
||||||
|
|
||||||
|
describe '#verify' do
|
||||||
|
context 'when condition is met' do
|
||||||
|
it 'returns true' do
|
||||||
|
expect(test.verify).to be true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when condition is not met' do
|
||||||
|
let(:block) { proc { false } }
|
||||||
|
|
||||||
|
it 'returns false' do
|
||||||
|
expect(test.verify).to be false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#condition' do
|
||||||
|
it 'evaluates a conditon' do
|
||||||
|
expect(Condition).to receive(:evaluate).with(env, *arguments, &block)
|
||||||
|
test.condition
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the evaluated condition' do
|
||||||
|
condition = double 'condition'
|
||||||
|
allow(Condition).to receive(:evaluate) { condition }
|
||||||
|
expect(test.condition).to eq condition
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#condition_args' do
|
||||||
|
it 'returns arguments for condition' do
|
||||||
|
expect(test.condition_args).to eq arguments
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#condition_block' do
|
||||||
|
it 'returns condition block' do
|
||||||
|
expect(test.condition_block).to eq block
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user