fitting 2.2.0 → 2.3.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/CHANGELOG.md +11 -0
- data/README.md +7 -0
- data/lib/fitting.rb +1 -3
- data/lib/fitting/configuration.rb +41 -11
- data/lib/fitting/configuration/legacy.rb +41 -0
- data/lib/fitting/configuration/yaml.rb +60 -0
- data/lib/fitting/matchers/response_matcher.rb +33 -14
- data/lib/fitting/records/documented/request.rb +53 -0
- data/lib/fitting/records/tested/request.rb +30 -0
- data/lib/fitting/records/tested/response.rb +19 -0
- data/lib/fitting/records/unit/json_schema.rb +25 -0
- data/lib/fitting/records/unit/request.rb +36 -0
- data/lib/fitting/records/unit/response.rb +31 -0
- data/lib/fitting/statistics.rb +14 -19
- data/lib/fitting/statistics/analysis.rb +24 -0
- data/lib/fitting/statistics/great.rb +13 -0
- data/lib/fitting/statistics/list.rb +45 -0
- data/lib/fitting/statistics/lists.rb +52 -0
- data/lib/fitting/statistics/measurement.rb +94 -0
- data/lib/fitting/statistics/not_covered_responses.rb +13 -0
- data/lib/fitting/statistics/percent.rb +19 -0
- data/lib/fitting/statistics/requests_stats.rb +40 -0
- data/lib/fitting/statistics/responses_stats.rb +32 -0
- data/lib/fitting/statistics/template.rb +90 -0
- data/lib/fitting/storage/responses.rb +6 -28
- data/lib/fitting/version.rb +1 -1
- metadata +20 -11
- data/lib/fitting/route.rb +0 -28
- data/lib/fitting/route/coverage.rb +0 -45
- data/lib/fitting/route/requests.rb +0 -25
- data/lib/fitting/route/requests/combine.rb +0 -113
- data/lib/fitting/route/requests/coverage.rb +0 -58
- data/lib/fitting/route/requests/lists.rb +0 -92
- data/lib/fitting/route/requests/statistics.rb +0 -40
- data/lib/fitting/route/responses.rb +0 -24
- data/lib/fitting/storage/documentation.rb +0 -22
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'fitting/records/unit/json_schema'
|
2
|
+
|
3
|
+
module Fitting
|
4
|
+
class Records
|
5
|
+
class Unit
|
6
|
+
class Response
|
7
|
+
def initialize(documented_response, tested_responses)
|
8
|
+
@documented_response = documented_response
|
9
|
+
@tested_responses = tested_responses
|
10
|
+
end
|
11
|
+
|
12
|
+
def status
|
13
|
+
@status ||= @documented_response['status']
|
14
|
+
end
|
15
|
+
|
16
|
+
def json_schemas
|
17
|
+
@json_schemas ||= @documented_response['json_schemas'].inject([]) do |res, documented_json_schema|
|
18
|
+
res.push(Fitting::Records::Unit::JsonSchema.new(documented_json_schema, tested_bodies))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def tested_bodies
|
23
|
+
@tested_bodies ||= @tested_responses.inject([]) do |res, tested_response|
|
24
|
+
next res unless status == tested_response.status.to_s
|
25
|
+
res.push(tested_response.body)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/fitting/statistics.rb
CHANGED
@@ -1,30 +1,25 @@
|
|
1
|
-
require 'fitting/
|
2
|
-
require 'fileutils'
|
1
|
+
require 'fitting/statistics/template'
|
3
2
|
|
4
3
|
module Fitting
|
5
4
|
class Statistics
|
6
|
-
def initialize(
|
7
|
-
@
|
8
|
-
@black_route = Fitting::Route.new(all_responses, @documentation.black, strict)
|
9
|
-
@white_route = Fitting::Route.new(all_responses, @documentation.white, strict)
|
5
|
+
def initialize(tested_requests)
|
6
|
+
@tested_requests = tested_requests
|
10
7
|
end
|
11
8
|
|
12
9
|
def save
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
if @documentation.black.any?
|
20
|
-
[
|
21
|
-
['[Black list]', @black_route.statistics_with_conformity_lists].join("\n"),
|
22
|
-
['[White list]', @white_route.statistics_with_conformity_lists].join("\n"),
|
23
|
-
''
|
24
|
-
].join("\n\n")
|
10
|
+
make_dir('fitting')
|
11
|
+
if Fitting.configuration.is_a?(Array)
|
12
|
+
Fitting.configuration.each do |config|
|
13
|
+
make_dir("fitting/#{config.title}")
|
14
|
+
Fitting::Statistics::Template.new(@tested_requests, config).save
|
15
|
+
end
|
25
16
|
else
|
26
|
-
|
17
|
+
Fitting::Statistics::Template.new(@tested_requests, Fitting.configuration).save
|
27
18
|
end
|
28
19
|
end
|
20
|
+
|
21
|
+
def make_dir(dir_name)
|
22
|
+
FileUtils.mkdir_p(dir_name)
|
23
|
+
end
|
29
24
|
end
|
30
25
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'fitting/statistics/lists'
|
2
|
+
require 'fitting/statistics/requests_stats'
|
3
|
+
require 'fitting/statistics/responses_stats'
|
4
|
+
require 'fitting/statistics/great'
|
5
|
+
require 'fitting/statistics/not_covered_responses'
|
6
|
+
|
7
|
+
module Fitting
|
8
|
+
class Statistics
|
9
|
+
class Analysis
|
10
|
+
def initialize(measurement)
|
11
|
+
@measurement = measurement
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
[
|
16
|
+
Fitting::Statistics::Lists.new(@measurement).to_s,
|
17
|
+
Fitting::Statistics::RequestsStats.new(@measurement).to_s,
|
18
|
+
Fitting::Statistics::ResponsesStats.new(@measurement).to_s,
|
19
|
+
Fitting::Statistics::Great.new(@measurement).to_s
|
20
|
+
].compact.join("\n\n")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Fitting
|
2
|
+
class Statistics
|
3
|
+
class Great
|
4
|
+
def initialize(measurement)
|
5
|
+
@measurement = measurement
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
return 'All responses are 100% valid! Great job!' if @measurement.cover_responses == @measurement.all_responses
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Fitting
|
2
|
+
class Statistics
|
3
|
+
class List
|
4
|
+
def initialize(coverage, max_response_path)
|
5
|
+
@coverage = coverage
|
6
|
+
@max_response_path = max_response_path
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
list_sort.inject([]) do |res, request|
|
11
|
+
res.push("#{request.method}\t#{request.path}#{responses_stat(request)}")
|
12
|
+
end.join("\n")
|
13
|
+
end
|
14
|
+
|
15
|
+
def list_sort
|
16
|
+
@coverage.sort do |first, second|
|
17
|
+
first.path.to_s <=> second.path.to_s
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def responses_stat(request)
|
22
|
+
tab = "\t" * ((@max_response_path - request.path.to_s.size / 8) + 3)
|
23
|
+
tab + request.responses.to_a.each_with_object([]) do |response, res|
|
24
|
+
response_stat(response, res)
|
25
|
+
end.join(' ')
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def response_stat(response, res)
|
31
|
+
response.json_schemas.map do |json_schema|
|
32
|
+
json_schema_stat(res, json_schema, response)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def json_schema_stat(res, json_schema, response)
|
37
|
+
if json_schema.bodies == []
|
38
|
+
res.push("✖ #{response.status}")
|
39
|
+
else
|
40
|
+
res.push("✔ #{response.status}")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'fitting/statistics/list'
|
2
|
+
|
3
|
+
module Fitting
|
4
|
+
class Statistics
|
5
|
+
class Lists
|
6
|
+
def initialize(measurement)
|
7
|
+
@measurement = measurement
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
[
|
12
|
+
coverage_fully_stat,
|
13
|
+
coverage_partially_stat,
|
14
|
+
coverage_non_stat
|
15
|
+
].compact.join("\n\n")
|
16
|
+
end
|
17
|
+
|
18
|
+
def coverage_fully_stat
|
19
|
+
if @measurement.coverage_fully == []
|
20
|
+
nil
|
21
|
+
else
|
22
|
+
[
|
23
|
+
'Fully conforming requests:',
|
24
|
+
Fitting::Statistics::List.new(@measurement.coverage_fully, @measurement.max_response_path).to_s
|
25
|
+
].join("\n")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def coverage_partially_stat
|
30
|
+
if @measurement.coverage_partially == []
|
31
|
+
nil
|
32
|
+
else
|
33
|
+
[
|
34
|
+
'Partially conforming requests:',
|
35
|
+
Fitting::Statistics::List.new(@measurement.coverage_partially, @measurement.max_response_path).to_s
|
36
|
+
].join("\n")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def coverage_non_stat
|
41
|
+
if @measurement.coverage_non == []
|
42
|
+
nil
|
43
|
+
else
|
44
|
+
[
|
45
|
+
'Non-conforming requests:',
|
46
|
+
Fitting::Statistics::List.new(@measurement.coverage_non, @measurement.max_response_path).to_s
|
47
|
+
].join("\n")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Fitting
|
2
|
+
class Statistics
|
3
|
+
class Measurement
|
4
|
+
attr_reader :requests, :all_responses, :cover_responses, :not_cover_responses, :max_response_path,
|
5
|
+
:coverage_fully, :coverage_non, :coverage_partially, :not_covered_responses
|
6
|
+
|
7
|
+
def initialize(requests)
|
8
|
+
@requests = requests
|
9
|
+
@all_responses = 0
|
10
|
+
@cover_responses = 0
|
11
|
+
@not_cover_responses = 0
|
12
|
+
@max_response_path = 0
|
13
|
+
@coverage_fully = []
|
14
|
+
@coverage_non = []
|
15
|
+
@coverage_partially = []
|
16
|
+
@not_covered_responses = []
|
17
|
+
check_responses
|
18
|
+
end
|
19
|
+
|
20
|
+
def check_responses
|
21
|
+
return if @ready
|
22
|
+
|
23
|
+
@requests.map do |request|
|
24
|
+
chech_request(request)
|
25
|
+
end
|
26
|
+
|
27
|
+
@ready = true
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def chech_request(request)
|
33
|
+
check_cover(request)
|
34
|
+
coverage_push(request)
|
35
|
+
|
36
|
+
if request.path.to_s.size / 8 > @max_response_path
|
37
|
+
@max_response_path = request.path.to_s.size / 8
|
38
|
+
end
|
39
|
+
request.responses.map do |response|
|
40
|
+
check_response(response, request)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def check_response(response, request)
|
45
|
+
json_schema_index = 0
|
46
|
+
response.json_schemas.map do |json_schema|
|
47
|
+
json_schema_index = check_json_schema(json_schema, request, response, json_schema_index)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def check_json_schema(json_schema, request, response, json_schema_index)
|
52
|
+
if json_schema.bodies == []
|
53
|
+
@not_cover_responses += 1
|
54
|
+
@not_covered_responses.push("#{request.method}\t#{request.path} #{response.status} #{json_schema_index}")
|
55
|
+
else
|
56
|
+
@cover_responses += 1
|
57
|
+
end
|
58
|
+
@all_responses += 1
|
59
|
+
json_schema_index + 1
|
60
|
+
end
|
61
|
+
|
62
|
+
def coverage_push(request)
|
63
|
+
if @all == @cover
|
64
|
+
@coverage_fully.push(request)
|
65
|
+
elsif @all == @not_cover
|
66
|
+
@coverage_non.push(request)
|
67
|
+
else
|
68
|
+
@coverage_partially.push(request)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def check_cover(request)
|
73
|
+
@all = 0
|
74
|
+
@cover = 0
|
75
|
+
@not_cover = 0
|
76
|
+
|
77
|
+
request.responses.map do |response|
|
78
|
+
response.json_schemas.map do |json_schema|
|
79
|
+
count_cover(json_schema)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def count_cover(json_schema)
|
85
|
+
@all += 1
|
86
|
+
if json_schema.bodies == []
|
87
|
+
@not_cover += 1
|
88
|
+
else
|
89
|
+
@cover += 1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Fitting
|
2
|
+
class Statistics
|
3
|
+
class Percent
|
4
|
+
def initialize(divider, dividend)
|
5
|
+
@divider = divider
|
6
|
+
@dividend = dividend
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_f
|
10
|
+
return 0.to_f if @divider.zero?
|
11
|
+
(@dividend.to_f / @divider.to_f * 100.0).round(2)
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
"#{@dividend} (#{to_f}% of #{@divider})"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'fitting/statistics/percent'
|
2
|
+
|
3
|
+
module Fitting
|
4
|
+
class Statistics
|
5
|
+
class RequestsStats
|
6
|
+
def initialize(measurement)
|
7
|
+
@measurement = measurement
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
@to_s ||= [
|
12
|
+
"API requests with fully implemented responses: #{fully}.",
|
13
|
+
"API requests with partially implemented responses: #{partially}.",
|
14
|
+
"API requests with no implemented responses: #{non}."
|
15
|
+
].join("\n")
|
16
|
+
end
|
17
|
+
|
18
|
+
def fully
|
19
|
+
@fully ||= Fitting::Statistics::Percent.new(
|
20
|
+
@measurement.requests.size,
|
21
|
+
@measurement.coverage_fully.size
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def partially
|
26
|
+
@partially ||= Fitting::Statistics::Percent.new(
|
27
|
+
@measurement.requests.size,
|
28
|
+
@measurement.coverage_partially.size
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def non
|
33
|
+
@non ||= Fitting::Statistics::Percent.new(
|
34
|
+
@measurement.requests.size,
|
35
|
+
@measurement.coverage_non.size
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'fitting/statistics/percent'
|
2
|
+
|
3
|
+
module Fitting
|
4
|
+
class Statistics
|
5
|
+
class ResponsesStats
|
6
|
+
def initialize(measurement)
|
7
|
+
@measurement = measurement
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
@to_s ||= [
|
12
|
+
"API responses conforming to the blueprint: #{cover}.",
|
13
|
+
"API responses with validation errors or untested: #{not_cover}."
|
14
|
+
].join("\n")
|
15
|
+
end
|
16
|
+
|
17
|
+
def cover
|
18
|
+
@cover ||= Fitting::Statistics::Percent.new(
|
19
|
+
@measurement.all_responses,
|
20
|
+
@measurement.cover_responses
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def not_cover
|
25
|
+
@not_cover ||= Fitting::Statistics::Percent.new(
|
26
|
+
@measurement.all_responses,
|
27
|
+
@measurement.not_cover_responses
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'fitting/statistics/not_covered_responses'
|
2
|
+
require 'fitting/statistics/analysis'
|
3
|
+
require 'fitting/statistics/measurement'
|
4
|
+
require 'fitting/records/unit/request'
|
5
|
+
require 'fitting/storage/white_list'
|
6
|
+
require 'fitting/records/documented/request'
|
7
|
+
|
8
|
+
module Fitting
|
9
|
+
class Statistics
|
10
|
+
class Template
|
11
|
+
def initialize(tested_requests, config)
|
12
|
+
@tested_requests = tested_requests
|
13
|
+
@config = config
|
14
|
+
end
|
15
|
+
|
16
|
+
def save
|
17
|
+
File.open(@config.stats_path, 'w') { |file| file.write(stats) }
|
18
|
+
File.open(@config.not_covered_path, 'w') { |file| file.write(not_covered) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def stats
|
22
|
+
if documented.to_a.size > documented_requests_white.size
|
23
|
+
[
|
24
|
+
['[Black list]', black_statistics].join("\n"),
|
25
|
+
['[White list]', white_statistics].join("\n"),
|
26
|
+
''
|
27
|
+
].join("\n\n")
|
28
|
+
else
|
29
|
+
[white_statistics, "\n\n"].join
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def not_covered
|
34
|
+
Fitting::Statistics::NotCoveredResponses.new(white_measurement).to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
def white_statistics
|
38
|
+
@white_statistics ||= Fitting::Statistics::Analysis.new(white_measurement)
|
39
|
+
end
|
40
|
+
|
41
|
+
def black_statistics
|
42
|
+
@black_statistics ||= Fitting::Statistics::Analysis.new(black_measurement)
|
43
|
+
end
|
44
|
+
|
45
|
+
def white_measurement
|
46
|
+
@white_measurement ||= Fitting::Statistics::Measurement.new(white_unit)
|
47
|
+
end
|
48
|
+
|
49
|
+
def black_measurement
|
50
|
+
@black_measurement ||= Fitting::Statistics::Measurement.new(black_unit)
|
51
|
+
end
|
52
|
+
|
53
|
+
def white_unit
|
54
|
+
@white_unit_requests ||= documented_requests_white.inject([]) do |res, documented_request|
|
55
|
+
res.push(Fitting::Records::Unit::Request.new(documented_request, @tested_requests))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def black_unit
|
60
|
+
@black_unit_requests ||= documented_requests_black.inject([]) do |res, documented_request|
|
61
|
+
res.push(Fitting::Records::Unit::Request.new(documented_request, @tested_requests))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def documented_requests_white
|
66
|
+
@documented_requests_white ||= documented.find_all(&:white)
|
67
|
+
end
|
68
|
+
|
69
|
+
def documented_requests_black
|
70
|
+
@documented_requests_black ||= documented.find_all do |request|
|
71
|
+
!request.white
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def documented
|
76
|
+
@documented_requests ||= @config.tomogram.to_hash.inject([]) do |res, tomogram_request|
|
77
|
+
res.push(Fitting::Records::Documented::Request.new(tomogram_request, white_list.to_a))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def white_list
|
82
|
+
@white_list ||= Fitting::Storage::WhiteList.new(
|
83
|
+
@config.white_list,
|
84
|
+
@config.resource_white_list,
|
85
|
+
@config.tomogram.to_resources
|
86
|
+
)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|