api_mini_tester 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/api_mini_tester.rb +6 -0
- data/lib/api_mini_tester/test_formatter.rb +209 -0
- data/lib/api_mini_tester/test_scenario.rb +44 -0
- data/lib/api_mini_tester/test_step.rb +199 -0
- data/lib/api_mini_tester/test_suite.rb +47 -0
- metadata +268 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ab778aea0e70140ad7987422ea3cc84423ca3c83
|
4
|
+
data.tar.gz: 482db1276239fca74afb2b54a490e464f1529ccb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f75c1d2e8af06c2629da0c2e52f8b63f154871df0c3a0fb950e03dd2adf8f485f99161cbeb22f385d7869c5460341893a3f65ed366c9f217b1ecf4a8c3bf7bae
|
7
|
+
data.tar.gz: d72335d77cab38d7f09a0171914b2a56323a59ae057c9ef2acac8a38ae9c5b6a1b176aa0de9889d675988eeceb4c9bbe099d2258b49a8cd2eaad04bf0dcbcb09
|
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'builder'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
class TestFormatter
|
5
|
+
|
6
|
+
RESULT_SECTIONS = %i[status headers body timing].freeze
|
7
|
+
SECTION_TRANSLATE = {
|
8
|
+
status: "Status",
|
9
|
+
headers: "Headers",
|
10
|
+
body: "Body",
|
11
|
+
timing: "Timing"
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
attr_accessor :results
|
15
|
+
|
16
|
+
def initialize(results)
|
17
|
+
@results = results
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_json
|
21
|
+
clean_up_infinity.to_json
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_yaml
|
25
|
+
clean_up_infinity.to_yaml
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_junit_xml
|
29
|
+
xml = Builder::XmlMarkup.new(indent: 2)
|
30
|
+
xml.instruct! :xml, encoding: "UTF-8"
|
31
|
+
xml.testsuites do
|
32
|
+
results[:scenarios].each do |scenario|
|
33
|
+
xml.testsuite name: scenario[:name],
|
34
|
+
timestamp: timestamp,
|
35
|
+
hostname: hostname,
|
36
|
+
tests: tests_in_scenario(scenario),
|
37
|
+
skipped: 0,
|
38
|
+
failures: failed_in_scenario(scenario),
|
39
|
+
errors: 0,
|
40
|
+
time: time_in_scenario(scenario) do
|
41
|
+
scenario[:steps].each do |step|
|
42
|
+
classname = name_to_camelcase(step[:name])
|
43
|
+
RESULT_SECTIONS.each do |section|
|
44
|
+
step[section].each do |s|
|
45
|
+
xml.testcase classname: classname,
|
46
|
+
name: s[:name],
|
47
|
+
time: step_timing(step),
|
48
|
+
file: "./#{classname}.rb" do
|
49
|
+
s[:result] ? nil : xml.failure(message: s[:desc])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def timestamp
|
60
|
+
Time.now.strftime("%FT%T%:z")
|
61
|
+
end
|
62
|
+
|
63
|
+
def scenarios_count
|
64
|
+
results[:scenarios].size
|
65
|
+
end
|
66
|
+
|
67
|
+
def steps_count(scenario)
|
68
|
+
scenario[:steps].size
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_count(step)
|
72
|
+
count = 0
|
73
|
+
[:status, :headers, :body, :timing].each do |section|
|
74
|
+
count += step[section].size
|
75
|
+
end
|
76
|
+
count
|
77
|
+
end
|
78
|
+
|
79
|
+
def tests_in_scenario(scenario)
|
80
|
+
count = 0
|
81
|
+
scenario[:steps].each do |step|
|
82
|
+
count += test_count(step)
|
83
|
+
end
|
84
|
+
count
|
85
|
+
end
|
86
|
+
|
87
|
+
def time_in_scenario(scenario)
|
88
|
+
time = 0.0
|
89
|
+
scenario[:steps].each do |step|
|
90
|
+
time += step[:timing].first[:real]
|
91
|
+
end
|
92
|
+
time
|
93
|
+
end
|
94
|
+
|
95
|
+
def failed_in_scenario(scenario)
|
96
|
+
count = 0
|
97
|
+
scenario[:steps].each do |step|
|
98
|
+
[:status, :headers, :body, :timing].each do |section|
|
99
|
+
count += step[section].map { |res| res[:result] }.select(&:!).size
|
100
|
+
end
|
101
|
+
end
|
102
|
+
count
|
103
|
+
end
|
104
|
+
|
105
|
+
def hostname
|
106
|
+
Socket.gethostname
|
107
|
+
end
|
108
|
+
|
109
|
+
def name_to_camelcase(name)
|
110
|
+
name.gsub(/[[:space:]]+/, '_').downcase.gsub(/(?:^|_)([a-z])/) { $1.upcase }
|
111
|
+
end
|
112
|
+
|
113
|
+
def step_timing(step)
|
114
|
+
step[:timing].first ? step[:timing].first[:real] : 0
|
115
|
+
end
|
116
|
+
|
117
|
+
def clean_up_infinity
|
118
|
+
res = results.dup
|
119
|
+
res[:scenarios].each do |scenario|
|
120
|
+
scenario[:steps].each do |step|
|
121
|
+
step[:timing].each do |timing|
|
122
|
+
timing[:exp] = "Not Specified" if timing.is_a?(Hash) && timing[:exp] && timing[:exp] == Float::INFINITY
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
res
|
127
|
+
end
|
128
|
+
|
129
|
+
def array_in(array)
|
130
|
+
list = ''
|
131
|
+
array.each do |item|
|
132
|
+
if item.instance_of?(Array)
|
133
|
+
list << array_in(item)
|
134
|
+
elsif item.instance_of?(Hash)
|
135
|
+
list << hash_in(item)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
list
|
139
|
+
end
|
140
|
+
|
141
|
+
def hash_in(hash)
|
142
|
+
list = ''
|
143
|
+
hash.each do |k, v|
|
144
|
+
if v.instance_of?(Hash)
|
145
|
+
list << hash_in(v)
|
146
|
+
elsif v.instance_of?(Array)
|
147
|
+
list << array_in(v)
|
148
|
+
elsif k == :result
|
149
|
+
list << (v ? '.' : 'E')
|
150
|
+
end
|
151
|
+
end
|
152
|
+
list
|
153
|
+
end
|
154
|
+
|
155
|
+
def to_simple
|
156
|
+
hash_in results
|
157
|
+
end
|
158
|
+
|
159
|
+
def md_section_header(header, desc, level)
|
160
|
+
output = []
|
161
|
+
output << "#{'#' * level} #{header}"
|
162
|
+
output << ""
|
163
|
+
if desc
|
164
|
+
output << "Desc: #{desc}"
|
165
|
+
output << ""
|
166
|
+
end
|
167
|
+
output
|
168
|
+
end
|
169
|
+
|
170
|
+
def md_step_header(step)
|
171
|
+
output = []
|
172
|
+
output.push(*md_section_header(step[:name], step[:desc], 3))
|
173
|
+
output.push(*md_section_header("Call", nil, 4))
|
174
|
+
step[:url].each do |url|
|
175
|
+
output << "* #{url[:desc]}"
|
176
|
+
end
|
177
|
+
step[:method].each do |method|
|
178
|
+
output << "* #{method[:desc]}"
|
179
|
+
end
|
180
|
+
output << ""
|
181
|
+
output
|
182
|
+
end
|
183
|
+
|
184
|
+
def md_section_content(step, section)
|
185
|
+
output = []
|
186
|
+
output << md_section_header(SECTION_TRANSLATE[section], nil, 4)
|
187
|
+
step[section].each do |status|
|
188
|
+
output << "* `#{status[:result]}`: #{status[:desc]}"
|
189
|
+
end
|
190
|
+
output << ""
|
191
|
+
output
|
192
|
+
end
|
193
|
+
|
194
|
+
def to_markdown
|
195
|
+
output = []
|
196
|
+
output << md_section_header(results[:name], results[:desc], 1)
|
197
|
+
results[:scenarios].each do |scenario|
|
198
|
+
output << md_section_header(scenario[:name], scenario[:desc], 2)
|
199
|
+
scenario[:steps].each do |step|
|
200
|
+
output.push(*md_step_header(step))
|
201
|
+
RESULT_SECTIONS.each do |section|
|
202
|
+
output.push(*md_section_content(step, section))
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
output.join("\n")
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require_relative 'test_step'
|
2
|
+
|
3
|
+
module ApiMiniTester
|
4
|
+
class TestScenario
|
5
|
+
|
6
|
+
attr_accessor :base_uri, :scenario, :data, :results, :name
|
7
|
+
|
8
|
+
def initialize(base_uri, scenario, data)
|
9
|
+
@base_uri = base_uri
|
10
|
+
@scenario = scenario
|
11
|
+
@data = data
|
12
|
+
@name = scenario['name']
|
13
|
+
@results = {name: scenario['name'], desc: scenario['desc'], steps: []}
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid?
|
17
|
+
return false if scenario.nil? || scenario['steps'].nil?
|
18
|
+
return false unless scenario['steps'].is_a?(Array) || scenario['steps'].empty?
|
19
|
+
return false if name.nil? || name.empty?
|
20
|
+
return false if base_uri.nil? || base_uri.empty?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_result(result)
|
25
|
+
@results.steps << result
|
26
|
+
end
|
27
|
+
|
28
|
+
def print_results
|
29
|
+
@results.each do |line|
|
30
|
+
puts line
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def run_scenario
|
35
|
+
@context = []
|
36
|
+
scenario['steps'].each do |step|
|
37
|
+
step = TestStep.new(base_uri, step, @context, data)
|
38
|
+
step_result, context = step.run_step
|
39
|
+
@results[:steps] << step_result
|
40
|
+
@context << context
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'liquid'
|
3
|
+
require 'hash_parser'
|
4
|
+
require 'uri'
|
5
|
+
require 'faker'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
module ApiMiniTester
|
9
|
+
class TestStep
|
10
|
+
|
11
|
+
include HTTParty
|
12
|
+
|
13
|
+
SUPPORTED_METHODS = %i[ get post put delete ].freeze
|
14
|
+
|
15
|
+
attr_accessor :uri, :method, :name, :input, :output
|
16
|
+
attr_reader :results
|
17
|
+
|
18
|
+
def initialize(base_uri, step, context = nil, data = nil)
|
19
|
+
@context = context
|
20
|
+
uri_template = Liquid::Template.parse([base_uri, step['uri']].join("/"), error_mode: :strict)
|
21
|
+
@name = step['name']
|
22
|
+
@uri = uri_template.render({'context' => context, 'data' => data}, { strict_variables: true })
|
23
|
+
@method = step['method'].downcase.to_sym
|
24
|
+
|
25
|
+
input_template = Liquid::Template.parse(step['input'].to_yaml.to_s, error_mode: :strict)
|
26
|
+
@input = YAML.load(input_template.render({'context' => context, 'data' => data}, { strict_variables: true }))
|
27
|
+
|
28
|
+
output_template = Liquid::Template.parse(step['output'].to_yaml.to_s, error_mode: :strict)
|
29
|
+
@output = YAML.load(output_template.render({'context' => context, 'data' => data}, { strict_variables: true }))
|
30
|
+
|
31
|
+
@results = { name: step['name'], desc: step['desc'], status: [], headers: [], body: [], url: [], method: [], timing: [] }
|
32
|
+
end
|
33
|
+
|
34
|
+
def valid?
|
35
|
+
return false if uri.nil? || uri.empty?
|
36
|
+
return false unless URI.parse(uri) rescue false
|
37
|
+
return false unless SUPPORTED_METHODS.include? method
|
38
|
+
return false if @name.nil? || @name.empty?
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
def content_type
|
43
|
+
@input['content_type'] || 'application/json'
|
44
|
+
end
|
45
|
+
|
46
|
+
def headers
|
47
|
+
@input['header']['Content-type'] = content_type if content_type == 'application/json'
|
48
|
+
@input['header']
|
49
|
+
end
|
50
|
+
|
51
|
+
def body
|
52
|
+
case content_type
|
53
|
+
when 'application/x-www-form-urlencoded'
|
54
|
+
body_to_form_data
|
55
|
+
when 'multipart/form-data'
|
56
|
+
body_to_form_data
|
57
|
+
else
|
58
|
+
@input["body"].to_json
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def body_to_form_data
|
63
|
+
body = {}
|
64
|
+
@input["body"].each do |item|
|
65
|
+
body[item['name']] = item['value'] if item['type'] == 'input'
|
66
|
+
body[item['name']] = File.open(item['value'], 'r') if item['type'] == 'file'
|
67
|
+
end
|
68
|
+
body
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_headers
|
72
|
+
@output['header']
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_body
|
76
|
+
@output['body']
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_status
|
80
|
+
@output['status']
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_timing
|
84
|
+
@output['timing']
|
85
|
+
end
|
86
|
+
|
87
|
+
def run_step
|
88
|
+
@timing = Time.now
|
89
|
+
case method
|
90
|
+
when :get
|
91
|
+
response = HTTParty.get(uri, headers: headers)
|
92
|
+
when :post
|
93
|
+
response = HTTParty.post(uri, headers: headers, body: body)
|
94
|
+
when :put
|
95
|
+
response = HTTParty.put(uri, headers: headers, body: body)
|
96
|
+
when :delete
|
97
|
+
response = HTTParty.delete(uri, headers: headers)
|
98
|
+
end
|
99
|
+
@timing = Time.now - @timing
|
100
|
+
|
101
|
+
add_result :url, { result: true, desc: "Url: #{uri}" }
|
102
|
+
add_result :method, { result: true, desc: "Method: #{method}" }
|
103
|
+
|
104
|
+
assert_status(response.code, test_status)
|
105
|
+
assert_headers(response.headers, test_headers)
|
106
|
+
assert_body(response.parsed_response, test_body)
|
107
|
+
assert_timing(@timing, test_timing)
|
108
|
+
|
109
|
+
[ results, response ]
|
110
|
+
end
|
111
|
+
|
112
|
+
def print_results
|
113
|
+
@results.each do |line|
|
114
|
+
puts line
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def add_result(section, result)
|
119
|
+
@results[section] << result
|
120
|
+
end
|
121
|
+
|
122
|
+
def assert_timing(runtime, limit = nil)
|
123
|
+
limit ||= Float::INFINITY
|
124
|
+
add_result :timing, { result: (runtime < limit),
|
125
|
+
name: "Request time < #{limit}",
|
126
|
+
desc: "Expected request time #{limit}, real time #{runtime}",
|
127
|
+
exp: limit, real: runtime }
|
128
|
+
end
|
129
|
+
|
130
|
+
def assert_status(response, output)
|
131
|
+
add_result :status, { result: (response == output),
|
132
|
+
name: "Response code == #{output}",
|
133
|
+
desc: "Expected response #{output}, got response #{response}",
|
134
|
+
exp: output, real: response }
|
135
|
+
end
|
136
|
+
|
137
|
+
def assert_headers(response, output)
|
138
|
+
return if output.nil?
|
139
|
+
output.each do |k, v|
|
140
|
+
add_result :headers, { result: (v == response[k]),
|
141
|
+
name: "Header value: #{k} == #{v}",
|
142
|
+
desc: "Header #{k} expected: #{v}, got #{response[k]}",
|
143
|
+
exp: v, real: response[k] }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def assert_body(response, output)
|
148
|
+
if output.instance_of?(Hash)
|
149
|
+
hash_diff(output, response)
|
150
|
+
elsif output.instance_of?(Array)
|
151
|
+
array_diff(output, response)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def array_diff(a, b, path = nil, section = :body)
|
156
|
+
a.each do |a_item|
|
157
|
+
if a_item.instance_of?(Hash)
|
158
|
+
found = false
|
159
|
+
b.each do |b_item|
|
160
|
+
matching = true
|
161
|
+
a_item.each_key do |k, v|
|
162
|
+
matching = (b_item[k] == a_item[k]) if matching
|
163
|
+
end
|
164
|
+
found = true if matching
|
165
|
+
end
|
166
|
+
add_result section, { result: found,
|
167
|
+
name: "Response body value: #{[path].join(".")}",
|
168
|
+
desc: "Assert #{[path].join(".")} #{found ? 'contains' : 'does not contains'} #{a_item}" }
|
169
|
+
elsif a_item.instance_of?(Array)
|
170
|
+
# TODO: Add support for array of array it isn't so needed to compate so deep structures
|
171
|
+
else
|
172
|
+
add_result section, { result: b.include?(a_item),
|
173
|
+
name: "Response boby value: #{[path].join(".")}",
|
174
|
+
desc: "Assert #{[path].join(".")} #{b.include?(a_item) ? 'contains' : 'does not contains'} #{a_item}" }
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def hash_diff(a, b, path = nil, section = :body)
|
180
|
+
return nil if a.nil? || b.nil?
|
181
|
+
a.each_key do |k, v|
|
182
|
+
current_path = [path, k].join('.')
|
183
|
+
if b[k].nil?
|
184
|
+
add_result section, { result: false,
|
185
|
+
name: "Reponse value: #{[path, k].join(".")}",
|
186
|
+
desc: "Missing #{current_path}" }
|
187
|
+
elsif v.instance_of?(Hash)
|
188
|
+
hash_diff(a[k], b[k], current_path, section)
|
189
|
+
elsif v.instance_of?(Array)
|
190
|
+
array_diff(a[k], b[k], current_path, section)
|
191
|
+
else
|
192
|
+
add_result section, { result: (a[k] == b[k]),
|
193
|
+
name: "Reponse body value: #{[path, k].join(".")}",
|
194
|
+
desc: "Assert #{[path, k].join(".")}: #{a[k]} #{a[k] == b[k] ? '==' : '!='} #{b[k]}" }
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require_relative 'test_scenario'
|
3
|
+
require_relative 'test_formatter'
|
4
|
+
|
5
|
+
module ApiMiniTester
|
6
|
+
class TestSuite
|
7
|
+
|
8
|
+
attr_accessor :base_uri, :scenarios, :data, :results
|
9
|
+
|
10
|
+
def initialize(suite_def)
|
11
|
+
if suite_def.is_a?(String)
|
12
|
+
@test = YAML.load(File.open(suite_def))
|
13
|
+
elsif suite_def.is_a?(Hash)
|
14
|
+
@test = suite_def
|
15
|
+
end
|
16
|
+
setup
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?
|
20
|
+
return false if base_uri.nil? || base_uri.empty?
|
21
|
+
return false if scenarios.nil? || scenarios.empty?
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
25
|
+
def setup
|
26
|
+
@base_uri = @test['settings']['baseurl']
|
27
|
+
@scenarios = @test['tests']
|
28
|
+
@data = @test['data']
|
29
|
+
@results = {name: @test['name'], desc: @test['desc'], scenarios: []}
|
30
|
+
end
|
31
|
+
|
32
|
+
def run_scenarios
|
33
|
+
scenarios.each do |scenario|
|
34
|
+
runner = TestScenario.new(base_uri, scenario, data)
|
35
|
+
runner.run_scenario
|
36
|
+
@results[:scenarios] << runner.results
|
37
|
+
end
|
38
|
+
@results
|
39
|
+
end
|
40
|
+
|
41
|
+
def print_results(format)
|
42
|
+
formatter = TestFormatter.new(results)
|
43
|
+
formatter.send("to_#{format}")
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: api_mini_tester
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jindrich Skupa (@eMan)
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-09-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: builder
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.0.4
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.0.4
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: faker
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.8'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.8.7
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.8'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.8.7
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: hash_parser
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0.0'
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.0.2
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0.0'
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 0.0.2
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: httparty
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0.16'
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.16.0
|
83
|
+
type: :runtime
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.16'
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 0.16.0
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: liquid
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '4.0'
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 4.0.0
|
103
|
+
type: :runtime
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '4.0'
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 4.0.0
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: minitest
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '5.11'
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 5.11.3
|
123
|
+
type: :development
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '5.11'
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 5.11.3
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: minitest-reporters-json_reporter
|
135
|
+
requirement: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '1.0'
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 1.0.0
|
143
|
+
type: :development
|
144
|
+
prerelease: false
|
145
|
+
version_requirements: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - "~>"
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '1.0'
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 1.0.0
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: nexus
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '1.4'
|
160
|
+
- - ">="
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: 1.4.0
|
163
|
+
type: :development
|
164
|
+
prerelease: false
|
165
|
+
version_requirements: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - "~>"
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '1.4'
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: 1.4.0
|
173
|
+
- !ruby/object:Gem::Dependency
|
174
|
+
name: rubocop
|
175
|
+
requirement: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - "~>"
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '0.58'
|
180
|
+
- - ">="
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: 0.58.2
|
183
|
+
type: :development
|
184
|
+
prerelease: false
|
185
|
+
version_requirements: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - "~>"
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0.58'
|
190
|
+
- - ">="
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: 0.58.2
|
193
|
+
- !ruby/object:Gem::Dependency
|
194
|
+
name: simplecov
|
195
|
+
requirement: !ruby/object:Gem::Requirement
|
196
|
+
requirements:
|
197
|
+
- - "~>"
|
198
|
+
- !ruby/object:Gem::Version
|
199
|
+
version: '0.16'
|
200
|
+
- - ">="
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: 0.16.1
|
203
|
+
type: :development
|
204
|
+
prerelease: false
|
205
|
+
version_requirements: !ruby/object:Gem::Requirement
|
206
|
+
requirements:
|
207
|
+
- - "~>"
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: '0.16'
|
210
|
+
- - ">="
|
211
|
+
- !ruby/object:Gem::Version
|
212
|
+
version: 0.16.1
|
213
|
+
- !ruby/object:Gem::Dependency
|
214
|
+
name: webmock
|
215
|
+
requirement: !ruby/object:Gem::Requirement
|
216
|
+
requirements:
|
217
|
+
- - "~>"
|
218
|
+
- !ruby/object:Gem::Version
|
219
|
+
version: '3.4'
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: 3.4.2
|
223
|
+
type: :development
|
224
|
+
prerelease: false
|
225
|
+
version_requirements: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - "~>"
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '3.4'
|
230
|
+
- - ">="
|
231
|
+
- !ruby/object:Gem::Version
|
232
|
+
version: 3.4.2
|
233
|
+
description: Runs automated REST API based on YAML definiti
|
234
|
+
email: jindrich.skupa@gmail.com
|
235
|
+
executables: []
|
236
|
+
extensions: []
|
237
|
+
extra_rdoc_files: []
|
238
|
+
files:
|
239
|
+
- lib/api_mini_tester.rb
|
240
|
+
- lib/api_mini_tester/test_formatter.rb
|
241
|
+
- lib/api_mini_tester/test_scenario.rb
|
242
|
+
- lib/api_mini_tester/test_step.rb
|
243
|
+
- lib/api_mini_tester/test_suite.rb
|
244
|
+
homepage: http://rubygems.org/gems/api_mini_tester
|
245
|
+
licenses:
|
246
|
+
- MIT
|
247
|
+
metadata: {}
|
248
|
+
post_install_message:
|
249
|
+
rdoc_options: []
|
250
|
+
require_paths:
|
251
|
+
- lib
|
252
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
253
|
+
requirements:
|
254
|
+
- - ">="
|
255
|
+
- !ruby/object:Gem::Version
|
256
|
+
version: '0'
|
257
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
258
|
+
requirements:
|
259
|
+
- - ">="
|
260
|
+
- !ruby/object:Gem::Version
|
261
|
+
version: '0'
|
262
|
+
requirements: []
|
263
|
+
rubyforge_project:
|
264
|
+
rubygems_version: 2.6.8
|
265
|
+
signing_key:
|
266
|
+
specification_version: 4
|
267
|
+
summary: Runs automated REST API based on YAML definition
|
268
|
+
test_files: []
|