fitting 2.6.0 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +77 -31
- data/fitting.gemspec +1 -0
- data/lib/fitting/cover.rb +66 -0
- data/lib/fitting/cover/json_schema.rb +106 -0
- data/lib/fitting/cover/response.rb +41 -0
- data/lib/fitting/records/unit/combination.rb +28 -0
- data/lib/fitting/records/unit/json_schema.rb +30 -0
- data/lib/fitting/response.rb +6 -0
- data/lib/fitting/statistics/analysis.rb +3 -2
- data/lib/fitting/statistics/cover_error.rb +31 -0
- data/lib/fitting/statistics/list.rb +9 -4
- data/lib/fitting/statistics/lists.rb +5 -4
- data/lib/fitting/statistics/measurement_cover.rb +94 -0
- data/lib/fitting/statistics/template.rb +17 -5
- data/lib/fitting/statistics/template_cover_error.rb +54 -0
- data/lib/fitting/version.rb +1 -1
- data/lib/fitting/view/report.html.haml +16 -0
- data/lib/fitting/view/style.css +47 -0
- data/lib/tasks/fitting.rake +62 -0
- metadata +25 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 058ccfba8eb94e0929f24473e00684c70d39fe19
|
4
|
+
data.tar.gz: 1a3395ec6ea7e9dd577671a523f85042773a025f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6fcea3482af2fec8090fed3306af166d8c98699f18d1c629c13d2f8027fe95a42edf22ffb6ddbe0e15e883e446839450fea817273f18ddb5a0f986912ed9f33
|
7
|
+
data.tar.gz: a4ffbd091060c642052b2d4e5d9d5b33fcd3d3204622d86397b7407a6b8fdcb17527ee74ebe9d6ba759efb41fe3ecee0145b4cac27a80045a6b79fd0b6abed43
|
data/README.md
CHANGED
@@ -39,30 +39,52 @@ In your `spec_helper.rb`:
|
|
39
39
|
```ruby
|
40
40
|
require 'fitting'
|
41
41
|
|
42
|
-
Fitting.
|
42
|
+
Fitting.save_test_data
|
43
43
|
```
|
44
44
|
|
45
|
-
|
45
|
+
The tests.json file will be created
|
46
46
|
|
47
|
-
|
48
|
-
require 'fitting'
|
47
|
+
Example:
|
49
48
|
|
50
|
-
|
49
|
+
```
|
50
|
+
[
|
51
|
+
{
|
52
|
+
"method": "GET",
|
53
|
+
"path": "/api/v1/book",
|
54
|
+
"body": {},
|
55
|
+
"response": {
|
56
|
+
"status": 200,
|
57
|
+
"body": {
|
58
|
+
"title": "The Martian Chronicles"
|
59
|
+
}
|
60
|
+
},
|
61
|
+
"title": "/spec/controllers/api/v1/books_controller_spec.rb:11",
|
62
|
+
"group": "/spec/controllers/api/v1/books_controller_spec.rb"
|
63
|
+
},
|
64
|
+
{
|
65
|
+
"method": "POST",
|
66
|
+
"path": "/api/v1/book",
|
67
|
+
"body": {},
|
68
|
+
"response": {
|
69
|
+
"status": 200,
|
70
|
+
"body": {
|
71
|
+
"title": "The Old Man and the Sea"
|
72
|
+
}
|
73
|
+
},
|
74
|
+
"title": "/spec/controllers/api/v1/books_controller_spec.rb:22",
|
75
|
+
"group": "/spec/controllers/api/v1/books_controller_spec.rb"
|
76
|
+
},
|
77
|
+
...
|
78
|
+
```
|
51
79
|
|
52
|
-
RSpec.configure do |config|
|
53
|
-
config.after(:each, type: :controller) do
|
54
|
-
responses.add(response)
|
55
|
-
end
|
56
80
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
```
|
81
|
+
## Check documentation cover
|
82
|
+
|
83
|
+
### xs size
|
62
84
|
|
63
|
-
|
85
|
+
For match routes and valid json-schemas run `rake fitting:documentation_responses[xs]`
|
64
86
|
|
65
|
-
|
87
|
+
You will get statistics:
|
66
88
|
|
67
89
|
```
|
68
90
|
Fully conforming requests:
|
@@ -88,31 +110,50 @@ API responses conforming to the blueprint: 16 (64.00% of 25).
|
|
88
110
|
API responses with validation errors or untested: 9 (36.00% of 25).
|
89
111
|
```
|
90
112
|
|
91
|
-
|
92
|
-
|
93
|
-
## Matchers
|
113
|
+
### s size
|
94
114
|
|
95
|
-
|
115
|
+
In addition to the previous comand, you will learn the coverage json-schemas with task `rake fitting:documentation_responses[s]`
|
96
116
|
|
97
|
-
```ruby
|
98
|
-
config.include Fitting::Matchers, type: :controller
|
99
117
|
```
|
118
|
+
Fully conforming requests:
|
119
|
+
DELETE /api/v1/book 100% 200 100% 201 100% 404
|
120
|
+
DELETE /api/v1/book/{id} 100% 200 100% 201 100% 404
|
121
|
+
GET /api/v1/book/{id}/seller 100% 200 100% 201 100% 404
|
100
122
|
|
101
|
-
|
123
|
+
Partially conforming requests:
|
124
|
+
GET /api/v1/book 0% 200 66% 404
|
125
|
+
POST /api/v1/book 0% 200 90% 201 100% 404
|
126
|
+
GET /api/v1/book/{id} 0% 200 88% 404 10% 200
|
127
|
+
PATCH /api/v1/book/{id} 0% 200 100% 201 10% 404
|
102
128
|
|
103
|
-
|
129
|
+
Non-conforming requests:
|
130
|
+
GET /api/v1/seller 0% 200 0% 201 0 404
|
131
|
+
GET /api/v1/buyer 0% 200 0% 404
|
104
132
|
|
105
|
-
|
106
|
-
|
107
|
-
|
133
|
+
API requests with fully implemented responses: 3 (33.33% of 9).
|
134
|
+
API requests with partially implemented responses: 4 (44.44% of 9).
|
135
|
+
API requests with no implemented responses: 2 (22.22% of 9).
|
108
136
|
|
109
|
-
|
137
|
+
API responses conforming to the blueprint: 16 (64.00% of 25).
|
138
|
+
API responses with validation errors or untested: 9 (36.00% of 25).
|
139
|
+
```
|
110
140
|
|
111
|
-
|
141
|
+
For details `rake fitting:documentation_responses_error[s]`
|
112
142
|
|
113
|
-
```ruby
|
114
|
-
expect(response).to strictly_match_schema
|
115
143
|
```
|
144
|
+
request metohd: GET
|
145
|
+
request path: /api/v1/book
|
146
|
+
response staus: 200
|
147
|
+
source json-schema: {"$schema"=>"http://json-schema.org/draft-04/schema#", "type"=>"object", ...}
|
148
|
+
combination: ["required", "pages"]
|
149
|
+
new json-schema: {"$schema"=>"http://json-schema.org/draft-04/schema#", "type"=>"object", ...}
|
150
|
+
```
|
151
|
+
|
152
|
+
## Check tests cover
|
153
|
+
|
154
|
+
### xs size
|
155
|
+
|
156
|
+
`rake fitting:tests_responses[xs]`
|
116
157
|
|
117
158
|
## Config
|
118
159
|
|
@@ -176,6 +217,11 @@ resource_white_list:
|
|
176
217
|
|
177
218
|
Empty array `[]` means all methods.
|
178
219
|
|
220
|
+
### json_schema_cover
|
221
|
+
|
222
|
+
Default: false. Json-schema covering becomes mandatory.
|
223
|
+
Or you can call `responses.statistics.cover_save` if you don't use call `Fitting.statistics`.
|
224
|
+
|
179
225
|
### include_resources
|
180
226
|
|
181
227
|
Default: all resources if `include_resources` and `include_actions` is not used.
|
data/fitting.gemspec
CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_runtime_dependency 'json-schema', '~> 2.6', '>= 2.6.2'
|
24
24
|
spec.add_runtime_dependency 'multi_json'
|
25
25
|
spec.add_runtime_dependency 'tomograph', '~> 2.0', '>= 2.2.0'
|
26
|
+
spec.add_runtime_dependency 'haml'
|
26
27
|
spec.add_development_dependency 'bundler', '~> 1.12'
|
27
28
|
spec.add_development_dependency 'rake', '~> 10.0'
|
28
29
|
spec.add_development_dependency 'byebug', '~> 8.2', '>= 8.2.1'
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'fitting/cover/response'
|
2
|
+
require 'haml'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Fitting
|
6
|
+
class Cover
|
7
|
+
def initialize(all_responses, coverage)
|
8
|
+
@all_responses = all_responses
|
9
|
+
@coverage = coverage
|
10
|
+
@list = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_hash
|
14
|
+
return @list unless @list == {}
|
15
|
+
@all_responses.each_with_object({}) do |response, res|
|
16
|
+
next res unless response.documented?
|
17
|
+
if res.key?(response.route)
|
18
|
+
res[response.route].update(response)
|
19
|
+
else
|
20
|
+
res[response.route] = Fitting::Cover::Response.new(response)
|
21
|
+
end
|
22
|
+
end.map do |key, value|
|
23
|
+
@list[key] = value.to_hash
|
24
|
+
end
|
25
|
+
@list
|
26
|
+
end
|
27
|
+
|
28
|
+
def template
|
29
|
+
return @template if @template
|
30
|
+
@template = {}
|
31
|
+
to_hash.each do |key, value|
|
32
|
+
@template[key] = value
|
33
|
+
@template[key]['cover'] = 100.0
|
34
|
+
if value['flags'] == []
|
35
|
+
@template[key]['type'] = 'passed'
|
36
|
+
else
|
37
|
+
flag_true = value['flags'].find_all{|flag| flag == true}
|
38
|
+
flag_false = value['flags'].find_all{|flag| flag == false}
|
39
|
+
if flag_false.size == 0
|
40
|
+
@template[key]['type'] = 'passed'
|
41
|
+
else
|
42
|
+
if flag_true.size == 0
|
43
|
+
@template[key]['cover'] = 0.0
|
44
|
+
else
|
45
|
+
@template[key]['cover'] = flag_false.size / flag_true.size
|
46
|
+
end
|
47
|
+
@template[key]['type'] = 'failed'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
@template[key]['json_schema'] = JSON.pretty_generate(value['json_schemas'].last)
|
51
|
+
end
|
52
|
+
@template
|
53
|
+
end
|
54
|
+
|
55
|
+
def save
|
56
|
+
to_hash
|
57
|
+
contents = File.read(File.expand_path('../view/report.html.haml', __FILE__))
|
58
|
+
html = "<style>\n#{File.read(File.expand_path('../view/style.css', __FILE__))}\n</style>\n"
|
59
|
+
html += Haml::Engine.new(contents).render(
|
60
|
+
Object.new,
|
61
|
+
:@to_hash => template
|
62
|
+
)
|
63
|
+
html
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Fitting
|
2
|
+
class Cover
|
3
|
+
class JSONSchema
|
4
|
+
def initialize(json_schema)
|
5
|
+
@json_schema = json_schema
|
6
|
+
end
|
7
|
+
|
8
|
+
def json_schemas
|
9
|
+
return @json_schemas if @json_schemas
|
10
|
+
@json_schemas, @combinations = required(@json_schema)
|
11
|
+
|
12
|
+
return @json_schemas unless @json_schema['properties']
|
13
|
+
super_each(@json_schema['properties'], 'properties' => nil)
|
14
|
+
|
15
|
+
@json_schemas
|
16
|
+
end
|
17
|
+
|
18
|
+
def super_each(json_schema, old_keys_hash)
|
19
|
+
json_schema.each do |key, value|
|
20
|
+
new_keys_hash = clone_hash(old_keys_hash)
|
21
|
+
add_super_key(new_keys_hash, key)
|
22
|
+
if value.is_a?(Hash)
|
23
|
+
modify_json_shema(value, new_keys_hash)
|
24
|
+
super_each(value, new_keys_hash)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_super_key(vbn, new_key)
|
30
|
+
vbn.each do |key, value|
|
31
|
+
if value
|
32
|
+
add_super_key(value, new_key)
|
33
|
+
else
|
34
|
+
vbn[key] = { new_key => nil }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def super_merge(vbn, asd, old_json_schema)
|
40
|
+
vbn.each do |key, value|
|
41
|
+
if value
|
42
|
+
super_merge(value, asd, old_json_schema[key])
|
43
|
+
else
|
44
|
+
old_json_schema[key].merge!(asd)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
old_json_schema
|
48
|
+
end
|
49
|
+
|
50
|
+
def modify_json_shema(value, vbn)
|
51
|
+
qwe = required(value)
|
52
|
+
qwe[0].map do |asd|
|
53
|
+
new_json_shema = clone_hash(@json_schema)
|
54
|
+
super_merge(vbn, asd, new_json_shema)
|
55
|
+
@json_schemas += [new_json_shema]
|
56
|
+
end
|
57
|
+
@combinations += qwe[1]
|
58
|
+
end
|
59
|
+
|
60
|
+
def clone_hash(old_json_schema)
|
61
|
+
new_json_schema = {}
|
62
|
+
old_json_schema.each do |key, value|
|
63
|
+
if value.is_a?(Hash)
|
64
|
+
new_json_schema.merge!(key => clone_hash(value))
|
65
|
+
elsif value
|
66
|
+
new_json_schema.merge!(key => value.clone)
|
67
|
+
else
|
68
|
+
new_json_schema.merge!(key => nil)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
new_json_schema
|
72
|
+
end
|
73
|
+
|
74
|
+
def combinations
|
75
|
+
json_schemas
|
76
|
+
@combinations
|
77
|
+
end
|
78
|
+
|
79
|
+
def required(json_schema)
|
80
|
+
combinations = []
|
81
|
+
json_schemas = new_keys(json_schema).inject([]) do |new_json_shemas, new_key|
|
82
|
+
new_json_shema = json_schema.dup
|
83
|
+
if new_json_shema['required']
|
84
|
+
new_json_shema['required'] += [new_key]
|
85
|
+
else
|
86
|
+
new_json_shema['required'] = [new_key]
|
87
|
+
end
|
88
|
+
combinations.push(['required', new_key])
|
89
|
+
new_json_shemas.push(new_json_shema)
|
90
|
+
end
|
91
|
+
[json_schemas, combinations]
|
92
|
+
end
|
93
|
+
|
94
|
+
def new_keys(json_schema)
|
95
|
+
return [] unless json_schema && json_schema['properties']
|
96
|
+
all = json_schema['properties'].keys.map(&:to_s)
|
97
|
+
old = json_schema['required']
|
98
|
+
if old
|
99
|
+
all - old
|
100
|
+
else
|
101
|
+
all
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'fitting/cover/json_schema'
|
2
|
+
require 'json-schema'
|
3
|
+
|
4
|
+
module Fitting
|
5
|
+
class Cover
|
6
|
+
class Response
|
7
|
+
def initialize(response)
|
8
|
+
@cover_json_schemas = Fitting::Cover::JSONSchema.new(response.json_schema)
|
9
|
+
@json_schemas = @cover_json_schemas.json_schemas + [response.json_schema]
|
10
|
+
@combinations = @cover_json_schemas.combinations
|
11
|
+
@flags = @cover_json_schemas.json_schemas.map do |json_schema|
|
12
|
+
JSON::Validator.validate(json_schema, response.body)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :json_schemas
|
17
|
+
|
18
|
+
attr_reader :combinations
|
19
|
+
|
20
|
+
attr_reader :flags
|
21
|
+
|
22
|
+
def update(response)
|
23
|
+
index = 0
|
24
|
+
@cover_json_schemas.json_schemas.map do |json_schema|
|
25
|
+
flag = JSON::Validator.validate(json_schema, response.body)
|
26
|
+
@flags[index] = @flags[index] || flag
|
27
|
+
index += 1
|
28
|
+
end
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_hash
|
33
|
+
{
|
34
|
+
'json_schemas' => json_schemas,
|
35
|
+
'combinations' => combinations,
|
36
|
+
'flags' => flags
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'json-schema'
|
2
|
+
|
3
|
+
module Fitting
|
4
|
+
class Records
|
5
|
+
class Unit
|
6
|
+
class Combination
|
7
|
+
attr_reader :description, :json_schema, :bodies
|
8
|
+
|
9
|
+
def initialize(description, json_schema, bodies)
|
10
|
+
@description = description
|
11
|
+
@json_schema = json_schema
|
12
|
+
@bodies = bodies
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_bodies
|
16
|
+
@valid_bodies ||= @bodies.inject([]) do |res, tested_body|
|
17
|
+
begin
|
18
|
+
next res unless JSON::Validator.validate(@json_schema, tested_body)
|
19
|
+
res.push(tested_body)
|
20
|
+
rescue JSON::Schema::UriError
|
21
|
+
res.push(tested_body)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,9 +1,13 @@
|
|
1
1
|
require 'json-schema'
|
2
|
+
require 'fitting/cover/json_schema'
|
3
|
+
require 'fitting/records/unit/combination'
|
2
4
|
|
3
5
|
module Fitting
|
4
6
|
class Records
|
5
7
|
class Unit
|
6
8
|
class JsonSchema
|
9
|
+
attr_reader :json_schema
|
10
|
+
|
7
11
|
def initialize(json_schema, tested_bodies)
|
8
12
|
@json_schema = json_schema
|
9
13
|
@tested_bodies = tested_bodies
|
@@ -19,6 +23,32 @@ module Fitting
|
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
26
|
+
|
27
|
+
def combinations
|
28
|
+
return @combinations if @combinations
|
29
|
+
@combinations = []
|
30
|
+
cover_json_schema = Fitting::Cover::JSONSchema.new(@json_schema)
|
31
|
+
cover_json_schema.json_schemas.each_index do |index|
|
32
|
+
@combinations.push(Fitting::Records::Unit::Combination.new(
|
33
|
+
cover_json_schema.combinations[index],
|
34
|
+
cover_json_schema.json_schemas[index],
|
35
|
+
bodies
|
36
|
+
))
|
37
|
+
end
|
38
|
+
@combinations
|
39
|
+
end
|
40
|
+
|
41
|
+
def cover
|
42
|
+
@cover ||= if bodies == []
|
43
|
+
0
|
44
|
+
else
|
45
|
+
count = 0
|
46
|
+
combinations.map do |combination|
|
47
|
+
count += 1 unless combination.valid_bodies == []
|
48
|
+
end
|
49
|
+
(count + 1) * 100 / (combinations.size + 1)
|
50
|
+
end
|
51
|
+
end
|
22
52
|
end
|
23
53
|
end
|
24
54
|
end
|
data/lib/fitting/response.rb
CHANGED
@@ -5,6 +5,8 @@ require 'multi_json'
|
|
5
5
|
|
6
6
|
module Fitting
|
7
7
|
class Response
|
8
|
+
attr_reader :body
|
9
|
+
|
8
10
|
def initialize(env_response, tomogram)
|
9
11
|
@request = Fitting::Request.new(env_response.request, tomogram)
|
10
12
|
@status = env_response.status
|
@@ -54,6 +56,10 @@ module Fitting
|
|
54
56
|
end.join("\n\n")
|
55
57
|
end
|
56
58
|
|
59
|
+
def json_schema
|
60
|
+
@schemas[index.first]
|
61
|
+
end
|
62
|
+
|
57
63
|
def ignored?(ignore_list)
|
58
64
|
@request.ignored?(ignore_list)
|
59
65
|
end
|
@@ -7,13 +7,14 @@ require 'fitting/statistics/not_covered_responses'
|
|
7
7
|
module Fitting
|
8
8
|
class Statistics
|
9
9
|
class Analysis
|
10
|
-
def initialize(measurement)
|
10
|
+
def initialize(measurement, depth)
|
11
11
|
@measurement = measurement
|
12
|
+
@depth = depth
|
12
13
|
end
|
13
14
|
|
14
15
|
def to_s
|
15
16
|
[
|
16
|
-
Fitting::Statistics::Lists.new(@measurement).to_s,
|
17
|
+
Fitting::Statistics::Lists.new(@measurement, @depth).to_s,
|
17
18
|
Fitting::Statistics::RequestsStats.new(@measurement).to_s,
|
18
19
|
Fitting::Statistics::ResponsesStats.new(@measurement).to_s,
|
19
20
|
Fitting::Statistics::Great.new(@measurement).to_s
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Fitting
|
2
|
+
class Statistics
|
3
|
+
class CoverError
|
4
|
+
def initialize(request_unit)
|
5
|
+
@request_unit = request_unit
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
res = ''
|
10
|
+
@request_unit.map do |request|
|
11
|
+
request.responses.map do |response|
|
12
|
+
if response.tested_bodies == []
|
13
|
+
return 'Error, not all responses valid without cover!'
|
14
|
+
else
|
15
|
+
response.json_schemas.map do |json_schema|
|
16
|
+
json_schema.combinations.map do |combination|
|
17
|
+
if combination.valid_bodies == []
|
18
|
+
res += "request metohd: #{request.method}\nrequest path: #{request.path}\n"\
|
19
|
+
"response staus: #{response.status}\nsource json-schema: #{json_schema.json_schema}\n"\
|
20
|
+
"combination: #{combination.description}\nnew json-schema: #{combination.json_schema}\n\n"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
res
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module Fitting
|
2
2
|
class Statistics
|
3
3
|
class List
|
4
|
-
def initialize(coverage, max_response_path)
|
4
|
+
def initialize(coverage, max_response_path, depth)
|
5
5
|
@coverage = coverage
|
6
6
|
@max_response_path = max_response_path
|
7
|
+
@depth = depth
|
7
8
|
end
|
8
9
|
|
9
10
|
def to_s
|
@@ -34,10 +35,14 @@ module Fitting
|
|
34
35
|
end
|
35
36
|
|
36
37
|
def json_schema_stat(res, json_schema, response)
|
37
|
-
if
|
38
|
-
|
38
|
+
if @depth == 'valid'
|
39
|
+
if json_schema.bodies == []
|
40
|
+
res.push("✖ #{response.status}")
|
41
|
+
else
|
42
|
+
res.push("✔ #{response.status}")
|
43
|
+
end
|
39
44
|
else
|
40
|
-
res.push("
|
45
|
+
res.push("#{json_schema.cover}% #{response.status}")
|
41
46
|
end
|
42
47
|
end
|
43
48
|
end
|
@@ -3,8 +3,9 @@ require 'fitting/statistics/list'
|
|
3
3
|
module Fitting
|
4
4
|
class Statistics
|
5
5
|
class Lists
|
6
|
-
def initialize(measurement)
|
6
|
+
def initialize(measurement, depth)
|
7
7
|
@measurement = measurement
|
8
|
+
@depth = depth
|
8
9
|
end
|
9
10
|
|
10
11
|
def to_s
|
@@ -21,7 +22,7 @@ module Fitting
|
|
21
22
|
else
|
22
23
|
[
|
23
24
|
'Fully conforming requests:',
|
24
|
-
Fitting::Statistics::List.new(@measurement.coverage_fully, @measurement.max_response_path).to_s
|
25
|
+
Fitting::Statistics::List.new(@measurement.coverage_fully, @measurement.max_response_path, @depth).to_s
|
25
26
|
].join("\n")
|
26
27
|
end
|
27
28
|
end
|
@@ -32,7 +33,7 @@ module Fitting
|
|
32
33
|
else
|
33
34
|
[
|
34
35
|
'Partially conforming requests:',
|
35
|
-
Fitting::Statistics::List.new(@measurement.coverage_partially, @measurement.max_response_path).to_s
|
36
|
+
Fitting::Statistics::List.new(@measurement.coverage_partially, @measurement.max_response_path, @depth).to_s
|
36
37
|
].join("\n")
|
37
38
|
end
|
38
39
|
end
|
@@ -43,7 +44,7 @@ module Fitting
|
|
43
44
|
else
|
44
45
|
[
|
45
46
|
'Non-conforming requests:',
|
46
|
-
Fitting::Statistics::List.new(@measurement.coverage_non, @measurement.max_response_path).to_s
|
47
|
+
Fitting::Statistics::List.new(@measurement.coverage_non, @measurement.max_response_path, @depth).to_s
|
47
48
|
].join("\n")
|
48
49
|
end
|
49
50
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Fitting
|
2
|
+
class Statistics
|
3
|
+
class MeasurementCover
|
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.cover != 100
|
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.cover != 100
|
87
|
+
@not_cover += 1
|
88
|
+
else
|
89
|
+
@cover += 1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'fitting/statistics/not_covered_responses'
|
2
2
|
require 'fitting/statistics/analysis'
|
3
3
|
require 'fitting/statistics/measurement'
|
4
|
+
require 'fitting/statistics/measurement_cover'
|
4
5
|
require 'fitting/records/unit/request'
|
5
6
|
require 'fitting/storage/white_list'
|
6
7
|
require 'fitting/records/documented/request'
|
@@ -8,9 +9,10 @@ require 'fitting/records/documented/request'
|
|
8
9
|
module Fitting
|
9
10
|
class Statistics
|
10
11
|
class Template
|
11
|
-
def initialize(tested_requests, config)
|
12
|
+
def initialize(tested_requests, config, depth = 'valid')
|
12
13
|
@tested_requests = tested_requests
|
13
14
|
@config = config
|
15
|
+
@depth = depth
|
14
16
|
end
|
15
17
|
|
16
18
|
def save
|
@@ -35,19 +37,29 @@ module Fitting
|
|
35
37
|
end
|
36
38
|
|
37
39
|
def white_statistics
|
38
|
-
@white_statistics ||= Fitting::Statistics::Analysis.new(white_measurement)
|
40
|
+
@white_statistics ||= Fitting::Statistics::Analysis.new(white_measurement, @depth)
|
39
41
|
end
|
40
42
|
|
41
43
|
def black_statistics
|
42
|
-
@black_statistics ||= Fitting::Statistics::Analysis.new(black_measurement)
|
44
|
+
@black_statistics ||= Fitting::Statistics::Analysis.new(black_measurement, @depth)
|
43
45
|
end
|
44
46
|
|
45
47
|
def white_measurement
|
46
|
-
@white_measurement ||=
|
48
|
+
@white_measurement ||=
|
49
|
+
if @depth == 'valid'
|
50
|
+
Fitting::Statistics::Measurement.new(white_unit)
|
51
|
+
else
|
52
|
+
Fitting::Statistics::MeasurementCover.new(white_unit)
|
53
|
+
end
|
47
54
|
end
|
48
55
|
|
49
56
|
def black_measurement
|
50
|
-
@black_measurement ||=
|
57
|
+
@black_measurement ||=
|
58
|
+
if @depth == 'valid'
|
59
|
+
Fitting::Statistics::Measurement.new(black_unit)
|
60
|
+
else
|
61
|
+
Fitting::Statistics::MeasurementCover.new(black_unit)
|
62
|
+
end
|
51
63
|
end
|
52
64
|
|
53
65
|
def white_unit
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'fitting/statistics/cover_error'
|
2
|
+
require 'fitting/records/unit/request'
|
3
|
+
require 'fitting/storage/white_list'
|
4
|
+
require 'fitting/records/documented/request'
|
5
|
+
|
6
|
+
module Fitting
|
7
|
+
class Statistics
|
8
|
+
class TemplateCoverError
|
9
|
+
def initialize(tested_requests, config)
|
10
|
+
@tested_requests = tested_requests
|
11
|
+
@config = config
|
12
|
+
end
|
13
|
+
|
14
|
+
def stats
|
15
|
+
[
|
16
|
+
['[White list]', white_statistics].join("\n"),
|
17
|
+
''
|
18
|
+
].join("\n\n")
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def white_statistics
|
23
|
+
@white_statistics ||= Fitting::Statistics::CoverError.new(white_unit)
|
24
|
+
end
|
25
|
+
|
26
|
+
def white_unit
|
27
|
+
@white_unit_requests ||= documented_requests_white.inject([]) do |res, documented_request|
|
28
|
+
res.push(Fitting::Records::Unit::Request.new(documented_request, @tested_requests))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def documented_requests_white
|
33
|
+
@documented_requests_white ||= documented.find_all(&:white)
|
34
|
+
end
|
35
|
+
|
36
|
+
def documented
|
37
|
+
@documented_requests ||= @config.tomogram.to_a.inject([]) do |res, tomogram_request|
|
38
|
+
res.push(Fitting::Records::Documented::Request.new(tomogram_request, white_list.to_a))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def white_list
|
43
|
+
@white_list ||= Fitting::Storage::WhiteList.new(
|
44
|
+
@config.prefix,
|
45
|
+
@config.white_list,
|
46
|
+
@config.resource_white_list,
|
47
|
+
@config.include_resources,
|
48
|
+
@config.include_actions,
|
49
|
+
@config.tomogram.to_resources
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/fitting/version.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
!!! 5
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%title= Time.now
|
5
|
+
%meta{charset: "utf-8"}
|
6
|
+
%body
|
7
|
+
- @to_hash.each do |key, value|
|
8
|
+
%details
|
9
|
+
%summary{class: "collapse #{value['type']}"}
|
10
|
+
= "#{key} #{value['cover']}"
|
11
|
+
%div{class: 'group'}
|
12
|
+
%div{class: 'section'}
|
13
|
+
%div
|
14
|
+
%b main json-schema
|
15
|
+
%xmp
|
16
|
+
= value['json_schema']
|
@@ -0,0 +1,47 @@
|
|
1
|
+
summary {
|
2
|
+
margin: 10px;
|
3
|
+
}
|
4
|
+
|
5
|
+
summary:hover {
|
6
|
+
background: #e1e1e1;
|
7
|
+
}
|
8
|
+
|
9
|
+
.passed {
|
10
|
+
color: green;
|
11
|
+
}
|
12
|
+
|
13
|
+
.failed {
|
14
|
+
color: red;
|
15
|
+
}
|
16
|
+
|
17
|
+
.pending {
|
18
|
+
color: orange;
|
19
|
+
}
|
20
|
+
|
21
|
+
.collapse {
|
22
|
+
cursor: pointer;
|
23
|
+
display: block;
|
24
|
+
background: white;
|
25
|
+
}
|
26
|
+
|
27
|
+
.collapse + input {
|
28
|
+
display: none; /* hide the checkboxes */
|
29
|
+
}
|
30
|
+
|
31
|
+
.collapse + input + div {
|
32
|
+
display: none;
|
33
|
+
}
|
34
|
+
|
35
|
+
.collapse + input:checked + div {
|
36
|
+
display: block;
|
37
|
+
}
|
38
|
+
|
39
|
+
.section {
|
40
|
+
padding-top: 10px;
|
41
|
+
}
|
42
|
+
|
43
|
+
.group {
|
44
|
+
border: 1px solid black;
|
45
|
+
margin: 5px 0px;
|
46
|
+
padding: 0px 5px;
|
47
|
+
}
|
data/lib/tasks/fitting.rake
CHANGED
@@ -2,6 +2,7 @@ require 'fitting/records/spherical/requests'
|
|
2
2
|
require 'fitting/configuration'
|
3
3
|
require 'fitting/records/realized_unit'
|
4
4
|
require 'fitting/templates/realized_template'
|
5
|
+
require 'fitting/statistics/template_cover_error'
|
5
6
|
|
6
7
|
namespace :fitting do
|
7
8
|
desc 'Fitting documentation'
|
@@ -18,6 +19,49 @@ namespace :fitting do
|
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
22
|
+
desc 'Fitting documentation responses cover'
|
23
|
+
task :documentation_responses, [:size] => :environment do |_, args|
|
24
|
+
if args.size == 'xs'
|
25
|
+
documented_unit = Fitting::Statistics::Template.new(
|
26
|
+
Fitting::Records::Spherical::Requests.new,
|
27
|
+
Fitting.configuration
|
28
|
+
)
|
29
|
+
puts documented_unit.stats
|
30
|
+
|
31
|
+
unless documented_unit.not_covered == "\n"
|
32
|
+
puts 'Not all responses from the whitelist are covered!'
|
33
|
+
exit 1
|
34
|
+
end
|
35
|
+
elsif args.size == 's'
|
36
|
+
documented_unit = Fitting::Statistics::Template.new(
|
37
|
+
Fitting::Records::Spherical::Requests.new,
|
38
|
+
Fitting.configuration,
|
39
|
+
'cover'
|
40
|
+
)
|
41
|
+
puts documented_unit.stats
|
42
|
+
|
43
|
+
unless documented_unit.not_covered == "\n"
|
44
|
+
puts 'Not all responses from the whitelist are covered!'
|
45
|
+
exit 1
|
46
|
+
end
|
47
|
+
else
|
48
|
+
puts 'need key xs or s'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
desc 'Fitting documentation responses cover error'
|
53
|
+
task :documentation_responses_error, [:size] => :environment do |_, args|
|
54
|
+
if args.size == 's'
|
55
|
+
documented_unit = Fitting::Statistics::TemplateCoverError.new(
|
56
|
+
Fitting::Records::Spherical::Requests.new,
|
57
|
+
Fitting.configuration
|
58
|
+
)
|
59
|
+
puts documented_unit.stats
|
60
|
+
else
|
61
|
+
puts 'need key s'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
21
65
|
desc 'Fitting tests'
|
22
66
|
task :tests do
|
23
67
|
realized_unit = Fitting::Records::RealizedUnit.new(
|
@@ -31,4 +75,22 @@ namespace :fitting do
|
|
31
75
|
exit 1
|
32
76
|
end
|
33
77
|
end
|
78
|
+
|
79
|
+
desc 'Fitting tests'
|
80
|
+
task :tests_responses, [:size] => :environment do |_, args|
|
81
|
+
if args.size == 'xs'
|
82
|
+
realized_unit = Fitting::Records::RealizedUnit.new(
|
83
|
+
Fitting::Records::Spherical::Requests.new,
|
84
|
+
Fitting.configuration.tomogram
|
85
|
+
)
|
86
|
+
puts Fitting::Templates::RealizedTemplate.new(realized_unit).to_s
|
87
|
+
|
88
|
+
unless realized_unit.fully_covered?
|
89
|
+
puts 'Not all responses from the whitelist are covered!'
|
90
|
+
exit 1
|
91
|
+
end
|
92
|
+
else
|
93
|
+
puts 'need key xs'
|
94
|
+
end
|
95
|
+
end
|
34
96
|
end
|
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: 2.
|
4
|
+
version: 2.7.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: 2018-
|
11
|
+
date: 2018-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json-schema
|
@@ -64,6 +64,20 @@ dependencies:
|
|
64
64
|
- - ">="
|
65
65
|
- !ruby/object:Gem::Version
|
66
66
|
version: 2.2.0
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: haml
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
type: :runtime
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
67
81
|
- !ruby/object:Gem::Dependency
|
68
82
|
name: bundler
|
69
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -195,6 +209,9 @@ files:
|
|
195
209
|
- lib/fitting/configuration.rb
|
196
210
|
- lib/fitting/configuration/legacy.rb
|
197
211
|
- lib/fitting/configuration/yaml.rb
|
212
|
+
- lib/fitting/cover.rb
|
213
|
+
- lib/fitting/cover/json_schema.rb
|
214
|
+
- lib/fitting/cover/response.rb
|
198
215
|
- lib/fitting/documentation.rb
|
199
216
|
- lib/fitting/matchers/response_matcher.rb
|
200
217
|
- lib/fitting/railtie.rb
|
@@ -206,6 +223,7 @@ files:
|
|
206
223
|
- lib/fitting/records/test_unit/request.rb
|
207
224
|
- lib/fitting/records/tested/request.rb
|
208
225
|
- lib/fitting/records/tested/response.rb
|
226
|
+
- lib/fitting/records/unit/combination.rb
|
209
227
|
- lib/fitting/records/unit/json_schema.rb
|
210
228
|
- lib/fitting/records/unit/request.rb
|
211
229
|
- lib/fitting/records/unit/response.rb
|
@@ -214,20 +232,25 @@ files:
|
|
214
232
|
- lib/fitting/response/fully_validates.rb
|
215
233
|
- lib/fitting/statistics.rb
|
216
234
|
- lib/fitting/statistics/analysis.rb
|
235
|
+
- lib/fitting/statistics/cover_error.rb
|
217
236
|
- lib/fitting/statistics/great.rb
|
218
237
|
- lib/fitting/statistics/list.rb
|
219
238
|
- lib/fitting/statistics/lists.rb
|
220
239
|
- lib/fitting/statistics/measurement.rb
|
240
|
+
- lib/fitting/statistics/measurement_cover.rb
|
221
241
|
- lib/fitting/statistics/not_covered_responses.rb
|
222
242
|
- lib/fitting/statistics/percent.rb
|
223
243
|
- lib/fitting/statistics/requests_stats.rb
|
224
244
|
- lib/fitting/statistics/responses_stats.rb
|
225
245
|
- lib/fitting/statistics/template.rb
|
246
|
+
- lib/fitting/statistics/template_cover_error.rb
|
226
247
|
- lib/fitting/storage/responses.rb
|
227
248
|
- lib/fitting/storage/white_list.rb
|
228
249
|
- lib/fitting/templates/realized_template.rb
|
229
250
|
- lib/fitting/tests.rb
|
230
251
|
- lib/fitting/version.rb
|
252
|
+
- lib/fitting/view/report.html.haml
|
253
|
+
- lib/fitting/view/style.css
|
231
254
|
- lib/tasks/fitting.rake
|
232
255
|
homepage: https://github.com/funbox/fitting
|
233
256
|
licenses:
|