webspicy 0.20.0 → 0.20.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/sandr +14 -0
- data/bin/search +2 -0
- data/bin/webspicy +3 -4
- data/lib/finitio/webspicy/shared.fio +10 -0
- data/lib/webspicy.rb +22 -53
- data/lib/webspicy/configuration.rb +17 -0
- data/lib/webspicy/configuration/scope.rb +3 -2
- data/lib/webspicy/configuration/single_url.rb +35 -25
- data/lib/webspicy/configuration/single_yml_file.rb +7 -2
- data/lib/webspicy/specification.rb +0 -55
- data/lib/webspicy/specification/oldies/bridge.rb +4 -1
- data/lib/webspicy/specification/post/missing_condition_impl.rb +2 -2
- data/lib/webspicy/specification/post/unexpected_condition_impl.rb +2 -2
- data/lib/webspicy/specification/service.rb +4 -5
- data/lib/webspicy/specification/test_case.rb +3 -49
- data/lib/webspicy/support/colorize.rb +7 -1
- data/lib/webspicy/tester.rb +21 -20
- data/lib/webspicy/tester/assertions.rb +2 -2
- data/lib/webspicy/tester/reporter.rb +5 -0
- data/lib/webspicy/tester/reporter/documentation.rb +26 -8
- data/lib/webspicy/tester/reporter/error_count.rb +11 -7
- data/lib/webspicy/tester/reporter/file_progress.rb +2 -2
- data/lib/webspicy/tester/reporter/file_summary.rb +2 -2
- data/lib/webspicy/tester/reporter/progress.rb +4 -4
- data/lib/webspicy/tester/reporter/summary.rb +8 -7
- data/lib/webspicy/tester/result.rb +2 -2
- data/lib/webspicy/tester/result/errcondition_met.rb +1 -3
- data/lib/webspicy/tester/result/error_schema_met.rb +1 -0
- data/lib/webspicy/tester/result/output_schema_met.rb +1 -0
- data/lib/webspicy/tester/result/postcondition_met.rb +1 -3
- data/lib/webspicy/version.rb +1 -1
- data/lib/webspicy/web.rb +46 -0
- data/lib/webspicy/{formaldoc.fio → web/formaldoc.fio} +5 -13
- data/lib/webspicy/web/invocation.rb +7 -3
- data/lib/webspicy/web/specification.rb +68 -0
- data/lib/webspicy/web/specification/file_upload.rb +39 -0
- data/lib/webspicy/web/specification/service.rb +13 -0
- data/lib/webspicy/web/specification/test_case.rb +58 -0
- data/spec/unit/configuration/scope/test_expand_example.rb +11 -5
- data/spec/unit/specification/pre/test_global_request_headers.rb +3 -3
- data/spec/unit/specification/service/test_dress_params.rb +2 -2
- data/spec/unit/test_configuration.rb +1 -0
- data/spec/unit/web/specification/test_instantiate_url.rb +36 -0
- data/spec/unit/web/specification/test_url_placeholders.rb +23 -0
- data/tasks/test.rake +2 -1
- metadata +24 -16
- data/lib/webspicy/specification/file_upload.rb +0 -37
- data/spec/unit/specification/test_instantiate_url.rb +0 -34
- data/spec/unit/specification/test_url_placeholders.rb +0 -21
@@ -4,9 +4,9 @@ module Webspicy
|
|
4
4
|
class UnexpectedConditionImpl
|
5
5
|
include Post
|
6
6
|
|
7
|
-
def check
|
7
|
+
def check!
|
8
8
|
msg = matching_description.gsub(/\( \)/, "<x>")
|
9
|
-
|
9
|
+
fail!("#{msg} (is instrumented)")
|
10
10
|
end
|
11
11
|
|
12
12
|
end # class UnexpectedConditionImpl
|
@@ -10,6 +10,9 @@ module Webspicy
|
|
10
10
|
end
|
11
11
|
attr_accessor :specification
|
12
12
|
|
13
|
+
# Deprecated
|
14
|
+
alias :resource :specification
|
15
|
+
|
13
16
|
def self.info(raw)
|
14
17
|
new(raw)
|
15
18
|
end
|
@@ -18,10 +21,6 @@ module Webspicy
|
|
18
21
|
specification.config
|
19
22
|
end
|
20
23
|
|
21
|
-
def method
|
22
|
-
@raw[:method]
|
23
|
-
end
|
24
|
-
|
25
24
|
def description
|
26
25
|
@raw[:description]
|
27
26
|
end
|
@@ -65,7 +64,7 @@ module Webspicy
|
|
65
64
|
def generated_counterexamples
|
66
65
|
preconditions.map{|pre|
|
67
66
|
pre.counterexamples(self).map{|tc|
|
68
|
-
tc =
|
67
|
+
tc = config.factory.test_case(tc, Webspicy.current_scope)
|
69
68
|
tc.bind(self, true)
|
70
69
|
}
|
71
70
|
}.flatten
|
@@ -28,6 +28,9 @@ module Webspicy
|
|
28
28
|
service.specification
|
29
29
|
end
|
30
30
|
|
31
|
+
# Deprecated
|
32
|
+
alias :resource :specification
|
33
|
+
|
31
34
|
def self.info(raw)
|
32
35
|
new(raw)
|
33
36
|
end
|
@@ -40,10 +43,6 @@ module Webspicy
|
|
40
43
|
@raw[:seeds]
|
41
44
|
end
|
42
45
|
|
43
|
-
def headers
|
44
|
-
@raw[:headers] ||= {}
|
45
|
-
end
|
46
|
-
|
47
46
|
def metadata
|
48
47
|
@raw[:metadata] ||= {}
|
49
48
|
end
|
@@ -52,47 +51,10 @@ module Webspicy
|
|
52
51
|
@raw[:tags] ||= []
|
53
52
|
end
|
54
53
|
|
55
|
-
def dress_params
|
56
|
-
@raw.fetch(:dress_params){ true }
|
57
|
-
end
|
58
|
-
alias :dress_params? :dress_params
|
59
|
-
|
60
|
-
def params
|
61
|
-
@raw[:params] || {}
|
62
|
-
end
|
63
|
-
|
64
|
-
def body
|
65
|
-
@raw[:body]
|
66
|
-
end
|
67
|
-
|
68
|
-
def file_upload
|
69
|
-
@raw[:file_upload]
|
70
|
-
end
|
71
|
-
|
72
|
-
def located_file_upload
|
73
|
-
file_upload ? file_upload.locate(specification) : nil
|
74
|
-
end
|
75
|
-
|
76
54
|
def expected
|
77
55
|
@raw[:expected] || {}
|
78
56
|
end
|
79
57
|
|
80
|
-
def expected_content_type
|
81
|
-
expected[:content_type]
|
82
|
-
end
|
83
|
-
|
84
|
-
def expected_status
|
85
|
-
expected[:status]
|
86
|
-
end
|
87
|
-
|
88
|
-
def is_expected_status?(status)
|
89
|
-
expected_status === status
|
90
|
-
end
|
91
|
-
|
92
|
-
def has_expected_status?
|
93
|
-
not expected[:status].nil?
|
94
|
-
end
|
95
|
-
|
96
58
|
def expected_error
|
97
59
|
expected[:error]
|
98
60
|
end
|
@@ -101,14 +63,6 @@ module Webspicy
|
|
101
63
|
!expected_error.nil?
|
102
64
|
end
|
103
65
|
|
104
|
-
def expected_headers
|
105
|
-
expected[:headers] || {}
|
106
|
-
end
|
107
|
-
|
108
|
-
def has_expected_headers?
|
109
|
-
!expected_headers.empty?
|
110
|
-
end
|
111
|
-
|
112
66
|
def assert
|
113
67
|
@raw[:assert] || []
|
114
68
|
end
|
@@ -3,11 +3,17 @@ module Webspicy
|
|
3
3
|
module Colorize
|
4
4
|
|
5
5
|
def colorize(str, kind, config = nil)
|
6
|
+
return str if config && !config.colorize
|
6
7
|
color = (config || self.config).colors[kind]
|
7
|
-
|
8
|
+
Paint[str, color]
|
8
9
|
end
|
9
10
|
module_function :colorize
|
10
11
|
|
12
|
+
def colorize_section(str, cfg = nil)
|
13
|
+
colorize(str, :section, cfg)
|
14
|
+
end
|
15
|
+
module_function :colorize_section
|
16
|
+
|
11
17
|
def colorize_highlight(str, cfg = nil)
|
12
18
|
colorize(str, :highlight, cfg)
|
13
19
|
end
|
data/lib/webspicy/tester.rb
CHANGED
@@ -15,7 +15,7 @@ module Webspicy
|
|
15
15
|
@test_case = nil
|
16
16
|
@invocation = nil
|
17
17
|
@invocation_error = nil
|
18
|
-
@reporter =
|
18
|
+
@reporter = @config.reporter
|
19
19
|
end
|
20
20
|
attr_reader :config, :scope, :hooks, :client
|
21
21
|
attr_reader :specification, :spec_file
|
@@ -31,15 +31,6 @@ module Webspicy
|
|
31
31
|
config.failfast
|
32
32
|
end
|
33
33
|
|
34
|
-
def default_reporter
|
35
|
-
@reporter = Reporter::Composite.new
|
36
|
-
#@reporter << Reporter::Progress.new
|
37
|
-
@reporter << Reporter::Documentation.new
|
38
|
-
@reporter << Reporter::Exceptions.new
|
39
|
-
@reporter << Reporter::Summary.new
|
40
|
-
@reporter << Reporter::ErrorCount.new
|
41
|
-
end
|
42
|
-
|
43
34
|
def call
|
44
35
|
reporter.init(self)
|
45
36
|
begin
|
@@ -50,6 +41,11 @@ module Webspicy
|
|
50
41
|
reporter.find(Reporter::ErrorCount).report
|
51
42
|
end
|
52
43
|
|
44
|
+
def call!
|
45
|
+
res = call
|
46
|
+
abort("KO") unless res == 0
|
47
|
+
end
|
48
|
+
|
53
49
|
def find_and_call(method, url, mutation)
|
54
50
|
unless tc = scope.find_test_case(method, url)
|
55
51
|
raise Error, "No such service `#{method} #{url}`"
|
@@ -61,6 +57,11 @@ module Webspicy
|
|
61
57
|
end
|
62
58
|
end
|
63
59
|
|
60
|
+
def bind_condition(c)
|
61
|
+
c = Specification::Oldies::Bridge.new(c) unless c.respond_to?(:bind)
|
62
|
+
c.bind(self)
|
63
|
+
end
|
64
|
+
|
64
65
|
protected
|
65
66
|
|
66
67
|
def run_config
|
@@ -68,19 +69,15 @@ module Webspicy
|
|
68
69
|
@scope = scope
|
69
70
|
@hooks = Support::Hooks.for(scope.config)
|
70
71
|
@client = scope.get_client
|
71
|
-
reporter.before_all
|
72
|
-
@hooks.fire_before_all(self)
|
73
|
-
reporter.before_all_done
|
74
|
-
reporter.before_scope
|
75
72
|
run_scope
|
76
|
-
reporter.scope_done
|
77
|
-
reporter.after_all
|
78
|
-
@hooks.fire_after_all(self)
|
79
|
-
reporter.after_all_done
|
80
73
|
end
|
81
74
|
end
|
82
75
|
|
83
76
|
def run_scope
|
77
|
+
reporter.before_all
|
78
|
+
hooks.fire_before_all(self)
|
79
|
+
reporter.before_all_done
|
80
|
+
reporter.before_scope
|
84
81
|
scope.each_specification_file do |spec_file|
|
85
82
|
@specification = load_specification(spec_file)
|
86
83
|
if @specification
|
@@ -92,12 +89,16 @@ module Webspicy
|
|
92
89
|
raise FailFast
|
93
90
|
end
|
94
91
|
end
|
92
|
+
reporter.scope_done
|
93
|
+
reporter.after_all
|
94
|
+
hooks.fire_after_all(self)
|
95
|
+
reporter.after_all_done
|
95
96
|
end
|
96
97
|
|
97
98
|
def load_specification(spec_file)
|
98
99
|
@spec_file = spec_file
|
99
100
|
reporter.before_spec_file
|
100
|
-
|
101
|
+
config.factory.specification(spec_file.load, spec_file, scope)
|
101
102
|
rescue *PASSTHROUGH_EXCEPTIONS
|
102
103
|
raise
|
103
104
|
rescue Exception => e
|
@@ -176,7 +177,7 @@ module Webspicy
|
|
176
177
|
end
|
177
178
|
|
178
179
|
def instrument_one(condition)
|
179
|
-
condition
|
180
|
+
bind_condition(condition).instrument
|
180
181
|
rescue ArgumentError
|
181
182
|
raise "#{condition.class} implements old PRE/POST contract"
|
182
183
|
end
|
@@ -40,7 +40,7 @@ module Webspicy
|
|
40
40
|
actual_size(target, path) == expected
|
41
41
|
end
|
42
42
|
|
43
|
-
def actual_size(target, path)
|
43
|
+
def actual_size(target, path)
|
44
44
|
target = extract_path(target, path)
|
45
45
|
respond_to!(target, :size).size
|
46
46
|
end
|
@@ -68,7 +68,7 @@ module Webspicy
|
|
68
68
|
an_array(target).find { |t| t[:id] == id }
|
69
69
|
end
|
70
70
|
|
71
|
-
def idFD(element, expected)
|
71
|
+
def idFD(element, expected)
|
72
72
|
expected.keys.all? do |k|
|
73
73
|
value_equal(expected[k], element[k])
|
74
74
|
end
|
@@ -4,40 +4,58 @@ module Webspicy
|
|
4
4
|
class Documentation < Reporter
|
5
5
|
|
6
6
|
module Helpers
|
7
|
+
INDENT = " ".freeze
|
8
|
+
|
9
|
+
def spec_file_line(spec_file)
|
10
|
+
path = Path(spec_file).expand_path
|
11
|
+
path = path.relative_to(config.folder)
|
12
|
+
path = spec_file if path.to_s.start_with?(".")
|
13
|
+
colorize_section(">> #{path}", config)
|
14
|
+
end
|
15
|
+
|
7
16
|
def spec_file_error_line(spec_file, ex)
|
8
|
-
str =
|
9
|
-
str +=
|
17
|
+
str = ""
|
18
|
+
str += colorize_error(INDENT + "X #{ex.message}", config)
|
10
19
|
if ex.root_cause && ex.root_cause != ex
|
11
|
-
str += "\n
|
20
|
+
str += "\n"
|
21
|
+
str += INDENT + colorize_error("#{ex.root_cause.message}", config)
|
12
22
|
end
|
13
23
|
str
|
14
24
|
end
|
15
25
|
|
16
26
|
def service_line(service, test_case)
|
17
|
-
str = service
|
18
|
-
str = colorize_highlight(str)
|
27
|
+
str = "#{service}, #{test_case}"
|
28
|
+
str = colorize_highlight(str, config)
|
19
29
|
end
|
20
30
|
|
21
31
|
def check_success_line(check)
|
22
|
-
|
32
|
+
INDENT + colorize_success("v " + check.behavior, config)
|
23
33
|
end
|
24
34
|
|
25
35
|
def check_failure_line(check, ex)
|
26
|
-
|
36
|
+
INDENT + colorize_error("F " + ex.message, config)
|
27
37
|
end
|
28
38
|
|
29
39
|
def check_error_line(check, ex)
|
30
|
-
|
40
|
+
INDENT + colorize_error("E " + ex.message, config)
|
31
41
|
end
|
32
42
|
end
|
33
43
|
include Helpers
|
34
44
|
|
35
45
|
def spec_file_error(e)
|
46
|
+
io.puts spec_file_line(spec_file)
|
47
|
+
io.puts
|
36
48
|
io.puts spec_file_error_line(spec_file, e)
|
37
49
|
io.puts
|
38
50
|
io.flush
|
39
51
|
end
|
40
52
|
|
53
|
+
def before_service
|
54
|
+
io.puts spec_file_line(spec_file)
|
55
|
+
io.puts
|
56
|
+
io.flush
|
57
|
+
end
|
58
|
+
|
41
59
|
def before_test_case
|
42
60
|
io.puts service_line(service, test_case)
|
43
61
|
io.flush
|
@@ -5,18 +5,22 @@ module Webspicy
|
|
5
5
|
|
6
6
|
def initialize(*args, &bl)
|
7
7
|
super
|
8
|
-
@
|
8
|
+
@errors = Hash.new{|h,k| 0 }
|
9
9
|
end
|
10
|
+
attr_reader :errors
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
[
|
13
|
+
:spec_file_error,
|
14
|
+
:check_error,
|
15
|
+
:check_failure
|
16
|
+
].each do |meth|
|
17
|
+
define_method(meth) do |*args, &bl|
|
18
|
+
@errors[meth] += 1
|
19
|
+
end
|
13
20
|
end
|
14
|
-
alias :spec_file_error :on_error
|
15
|
-
alias :check_failure :on_error
|
16
|
-
alias :check_error :on_error
|
17
21
|
|
18
22
|
def report
|
19
|
-
@
|
23
|
+
@errors.values.inject(0){|memo,x| memo+x }
|
20
24
|
end
|
21
25
|
|
22
26
|
end # class ErrorCount
|
@@ -4,12 +4,12 @@ module Webspicy
|
|
4
4
|
class FileProgress < Reporter
|
5
5
|
|
6
6
|
def spec_file_error(e)
|
7
|
-
io.print colorize_error("X")
|
7
|
+
io.print colorize_error("X", config)
|
8
8
|
io.flush
|
9
9
|
end
|
10
10
|
|
11
11
|
def spec_file_done
|
12
|
-
io.print colorize_success(".")
|
12
|
+
io.print colorize_success(".", config)
|
13
13
|
io.flush
|
14
14
|
end
|
15
15
|
|
@@ -22,9 +22,9 @@ module Webspicy
|
|
22
22
|
msg = "#{plural('spec file', spec_files_count)}, "\
|
23
23
|
"#{plural('error', errors_count)}"
|
24
24
|
if success?
|
25
|
-
msg = colorize_success(msg)
|
25
|
+
msg = colorize_success(msg, config)
|
26
26
|
else
|
27
|
-
msg = colorize_error(msg)
|
27
|
+
msg = colorize_error(msg, config)
|
28
28
|
end
|
29
29
|
io.puts(msg)
|
30
30
|
io.puts
|
@@ -4,16 +4,16 @@ module Webspicy
|
|
4
4
|
class Progress < Reporter
|
5
5
|
|
6
6
|
def spec_file_error(e)
|
7
|
-
io.print colorize_error("X")
|
7
|
+
io.print colorize_error("X", config)
|
8
8
|
end
|
9
9
|
|
10
10
|
def after_each_done
|
11
11
|
if result.success?
|
12
|
-
io.print colorize_success(".")
|
12
|
+
io.print colorize_success(".", config)
|
13
13
|
elsif result.failure?
|
14
|
-
io.print colorize_error("F")
|
14
|
+
io.print colorize_error("F", config)
|
15
15
|
elsif result.error?
|
16
|
-
io.print colorize_error("E")
|
16
|
+
io.print colorize_error("E", config)
|
17
17
|
end
|
18
18
|
io.flush
|
19
19
|
end
|
@@ -9,18 +9,21 @@ module Webspicy
|
|
9
9
|
@examples_count = 0
|
10
10
|
@counterexamples_count = 0
|
11
11
|
@assertions_count = 0
|
12
|
+
#
|
13
|
+
@spec_file_errors_count = 0
|
12
14
|
@errors_count = 0
|
13
15
|
@failures_count = 0
|
14
16
|
end
|
15
17
|
attr_reader :spec_files_count, :examples_count, :counterexamples_count
|
16
|
-
attr_reader :assertions_count
|
18
|
+
attr_reader :assertions_count
|
19
|
+
attr_reader :spec_file_errors_count, :errors_count, :failures_count
|
17
20
|
|
18
21
|
def before_spec_file
|
19
22
|
@spec_files_count += 1
|
20
23
|
end
|
21
24
|
|
22
25
|
def spec_file_error(e)
|
23
|
-
@
|
26
|
+
@spec_file_errors_count += 1
|
24
27
|
end
|
25
28
|
|
26
29
|
def after_each_done
|
@@ -42,19 +45,17 @@ module Webspicy
|
|
42
45
|
"#{plural('error', errors_count)}, "\
|
43
46
|
"#{plural('failure', failures_count)}"
|
44
47
|
if success?
|
45
|
-
msg = colorize_success(msg)
|
48
|
+
msg = colorize_success(msg, config)
|
46
49
|
else
|
47
|
-
msg = colorize_error(msg)
|
50
|
+
msg = colorize_error(msg, config)
|
48
51
|
end
|
49
52
|
io.puts(msg)
|
50
53
|
io.puts
|
51
54
|
io.flush
|
52
55
|
end
|
53
56
|
|
54
|
-
private
|
55
|
-
|
56
57
|
def success?
|
57
|
-
@errors_count == 0 && @failures_count == 0
|
58
|
+
@spec_file_errors_count == 0 && @errors_count == 0 && @failures_count == 0
|
58
59
|
end
|
59
60
|
|
60
61
|
end # class Summary
|