rast 0.18.0 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +15 -0
- data/CHANGELOG.md +14 -0
- data/Documentation.md +297 -0
- data/Gemfile +0 -2
- data/Getting-Started-Detailed.md +122 -0
- data/Getting-Started.md +19 -102
- data/README.md +80 -16
- data/examples/enum_module.rb +20 -6
- data/examples/factory_example.rb +4 -4
- data/examples/hotel_finder.rb +14 -0
- data/examples/person.rb +6 -0
- data/examples/prime_number.rb +13 -8
- data/lib/rast/parameter_generator.rb +107 -53
- data/lib/rast/rast_spec.rb +8 -2
- data/lib/rast/rules/logic_helper.rb +76 -95
- data/lib/rast/rules/rule_evaluator.rb +100 -98
- data/lib/rast/rules/rule_validator.rb +14 -7
- data/lib/rast/rules/token_util.rb +17 -0
- data/lib/rast/spec_dsl.rb +57 -35
- data/lib/rast.rb +5 -1
- data/lib/template_spec.yml +5 -7
- data/rast.gemspec +1 -1
- metadata +8 -9
- data/examples/arithmetic_module.rb +0 -8
- data/examples/double_example.rb +0 -14
- data/examples/logic_four.rb +0 -15
- data/examples/lohika.rb +0 -27
- data/examples/phone.rb +0 -6
- data/examples/quiz_module.rb +0 -34
- data/examples/triple.rb +0 -15
data/lib/rast/spec_dsl.rb
CHANGED
@@ -7,11 +7,12 @@ require 'rast/parameter_generator'
|
|
7
7
|
class SpecDSL
|
8
8
|
include FactoryGirl::Syntax::Methods
|
9
9
|
|
10
|
-
attr_accessor :subject, :
|
11
|
-
:prepare_block, :
|
10
|
+
attr_accessor :subject, :execute_block,
|
11
|
+
:prepare_block, :outcomes, :fixtures, :spec_id
|
12
12
|
|
13
13
|
# # yaml-less
|
14
|
-
attr_writer :variables, :exclude, :include, :converters, :rules, :pair,
|
14
|
+
attr_writer :variables, :exclude, :include, :converters, :rules, :pair,
|
15
|
+
:default_outcome
|
15
16
|
|
16
17
|
# @subject the sut instance
|
17
18
|
# @name the sut name to be displayed with -fd
|
@@ -23,9 +24,6 @@ class SpecDSL
|
|
23
24
|
@subject_name = name || subject.class
|
24
25
|
@fixtures = fixtures
|
25
26
|
|
26
|
-
@transients = []
|
27
|
-
@rspec_methods = []
|
28
|
-
|
29
27
|
instance_eval(&block)
|
30
28
|
end
|
31
29
|
|
@@ -34,10 +32,14 @@ class SpecDSL
|
|
34
32
|
@variables = vars
|
35
33
|
end
|
36
34
|
|
37
|
-
def
|
35
|
+
def exclusion(clause)
|
38
36
|
@exclude = clause
|
39
37
|
end
|
40
38
|
|
39
|
+
def inclusion(clause)
|
40
|
+
@include = clause
|
41
|
+
end
|
42
|
+
|
41
43
|
def rules(rules)
|
42
44
|
@rules = {}
|
43
45
|
|
@@ -52,11 +54,14 @@ class SpecDSL
|
|
52
54
|
rules(outcomes)
|
53
55
|
end
|
54
56
|
|
57
|
+
def default(default)
|
58
|
+
@default_outcome = default
|
59
|
+
end
|
60
|
+
|
55
61
|
# yaml-less end
|
56
62
|
|
57
63
|
def prepare(&block)
|
58
64
|
@prepare_block = block
|
59
|
-
@transients
|
60
65
|
end
|
61
66
|
|
62
67
|
def execute(&block)
|
@@ -69,24 +74,23 @@ class SpecDSL
|
|
69
74
|
'pair' => @pair,
|
70
75
|
'converters' => @converters,
|
71
76
|
'rules' => @rules,
|
72
|
-
'exclude' => @exclude
|
77
|
+
'exclude' => @exclude,
|
78
|
+
'include' => @include,
|
79
|
+
'default' => @default_outcome
|
73
80
|
} }
|
74
81
|
|
75
82
|
@fixtures = parameter_generator.generate_fixtures(spec_id: @spec_id)
|
76
83
|
end
|
77
84
|
|
78
85
|
@fixtures.sort_by! do |fixture|
|
79
|
-
|
80
|
-
|
81
|
-
|
86
|
+
if fixture[:expected].nil?
|
87
|
+
raise "Expected outcome not found for #{fixture[:scenario]}, check" \
|
88
|
+
' your single rule/else/default configuration'
|
82
89
|
end
|
83
90
|
|
84
|
-
fixture[:
|
85
|
-
# fixture[:scenario].to_s + fixture[:expected_outcome]
|
91
|
+
fixture[:expected] + fixture[:scenario].to_s
|
86
92
|
end
|
87
93
|
|
88
|
-
# @fixtures.reverse!
|
89
|
-
|
90
94
|
generate_rspecs
|
91
95
|
end
|
92
96
|
|
@@ -95,35 +99,39 @@ class SpecDSL
|
|
95
99
|
def generate_rspecs
|
96
100
|
main_scope = self
|
97
101
|
|
98
|
-
|
99
|
-
|
100
|
-
exclusion = fixtures.first[:spec].exclude_clause
|
101
|
-
exclusion = exclusion.join if exclusion.is_a? Array
|
102
|
-
title += ", EXCLUDE: '#{exclusion}'" if exclusion
|
103
|
-
inclusion = fixtures.first[:spec].include_clause
|
104
|
-
inclusion = inclusion.join if inclusion.is_a? Array
|
105
|
-
title += ", ONLY: '#{inclusion}'" if inclusion
|
106
|
-
|
107
|
-
RSpec.describe title do
|
102
|
+
RSpec.describe build_title do
|
108
103
|
main_scope.fixtures.each do |fixture|
|
109
104
|
generate_rspec(
|
110
105
|
scope: main_scope,
|
111
106
|
scenario: fixture[:scenario],
|
112
|
-
expected: fixture[:
|
107
|
+
expected: fixture[:expected]
|
113
108
|
)
|
114
109
|
end
|
115
110
|
end
|
116
111
|
end
|
117
112
|
end
|
118
113
|
|
119
|
-
def
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
114
|
+
def build_title
|
115
|
+
title = "#{@subject_name}: #{@fixtures.first[:spec].description}"
|
116
|
+
title += append_exclusion_title
|
117
|
+
title += append_inclusion_title
|
118
|
+
title
|
119
|
+
end
|
125
120
|
|
126
|
-
|
121
|
+
def append_exclusion_title
|
122
|
+
exclusion = @fixtures.first[:spec].exclude_clause
|
123
|
+
exclusion = exclusion.join if exclusion.is_a? Array
|
124
|
+
exclusion ? ", EXCLUDE: '#{exclusion}'" : ''
|
125
|
+
end
|
126
|
+
|
127
|
+
def append_inclusion_title
|
128
|
+
inclusion = @fixtures.first[:spec].include_clause
|
129
|
+
inclusion = inclusion.join if inclusion.is_a? Array
|
130
|
+
inclusion ? ", ONLY: '#{inclusion}'" : ''
|
131
|
+
end
|
132
|
+
|
133
|
+
def generate_rspec(scope: nil, scenario: {}, expected: '')
|
134
|
+
it _it_title(expected, scenario) do
|
127
135
|
block_params = scenario.values
|
128
136
|
|
129
137
|
@mysubject = scope.subject
|
@@ -132,7 +140,7 @@ def generate_rspec(scope: nil, scenario: {}, expected: '')
|
|
132
140
|
define_method(:subject) { @mysubject }
|
133
141
|
end
|
134
142
|
|
135
|
-
|
143
|
+
unless scope.prepare_block.nil?
|
136
144
|
instance_exec(*block_params, &scope.prepare_block)
|
137
145
|
end
|
138
146
|
|
@@ -142,6 +150,20 @@ def generate_rspec(scope: nil, scenario: {}, expected: '')
|
|
142
150
|
end
|
143
151
|
end
|
144
152
|
|
153
|
+
def _it_title(expected, scenario)
|
154
|
+
spec_params = scenario.keys.inject('') do |output, key|
|
155
|
+
build_it(scenario, output, key)
|
156
|
+
end
|
157
|
+
|
158
|
+
"[#{expected}]=[#{spec_params}]"
|
159
|
+
end
|
160
|
+
|
161
|
+
def build_it(scenario, output, key)
|
162
|
+
output += ', ' unless output == ''
|
163
|
+
calc_key = scenario[key].nil? ? nil : scenario[key]
|
164
|
+
output + "#{key}: #{calc_key}"
|
165
|
+
end
|
166
|
+
|
145
167
|
# DSL Entry Point
|
146
168
|
def spec(subject: nil, name: '', fixtures: [], spec_id: '', &block)
|
147
169
|
SpecDSL.new(
|
data/lib/rast.rb
CHANGED
@@ -34,7 +34,7 @@ class Rast
|
|
34
34
|
raise message unless yield
|
35
35
|
end
|
36
36
|
|
37
|
-
def xspec(id
|
37
|
+
def xspec(id)
|
38
38
|
p "xspec skipped #{id}"
|
39
39
|
end
|
40
40
|
|
@@ -53,3 +53,7 @@ end
|
|
53
53
|
def rast(rasted_subject, &block)
|
54
54
|
Rast.new(rasted_subject, &block)
|
55
55
|
end
|
56
|
+
|
57
|
+
def xrast(rasted_subject)
|
58
|
+
p "xrast skipped #{rasted_subject}"
|
59
|
+
end
|
data/lib/template_spec.yml
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
---
|
2
2
|
specs:
|
3
|
+
# spec key uniquely identifies a spec. It has to match the ID when the spec
|
4
|
+
# block is invoked in the ruby spec file. Usually the method name.
|
3
5
|
spec_key:
|
4
6
|
description: Spec Description
|
5
7
|
|
6
8
|
variables:
|
7
|
-
param1:
|
8
|
-
- one
|
9
|
-
- two
|
9
|
+
param1: [one, two]
|
10
10
|
|
11
11
|
outcomes: # required (dictionary)
|
12
|
-
true:
|
12
|
+
true: one[0] # sample outcome.
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
default: DEFAULT # optional (scalar) fall off value, or the else result of the `pair` config.
|
14
|
+
default: DEFAULT # optional (scalar) fall off value.
|
data/rast.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rast
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.19.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Royce Remulla
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-05-
|
11
|
+
date: 2020-05-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: factory_girl
|
@@ -35,26 +35,24 @@ files:
|
|
35
35
|
- ".gitignore"
|
36
36
|
- ".rspec"
|
37
37
|
- ".rubocop.yml"
|
38
|
+
- ".travis.yml"
|
38
39
|
- CHANGELOG.md
|
40
|
+
- Documentation.md
|
39
41
|
- Gemfile
|
40
42
|
- Gemfile.lock
|
43
|
+
- Getting-Started-Detailed.md
|
41
44
|
- Getting-Started.md
|
42
45
|
- README.md
|
43
|
-
- examples/arithmetic_module.rb
|
44
|
-
- examples/double_example.rb
|
45
46
|
- examples/enum_module.rb
|
46
47
|
- examples/factory_example.rb
|
48
|
+
- examples/hotel_finder.rb
|
47
49
|
- examples/logic_checker.rb
|
48
|
-
- examples/
|
49
|
-
- examples/lohika.rb
|
50
|
-
- examples/phone.rb
|
50
|
+
- examples/person.rb
|
51
51
|
- examples/positive.rb
|
52
52
|
- examples/positive2.rb
|
53
53
|
- examples/prime_number.rb
|
54
|
-
- examples/quiz_module.rb
|
55
54
|
- examples/quoted.rb
|
56
55
|
- examples/recruiter.rb
|
57
|
-
- examples/triple.rb
|
58
56
|
- examples/worker.rb
|
59
57
|
- lib/rast.rb
|
60
58
|
- lib/rast/converters/bool_converter.rb
|
@@ -70,6 +68,7 @@ files:
|
|
70
68
|
- lib/rast/rules/rule_evaluator.rb
|
71
69
|
- lib/rast/rules/rule_processor.rb
|
72
70
|
- lib/rast/rules/rule_validator.rb
|
71
|
+
- lib/rast/rules/token_util.rb
|
73
72
|
- lib/rast/spec_dsl.rb
|
74
73
|
- lib/template_spec.yml
|
75
74
|
- rast.gemspec
|
data/examples/double_example.rb
DELETED
data/examples/logic_four.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Checks bug introduced when converters are combined with token converter.
|
4
|
-
#
|
5
|
-
# @author Royce Remulla
|
6
|
-
#
|
7
|
-
class LogicFour
|
8
|
-
# Perform logical AND operation on two arguments.
|
9
|
-
#
|
10
|
-
# @param argument1 first argument of Boolean type.
|
11
|
-
# @param argument2 second argument of Boolean type.
|
12
|
-
def process(argument1, argument2, argument3, argument4)
|
13
|
-
!argument1 && !argument2 && !argument3 && argument4 == 'a'
|
14
|
-
end
|
15
|
-
end
|
data/examples/lohika.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# LogicChecker ported from Java
|
4
|
-
#
|
5
|
-
# @author Royce Remulla
|
6
|
-
#
|
7
|
-
class Lohika
|
8
|
-
# Perform logical AND operation on two arguments.
|
9
|
-
#
|
10
|
-
# @param argument1 first argument of Boolean type.
|
11
|
-
# @param argument2 second argument of Boolean type.
|
12
|
-
def at(argument1, argument2)
|
13
|
-
return :oo if argument1 == 'oo' && argument2 == 'oo'
|
14
|
-
|
15
|
-
:hindi
|
16
|
-
end
|
17
|
-
|
18
|
-
# Perform logical OR operation on two arguments.
|
19
|
-
#
|
20
|
-
# @param argument1 first argument of Boolean type.
|
21
|
-
# @param argument2 second argument of Boolean type.
|
22
|
-
def o(argument1, argument2)
|
23
|
-
return :oo if argument1 == 'oo' || argument2 == 'oo'
|
24
|
-
|
25
|
-
:hindi
|
26
|
-
end
|
27
|
-
end
|
data/examples/phone.rb
DELETED
data/examples/quiz_module.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
# Used to determine if cards form quiz type
|
2
|
-
# S postfix means Single option, M postfix means Multiple options
|
3
|
-
module QuizModule
|
4
|
-
RE_SELECTED = /(?<=\([*x]\)\s).*/.freeze
|
5
|
-
RE_CHECKED = /(?<=\[[*x]\]\s).*/.freeze
|
6
|
-
RE_WRONG_OPT_S = /(?<=\(\)\s).*/.freeze
|
7
|
-
RE_WRONG_OPT_M = /(?<=\[\]\s).*/.freeze
|
8
|
-
|
9
|
-
RE_QUIZ_OPTION_S = Regexp.new(
|
10
|
-
"#{RE_WRONG_OPT_S}|#{RE_SELECTED}",
|
11
|
-
Regexp::IGNORECASE
|
12
|
-
)
|
13
|
-
|
14
|
-
RE_QUIZ_OPTION_M = Regexp.new(
|
15
|
-
"#{RE_WRONG_OPT_M}|#{RE_CHECKED}",
|
16
|
-
Regexp::IGNORECASE
|
17
|
-
)
|
18
|
-
|
19
|
-
def quiz_multi_choice?(back)
|
20
|
-
if back.is_a?(Array) && back.any?
|
21
|
-
back.each { |element| return false unless element[RE_QUIZ_OPTION_M] }
|
22
|
-
|
23
|
-
# Find at least 1 checked answer
|
24
|
-
return false unless back.find do |element|
|
25
|
-
true if element[RE_CHECKED]
|
26
|
-
end
|
27
|
-
|
28
|
-
@quiz = true
|
29
|
-
@front_only = true
|
30
|
-
return true
|
31
|
-
end
|
32
|
-
false
|
33
|
-
end
|
34
|
-
end
|
data/examples/triple.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Triple. This example is used to test automatic detection of variable data type in yaml.
|
4
|
-
#
|
5
|
-
# @author Royce Remulla
|
6
|
-
#
|
7
|
-
class Triple
|
8
|
-
# Perform logical AND operation on two arguments.
|
9
|
-
#
|
10
|
-
# @param argument1 first argument of Boolean type.
|
11
|
-
# @param argument2 second argument of Boolean type.
|
12
|
-
def triple(argument1, argument2, _argument3)
|
13
|
-
argument1 && argument2
|
14
|
-
end
|
15
|
-
end
|