fitting 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/lib/fitting.rb +10 -23
- data/lib/fitting/configuration.rb +2 -1
- data/lib/fitting/documentation.rb +48 -0
- data/lib/fitting/route.rb +21 -0
- data/lib/fitting/route/coverage.rb +38 -0
- data/lib/fitting/route/requests.rb +148 -0
- data/lib/fitting/route/responses.rb +23 -0
- data/lib/fitting/statistics.rb +31 -0
- data/lib/fitting/storage/documentation.rb +2 -5
- data/lib/fitting/version.rb +1 -1
- metadata +8 -5
- data/lib/fitting/documentation/request/route.rb +0 -143
- data/lib/fitting/documentation/response/route.rb +0 -62
- data/lib/fitting/documentation/response/routes.rb +0 -53
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d1997d69b352bcdbba93f00c3e50cba25eb4d70
|
4
|
+
data.tar.gz: c39ea9c0cc9ee2c81d506f83c4f85ab614accb4f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68b687226ff3b178bb8fb774cc011a4c5a285ee13b246362dab05e15a71b18bbfee1b406a7f9a88494c8bd7a786fad4b43373382fa93495d3d86dc9cffa37402
|
7
|
+
data.tar.gz: 74928dc7e164fdad8fd68bc96fcf88753665cb49024fbb56db5bf68f706385f8a492254c4b1efec7960fbd6c0188a5264faca35af20e015bc2b78667fd272898
|
data/README.md
CHANGED
data/lib/fitting.rb
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
require 'fitting/version'
|
2
2
|
require 'fitting/configuration'
|
3
|
-
require 'fitting/documentation/response/route'
|
4
|
-
require 'fitting/documentation/response/routes'
|
5
|
-
require 'fitting/documentation/request/route'
|
6
|
-
require 'fitting/storage/responses'
|
7
3
|
require 'fitting/storage/documentation'
|
8
4
|
require 'fitting/storage/skip'
|
9
5
|
require 'fitting/matchers/response_matcher'
|
10
6
|
require 'rspec/core'
|
7
|
+
require 'fitting/statistics'
|
8
|
+
require 'fitting/documentation'
|
11
9
|
|
12
10
|
ERROR_EXIT_CODE = 1
|
13
11
|
|
@@ -34,28 +32,17 @@ module RSpec
|
|
34
32
|
|
35
33
|
return returned_exit_code if Fitting::Storage::Skip.get
|
36
34
|
|
37
|
-
|
38
|
-
Fitting::
|
39
|
-
Fitting.
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
Fitting::Storage::Responses.all,
|
45
|
-
responses_routes.black
|
46
|
-
)
|
47
|
-
response_routes_black.statistics
|
48
|
-
|
49
|
-
puts '[White list]'
|
50
|
-
response_routes_white = Fitting::Documentation::Response::Route.new(
|
51
|
-
Fitting::Storage::Responses.all,
|
52
|
-
responses_routes.white
|
53
|
-
)
|
54
|
-
response_routes_white.statistics_with_conformity_lists
|
35
|
+
statistics = Fitting::Statistics.new(
|
36
|
+
Fitting::Documentation.new(Fitting.configuration.tomogram, Fitting.configuration.white_list),
|
37
|
+
Fitting::Storage::Responses.all)
|
38
|
+
puts statistics
|
39
|
+
if Fitting.configuration.create_report_with_name
|
40
|
+
statistics.save(Fitting.configuration.create_report_with_name)
|
41
|
+
end
|
55
42
|
|
56
43
|
if Fitting.configuration.necessary_fully_implementation_of_responses &&
|
57
44
|
returned_exit_code == 0 &&
|
58
|
-
|
45
|
+
response.not_coverage?
|
59
46
|
return ERROR_EXIT_CODE
|
60
47
|
end
|
61
48
|
returned_exit_code
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
module Fitting
|
4
|
+
class Documentation
|
5
|
+
def initialize(tomogram, white_list)
|
6
|
+
@tomogram = tomogram
|
7
|
+
@white_list = white_list
|
8
|
+
end
|
9
|
+
|
10
|
+
def black
|
11
|
+
if @white_list
|
12
|
+
all.select do |response|
|
13
|
+
data = response.split(' ')
|
14
|
+
data[1] && !@white_list[data[1]] || (@white_list[data[1]] != [] && !@white_list[data[1]].include?(data[0]))
|
15
|
+
end
|
16
|
+
else
|
17
|
+
[]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def white
|
22
|
+
if @white_list
|
23
|
+
all.select do |response|
|
24
|
+
data = response.split(' ')
|
25
|
+
data[1] && @white_list[data[1]] && (@white_list[data[1]] == [] || @white_list[data[1]].include?(data[0]))
|
26
|
+
end
|
27
|
+
else
|
28
|
+
all
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def all
|
33
|
+
@all ||= MultiJson.load(@tomogram).inject([]) do |routes, request|
|
34
|
+
request['responses'].inject({}) do |responses, response|
|
35
|
+
responses[response['status']] ||= 0
|
36
|
+
responses[response['status']] += 1
|
37
|
+
responses
|
38
|
+
end.map do |status, indexes|
|
39
|
+
indexes.times do |index|
|
40
|
+
route = "#{request['method']}\t#{request['path']} #{status} #{index}"
|
41
|
+
routes.push(route)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
routes
|
45
|
+
end.uniq
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'fitting/route/coverage'
|
2
|
+
require 'fitting/route/requests'
|
3
|
+
require 'fitting/route/responses'
|
4
|
+
|
5
|
+
module Fitting
|
6
|
+
class Route
|
7
|
+
def initialize(all_responses, routes)
|
8
|
+
coverage = Fitting::Route::Coverage.new(all_responses, routes)
|
9
|
+
@requests = Fitting::Route::Requests.new(coverage)
|
10
|
+
@responses = Fitting::Route::Responses.new(routes, coverage)
|
11
|
+
end
|
12
|
+
|
13
|
+
def statistics
|
14
|
+
[@requests.statistics, @responses.statistics].join("\n\n")
|
15
|
+
end
|
16
|
+
|
17
|
+
def statistics_with_conformity_lists
|
18
|
+
[@requests.conformity_lists, statistics].join("\n\n")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
module Fitting
|
3
|
+
class Route
|
4
|
+
class Coverage
|
5
|
+
def initialize(coverage_responses, responses_routes)
|
6
|
+
@coverage_responses = coverage_responses
|
7
|
+
@responses_routes = responses_routes
|
8
|
+
end
|
9
|
+
|
10
|
+
def coverage
|
11
|
+
@coverage ||= @responses_routes - (@responses_routes - full_coverage)
|
12
|
+
end
|
13
|
+
|
14
|
+
def not_coverage
|
15
|
+
@not_coverage ||= @responses_routes - coverage
|
16
|
+
end
|
17
|
+
|
18
|
+
def cover_ratio
|
19
|
+
@cover_ratio ||= (coverage.size.to_f / @responses_routes.size.to_f * 100.0).round(2)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_hash
|
23
|
+
{
|
24
|
+
'coverage' => coverage,
|
25
|
+
'not coverage' => not_coverage
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def full_coverage
|
32
|
+
@coverage_responses.map do |response|
|
33
|
+
response.route if response.documented? && response.valid?
|
34
|
+
end.compact.uniq
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
module Fitting
|
4
|
+
class Route
|
5
|
+
class Requests
|
6
|
+
def initialize(coverage)
|
7
|
+
@coverage = coverage
|
8
|
+
end
|
9
|
+
|
10
|
+
def coverage_statistic
|
11
|
+
stat = {}
|
12
|
+
@coverage.coverage.map do |route|
|
13
|
+
macro_key = route.split(' ')[0..1].join(' ')
|
14
|
+
micro_key = route.split(' ')[2..3].join(' ')
|
15
|
+
stat[macro_key] ||= {}
|
16
|
+
stat[macro_key]['cover'] ||= []
|
17
|
+
stat[macro_key]['not_cover'] ||= []
|
18
|
+
stat[macro_key]['cover'].push(micro_key)
|
19
|
+
stat[macro_key]['all'] ||= []
|
20
|
+
stat[macro_key]['all'].push("✔ #{route.split(' ')[2..3].join(' ')}")
|
21
|
+
end
|
22
|
+
@coverage.not_coverage.map do |route|
|
23
|
+
macro_key = route.split(' ')[0..1].join(' ')
|
24
|
+
micro_key = route.split(' ')[2..3].join(' ')
|
25
|
+
stat[macro_key] ||= {}
|
26
|
+
stat[macro_key]['cover'] ||= []
|
27
|
+
stat[macro_key]['not_cover'] ||= []
|
28
|
+
stat[macro_key]['not_cover'].push(micro_key)
|
29
|
+
stat[macro_key]['all'] ||= []
|
30
|
+
stat[macro_key]['all'].push("✖ #{route.split(' ')[2..3].join(' ')}")
|
31
|
+
end
|
32
|
+
@stat = stat.inject(
|
33
|
+
{
|
34
|
+
'full cover' => [],
|
35
|
+
'partial cover' => [],
|
36
|
+
'no cover' => []
|
37
|
+
}
|
38
|
+
) do |res, date|
|
39
|
+
ratio = date.last['cover_ratio'] =
|
40
|
+
(date.last['cover'].size.to_f /
|
41
|
+
(date.last['cover'].size + date.last['not_cover'].size).to_f * 100.0).round(2)
|
42
|
+
info = {date.first => {
|
43
|
+
'cover' => date.last['cover'],
|
44
|
+
'not_cover' => date.last['not_cover'],
|
45
|
+
'all' => "#{beautiful_output(date.last)}"
|
46
|
+
}}
|
47
|
+
if ratio == 100.0
|
48
|
+
res['full cover'].push(info)
|
49
|
+
elsif ratio == 0.0
|
50
|
+
res['no cover'].push(info)
|
51
|
+
else
|
52
|
+
res['partial cover'].push(info)
|
53
|
+
end
|
54
|
+
path = date.first.split(' ')[1].size / 8
|
55
|
+
@max ||= 1
|
56
|
+
if path.size > @max
|
57
|
+
@max = path.size
|
58
|
+
end
|
59
|
+
res
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_hash
|
64
|
+
@stat ||= coverage_statistic
|
65
|
+
end
|
66
|
+
|
67
|
+
def fully_implemented
|
68
|
+
@stat ||= coverage_statistic
|
69
|
+
@fully_implemented ||= @stat['full cover'].map do |response|
|
70
|
+
"#{response.first.to_a.first.split(' ').join("\t")}#{"\t"*(@max-response.first.to_a.first.split(' ')[1].size/8)}#{response.first.to_a.last['all']}"
|
71
|
+
end.sort do |first, second|
|
72
|
+
first.split("\t")[1] <=> second.split("\t")[1]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def partially_implemented
|
77
|
+
@stat ||= coverage_statistic
|
78
|
+
@partially_implemented ||= @stat['partial cover'].map do |response|
|
79
|
+
"#{response.first.to_a.first.split(' ').join("\t")}#{"\t"*(@max-response.first.to_a.first.split(' ')[1].size/8)}#{response.first.to_a.last['all']}"
|
80
|
+
end.sort do |first, second|
|
81
|
+
first.split("\t")[1] <=> second.split("\t")[1]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def no_implemented
|
86
|
+
@stat ||= coverage_statistic
|
87
|
+
@no_implemented ||= @stat['no cover'].map do |response|
|
88
|
+
"#{response.first.to_a.first.split(' ').join("\t")}#{"\t"*(@max-response.first.to_a.first.split(' ')[1].size/8)}#{response.first.to_a.last['all']}"
|
89
|
+
end.sort do |first, second|
|
90
|
+
first.split("\t")[1] <=> second.split("\t")[1]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def statistics
|
95
|
+
@stat ||= coverage_statistic
|
96
|
+
full_count = @stat.to_hash['full cover'].size
|
97
|
+
part_count = @stat.to_hash['partial cover'].size
|
98
|
+
no_count = @stat.to_hash['no cover'].size
|
99
|
+
total_count = full_count + part_count + no_count
|
100
|
+
full_percentage = (full_count.to_f / total_count.to_f * 100.0).round(2)
|
101
|
+
part_percentage = (part_count.to_f / total_count.to_f * 100.0).round(2)
|
102
|
+
no_percentage = (no_count.to_f / total_count.to_f * 100.0).round(2)
|
103
|
+
|
104
|
+
[
|
105
|
+
"API requests with fully implemented responses: #{full_count} (#{full_percentage}% of #{total_count}).",
|
106
|
+
"API requests with partially implemented responses: #{part_count} (#{part_percentage}% of #{total_count}).",
|
107
|
+
"API requests with no implemented responses: #{no_count} (#{no_percentage}% of #{total_count})."
|
108
|
+
].join("\n")
|
109
|
+
end
|
110
|
+
|
111
|
+
def conformity_lists
|
112
|
+
@stat ||= coverage_statistic
|
113
|
+
fully_implemented ||= self.fully_implemented.join("\n")
|
114
|
+
partially_implemented ||= self.partially_implemented.join("\n")
|
115
|
+
no_implemented ||= self.no_implemented.join("\n")
|
116
|
+
|
117
|
+
[
|
118
|
+
['Fully conforming requests:', fully_implemented].join("\n"),
|
119
|
+
['Partially conforming requests:', partially_implemented].join("\n"),
|
120
|
+
['Non-conforming requests:', no_implemented].join("\n")
|
121
|
+
].join("\n\n")
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def beautiful_output(hash)
|
127
|
+
methods = {}
|
128
|
+
res = []
|
129
|
+
hash['cover'].map do |response|
|
130
|
+
method, index = response.split(' ')
|
131
|
+
methods[method] ||= []
|
132
|
+
methods[method][index.to_i] = {'method' => method, 'cover' => true}
|
133
|
+
end
|
134
|
+
hash['not_cover'].map do |response|
|
135
|
+
method, index = response.split(' ')
|
136
|
+
methods[method] ||= []
|
137
|
+
methods[method][index.to_i] = {'method' => method, 'cover' => false}
|
138
|
+
end
|
139
|
+
methods.map do |method|
|
140
|
+
method.last.size.times do |index|
|
141
|
+
res.push("#{method.last[index]['cover'] ? '✔' : '✖'} #{method.first}")
|
142
|
+
end
|
143
|
+
end
|
144
|
+
res.join(' ')
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Fitting
|
2
|
+
class Route
|
3
|
+
class Responses
|
4
|
+
def initialize(routes, coverage)
|
5
|
+
@routes = routes
|
6
|
+
@coverage = coverage
|
7
|
+
end
|
8
|
+
|
9
|
+
def statistics
|
10
|
+
valid_count = @coverage.coverage.size
|
11
|
+
valid_percentage = @coverage.cover_ratio
|
12
|
+
total_count = @routes.size
|
13
|
+
invalid_count = @coverage.not_coverage.size
|
14
|
+
invalid_percentage = (100.0 - @coverage.cover_ratio).round(2)
|
15
|
+
|
16
|
+
[
|
17
|
+
"API responses conforming to the blueprint: #{valid_count} (#{valid_percentage}% of #{total_count}).",
|
18
|
+
"API responses with validation errors or untested: #{invalid_count} (#{invalid_percentage}% of #{total_count})."
|
19
|
+
].join("\n")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'fitting/route'
|
2
|
+
|
3
|
+
module Fitting
|
4
|
+
class Statistics
|
5
|
+
def initialize(documentation, all_responses)
|
6
|
+
@documentation = documentation
|
7
|
+
@black_route = Fitting::Route.new(all_responses, @documentation.black)
|
8
|
+
@white_route = Fitting::Route.new(all_responses, @documentation.white)
|
9
|
+
end
|
10
|
+
|
11
|
+
def not_coverage?
|
12
|
+
@white_route.not_coverage.present?
|
13
|
+
end
|
14
|
+
|
15
|
+
def save(name)
|
16
|
+
File.open(name, 'w') { |file| file.write(to_s) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
if @documentation.black.any?
|
21
|
+
[
|
22
|
+
['[Black list]', @black_route.statistics].join("\n"),
|
23
|
+
['[White list]', @white_route.statistics_with_conformity_lists].join("\n"),
|
24
|
+
""
|
25
|
+
].join("\n\n")
|
26
|
+
else
|
27
|
+
[@white_route.statistics_with_conformity_lists, "\n\n"].join
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,15 +1,12 @@
|
|
1
1
|
require 'tomogram_routing'
|
2
|
+
require 'fitting/configuration'
|
2
3
|
|
3
4
|
module Fitting
|
4
5
|
module Storage
|
5
6
|
module Documentation
|
6
7
|
class << self
|
7
8
|
def tomogram
|
8
|
-
@tomogram ||= TomogramRouting::Tomogram.craft(
|
9
|
-
end
|
10
|
-
|
11
|
-
def hash
|
12
|
-
Fitting.configuration.tomogram
|
9
|
+
@tomogram ||= TomogramRouting::Tomogram.craft(Fitting.configuration.tomogram)
|
13
10
|
end
|
14
11
|
end
|
15
12
|
end
|
data/lib/fitting/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fitting
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- d.efimov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03-
|
11
|
+
date: 2017-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json-schema
|
@@ -212,12 +212,15 @@ files:
|
|
212
212
|
- fitting.gemspec
|
213
213
|
- lib/fitting.rb
|
214
214
|
- lib/fitting/configuration.rb
|
215
|
-
- lib/fitting/documentation
|
216
|
-
- lib/fitting/documentation/response/route.rb
|
217
|
-
- lib/fitting/documentation/response/routes.rb
|
215
|
+
- lib/fitting/documentation.rb
|
218
216
|
- lib/fitting/matchers/response_matcher.rb
|
219
217
|
- lib/fitting/request.rb
|
220
218
|
- lib/fitting/response.rb
|
219
|
+
- lib/fitting/route.rb
|
220
|
+
- lib/fitting/route/coverage.rb
|
221
|
+
- lib/fitting/route/requests.rb
|
222
|
+
- lib/fitting/route/responses.rb
|
223
|
+
- lib/fitting/statistics.rb
|
221
224
|
- lib/fitting/storage/documentation.rb
|
222
225
|
- lib/fitting/storage/responses.rb
|
223
226
|
- lib/fitting/storage/skip.rb
|
@@ -1,143 +0,0 @@
|
|
1
|
-
require 'multi_json'
|
2
|
-
|
3
|
-
module Fitting
|
4
|
-
module Documentation
|
5
|
-
module Request
|
6
|
-
class Route
|
7
|
-
def initialize(response_routes)
|
8
|
-
@response_routes = response_routes
|
9
|
-
end
|
10
|
-
|
11
|
-
def coverage_statistic
|
12
|
-
stat = {}
|
13
|
-
@response_routes.coverage.map do |route|
|
14
|
-
macro_key = route.split(' ')[0..1].join(' ')
|
15
|
-
micro_key = route.split(' ')[2..3].join(' ')
|
16
|
-
stat[macro_key] ||= {}
|
17
|
-
stat[macro_key]['cover'] ||= []
|
18
|
-
stat[macro_key]['not_cover'] ||= []
|
19
|
-
stat[macro_key]['cover'].push(micro_key)
|
20
|
-
stat[macro_key]['all'] ||= []
|
21
|
-
stat[macro_key]['all'].push("✔ #{route.split(' ')[2..3].join(' ')}")
|
22
|
-
end
|
23
|
-
@response_routes.not_coverage.map do |route|
|
24
|
-
macro_key = route.split(' ')[0..1].join(' ')
|
25
|
-
micro_key = route.split(' ')[2..3].join(' ')
|
26
|
-
stat[macro_key] ||= {}
|
27
|
-
stat[macro_key]['cover'] ||= []
|
28
|
-
stat[macro_key]['not_cover'] ||= []
|
29
|
-
stat[macro_key]['not_cover'].push(micro_key)
|
30
|
-
stat[macro_key]['all'] ||= []
|
31
|
-
stat[macro_key]['all'].push("✖ #{route.split(' ')[2..3].join(' ')}")
|
32
|
-
end
|
33
|
-
@stat = stat.inject(
|
34
|
-
{
|
35
|
-
'full cover' => [],
|
36
|
-
'partial cover' => [],
|
37
|
-
'no cover' => []
|
38
|
-
}
|
39
|
-
) do |res, date|
|
40
|
-
ratio = date.last['cover_ratio'] =
|
41
|
-
(date.last['cover'].size.to_f /
|
42
|
-
(date.last['cover'].size + date.last['not_cover'].size).to_f * 100.0).round(2)
|
43
|
-
info = {date.first => {
|
44
|
-
'cover' => date.last['cover'],
|
45
|
-
'not_cover' => date.last['not_cover'],
|
46
|
-
'all' => "#{beautiful_output(date.last)}"
|
47
|
-
}}
|
48
|
-
if ratio == 100.0
|
49
|
-
res['full cover'].push(info)
|
50
|
-
elsif ratio == 0.0
|
51
|
-
res['no cover'].push(info)
|
52
|
-
else
|
53
|
-
res['partial cover'].push(info)
|
54
|
-
end
|
55
|
-
path = date.first.split(' ')[1].size / 8
|
56
|
-
@max ||= 1
|
57
|
-
if path.size > @max
|
58
|
-
@max = path.size
|
59
|
-
end
|
60
|
-
res
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def to_hash
|
65
|
-
@stat ||= coverage_statistic
|
66
|
-
end
|
67
|
-
|
68
|
-
def fully_implemented
|
69
|
-
@stat ||= coverage_statistic
|
70
|
-
@fully_implemented ||= @stat['full cover'].map do |response|
|
71
|
-
"#{response.first.to_a.first.split(' ').join("\t")}#{"\t"*(@max-response.first.to_a.first.split(' ')[1].size/8)}#{response.first.to_a.last['all']}"
|
72
|
-
end.sort do |first, second|
|
73
|
-
first.split("\t")[1] <=> second.split("\t")[1]
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def partially_implemented
|
78
|
-
@stat ||= coverage_statistic
|
79
|
-
@partially_implemented ||= @stat['partial cover'].map do |response|
|
80
|
-
"#{response.first.to_a.first.split(' ').join("\t")}#{"\t"*(@max-response.first.to_a.first.split(' ')[1].size/8)}#{response.first.to_a.last['all']}"
|
81
|
-
end.sort do |first, second|
|
82
|
-
first.split("\t")[1] <=> second.split("\t")[1]
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def no_implemented
|
87
|
-
@stat ||= coverage_statistic
|
88
|
-
@no_implemented ||= @stat['no cover'].map do |response|
|
89
|
-
"#{response.first.to_a.first.split(' ').join("\t")}#{"\t"*(@max-response.first.to_a.first.split(' ')[1].size/8)}#{response.first.to_a.last['all']}"
|
90
|
-
end.sort do |first, second|
|
91
|
-
first.split("\t")[1] <=> second.split("\t")[1]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def conformity_lists
|
96
|
-
puts "Fully conforming requests: \n#{fully_implemented.join("\n")}"
|
97
|
-
puts
|
98
|
-
puts "Partially conforming requests: \n#{partially_implemented.join("\n")}"
|
99
|
-
puts
|
100
|
-
puts "Non-conforming requests: \n#{no_implemented.join("\n")}"
|
101
|
-
puts
|
102
|
-
end
|
103
|
-
|
104
|
-
def statistics
|
105
|
-
full_count = to_hash['full cover'].size
|
106
|
-
part_count = to_hash['partial cover'].size
|
107
|
-
no_count = to_hash['no cover'].size
|
108
|
-
total_count = full_count + part_count + no_count
|
109
|
-
full_percentage = (full_count.to_f / total_count.to_f * 100.0).round(2)
|
110
|
-
part_percentage = (part_count.to_f / total_count.to_f * 100.0).round(2)
|
111
|
-
no_percentage = (no_count.to_f / total_count.to_f * 100.0).round(2)
|
112
|
-
puts "API requests with fully implemented responses: #{full_count} (#{full_percentage}% of #{total_count})."
|
113
|
-
puts "API requests with partially implemented responses: #{part_count} (#{part_percentage}% of #{total_count})."
|
114
|
-
puts "API requests with no implemented responses: #{no_count} (#{no_percentage}% of #{total_count})."
|
115
|
-
puts
|
116
|
-
end
|
117
|
-
|
118
|
-
private
|
119
|
-
|
120
|
-
def beautiful_output(hash)
|
121
|
-
methods = {}
|
122
|
-
res = []
|
123
|
-
hash['cover'].map do |response|
|
124
|
-
method, index = response.split(' ')
|
125
|
-
methods[method] ||= []
|
126
|
-
methods[method][index.to_i] = {'method' => method, 'cover' => true}
|
127
|
-
end
|
128
|
-
hash['not_cover'].map do |response|
|
129
|
-
method, index = response.split(' ')
|
130
|
-
methods[method] ||= []
|
131
|
-
methods[method][index.to_i] = {'method' => method, 'cover' => false}
|
132
|
-
end
|
133
|
-
methods.map do |method|
|
134
|
-
method.last.size.times do |index|
|
135
|
-
res.push("#{method.last[index]['cover'] ? '✔' : '✖'} #{method.first}")
|
136
|
-
end
|
137
|
-
end
|
138
|
-
res.join(' ')
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
require 'multi_json'
|
2
|
-
require 'fitting/documentation/request/route'
|
3
|
-
|
4
|
-
module Fitting
|
5
|
-
module Documentation
|
6
|
-
module Response
|
7
|
-
class Route
|
8
|
-
def initialize(coverage_responses, responses_routes)
|
9
|
-
@coverage_responses = coverage_responses
|
10
|
-
@responses_routes = responses_routes
|
11
|
-
end
|
12
|
-
|
13
|
-
def coverage
|
14
|
-
@coverage ||= @responses_routes - (@responses_routes - full_coverage)
|
15
|
-
end
|
16
|
-
|
17
|
-
def not_coverage
|
18
|
-
@not_coverage ||= @responses_routes - coverage
|
19
|
-
end
|
20
|
-
|
21
|
-
def cover_ratio
|
22
|
-
@cover_ratio ||= (coverage.size.to_f / @responses_routes.size.to_f * 100.0).round(2)
|
23
|
-
end
|
24
|
-
|
25
|
-
def to_hash
|
26
|
-
{
|
27
|
-
'coverage' => coverage,
|
28
|
-
'not coverage' => not_coverage
|
29
|
-
}
|
30
|
-
end
|
31
|
-
|
32
|
-
def statistics_with_conformity_lists
|
33
|
-
@request_routes ||= Fitting::Documentation::Request::Route.new(self)
|
34
|
-
@request_routes.conformity_lists
|
35
|
-
statistics
|
36
|
-
end
|
37
|
-
|
38
|
-
def statistics
|
39
|
-
@request_routes ||= Fitting::Documentation::Request::Route.new(self)
|
40
|
-
@request_routes.statistics
|
41
|
-
|
42
|
-
valid_count = coverage.size
|
43
|
-
valid_percentage = cover_ratio
|
44
|
-
total_count = @responses_routes.size
|
45
|
-
invalid_count = not_coverage.size
|
46
|
-
invalid_percentage = 100.0 - cover_ratio
|
47
|
-
puts "API responses conforming to the blueprint: #{valid_count} (#{valid_percentage}% of #{total_count})."
|
48
|
-
puts "API responses with validation errors or untested: #{invalid_count} (#{invalid_percentage}% of #{total_count})."
|
49
|
-
puts
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
def full_coverage
|
55
|
-
@coverage_responses.map do |response|
|
56
|
-
response.route if response.documented? && response.valid?
|
57
|
-
end.compact.uniq
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'multi_json'
|
2
|
-
require 'fitting/documentation/request/route'
|
3
|
-
|
4
|
-
module Fitting
|
5
|
-
module Documentation
|
6
|
-
module Response
|
7
|
-
class Routes
|
8
|
-
def initialize(tomogram, white_list)
|
9
|
-
@tomogram = tomogram
|
10
|
-
@white_list = white_list
|
11
|
-
end
|
12
|
-
|
13
|
-
def black
|
14
|
-
if @white_list
|
15
|
-
all.select do |response|
|
16
|
-
data = response.split(' ')
|
17
|
-
data[1] && !@white_list[data[1]] || (@white_list[data[1]] != [] && !@white_list[data[1]].include?(data[0]))
|
18
|
-
end
|
19
|
-
else
|
20
|
-
[]
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def white
|
25
|
-
if @white_list
|
26
|
-
all.select do |response|
|
27
|
-
data = response.split(' ')
|
28
|
-
data[1] && @white_list[data[1]] && (@white_list[data[1]] == [] || @white_list[data[1]].include?(data[0]))
|
29
|
-
end
|
30
|
-
else
|
31
|
-
all
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def all
|
36
|
-
@all ||= MultiJson.load(@tomogram).inject([]) do |routes, request|
|
37
|
-
request['responses'].inject({}) do |responses, response|
|
38
|
-
responses[response['status']] ||= 0
|
39
|
-
responses[response['status']] += 1
|
40
|
-
responses
|
41
|
-
end.map do |status, indexes|
|
42
|
-
indexes.times do |index|
|
43
|
-
route = "#{request['method']}\t#{request['path']} #{status} #{index}"
|
44
|
-
routes.push(route)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
routes
|
48
|
-
end.uniq
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|