webspicy 0.19.0 → 0.20.4
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/bin/webspicy +1 -2
- data/lib/webspicy.rb +0 -2
- data/lib/webspicy/configuration.rb +15 -0
- data/lib/webspicy/configuration/scope.rb +1 -0
- data/lib/webspicy/specification.rb +4 -3
- data/lib/webspicy/specification/condition.rb +29 -4
- data/lib/webspicy/specification/err.rb +18 -0
- data/lib/webspicy/specification/oldies.rb +4 -0
- data/lib/webspicy/specification/oldies/bridge.rb +32 -0
- data/lib/webspicy/specification/{errcondition.rb → oldies/errcondition.rb} +5 -0
- data/lib/webspicy/specification/{postcondition.rb → oldies/postcondition.rb} +5 -0
- data/lib/webspicy/specification/{precondition.rb → oldies/precondition.rb} +5 -2
- data/lib/webspicy/specification/post.rb +20 -0
- data/lib/webspicy/specification/post/missing_condition_impl.rb +15 -0
- data/lib/webspicy/specification/post/unexpected_condition_impl.rb +15 -0
- data/lib/webspicy/specification/pre.rb +19 -0
- data/lib/webspicy/specification/{precondition → pre}/global_request_headers.rb +4 -4
- data/lib/webspicy/specification/{precondition → pre}/robust_to_invalid_input.rb +4 -4
- data/lib/webspicy/specification/service.rb +29 -5
- data/lib/webspicy/specification/test_case.rb +3 -0
- data/lib/webspicy/support.rb +12 -2
- data/lib/webspicy/support/colorize.rb +6 -0
- data/lib/webspicy/tester.rb +89 -27
- data/lib/webspicy/tester/assertions.rb +2 -2
- data/lib/webspicy/tester/client.rb +0 -26
- data/lib/webspicy/tester/fakeses.rb +41 -0
- data/lib/webspicy/tester/fakeses/email.rb +38 -0
- data/lib/webspicy/tester/fakesmtp.rb +39 -0
- data/lib/webspicy/tester/fakesmtp/email.rb +27 -0
- data/lib/webspicy/tester/reporter.rb +5 -0
- data/lib/webspicy/tester/reporter/documentation.rb +31 -8
- data/lib/webspicy/tester/reporter/error_count.rb +11 -7
- data/lib/webspicy/tester/reporter/exceptions.rb +2 -0
- data/lib/webspicy/tester/reporter/file_progress.rb +5 -2
- data/lib/webspicy/tester/reporter/file_summary.rb +3 -2
- data/lib/webspicy/tester/reporter/progress.rb +6 -4
- data/lib/webspicy/tester/reporter/summary.rb +9 -7
- data/lib/webspicy/tester/result.rb +16 -13
- 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/invocation_succeeded.rb +13 -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 +2 -2
- data/lib/webspicy/web/invocation.rb +7 -3
- data/spec/blackbox/commandline.yml +24 -0
- data/spec/blackbox/fixtures/passing/config.rb +9 -0
- data/spec/blackbox/fixtures/passing/formaldef/get.yml +30 -0
- data/spec/unit/specification/{precondition → pre}/test_global_request_headers.rb +9 -4
- data/spec/unit/specification/test_condition.rb +18 -0
- data/spec/unit/tester/fakeses/test_email.rb +40 -0
- data/tasks/test.rake +2 -1
- metadata +34 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9afe697a47ba4391d2e059f1bf3707c04f97f9d6fd50557104a59c6602dbd75c
|
4
|
+
data.tar.gz: 66ec4036f8e76dad7af0f8b0cf83ea139a67a7b1020aa0a304c26fdc9402d593
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 79feb96443a47523b38f16e4cf7e7edfcd675f5a71c6b33aa452ad452aeacd5e64de1ce1ffa9ff3f5bf9cf428d59dc183e8f1455e1ce26126f2eddf9a14795fb
|
7
|
+
data.tar.gz: 2761eb20d67f4c697dedf7c27496cfd36ceed4f988f1f54f17809358e570102f1e40c29c47e46f614671504dcf1c877ce2fe6ccb7a72b510994a9da95bb74de1
|
data/bin/webspicy
CHANGED
data/lib/webspicy.rb
CHANGED
@@ -33,8 +33,6 @@ module Webspicy
|
|
33
33
|
HttpClient = Web::HttpClient
|
34
34
|
RackTestClient = Web::RackTestClient
|
35
35
|
Resource = Specification
|
36
|
-
Precondition = Specification::Precondition
|
37
|
-
Postcondition = Specification::Postcondition
|
38
36
|
FileUpload = Specification::FileUpload
|
39
37
|
Scope = Configuration::Scope
|
40
38
|
Checker = Tester::FileChecker
|
@@ -33,12 +33,15 @@ module Webspicy
|
|
33
33
|
@service_filter = default_service_filter
|
34
34
|
@test_case_filter = default_test_case_filter
|
35
35
|
@colors = {
|
36
|
+
:section => :magenta,
|
36
37
|
:highlight => :cyan,
|
37
38
|
:error => :red,
|
38
39
|
:success => :green
|
39
40
|
}
|
41
|
+
@colorize = true
|
40
42
|
@scope_factory = ->(config){ Scope.new(config) }
|
41
43
|
@client = Web::HttpClient
|
44
|
+
@reporter = default_reporter
|
42
45
|
Path.require_tree(@folder/'support') if (@folder/'support').exists?
|
43
46
|
@world = Support::World.new(folder/'world', self)
|
44
47
|
yield(self) if block_given?
|
@@ -47,6 +50,8 @@ module Webspicy
|
|
47
50
|
protected :folder=
|
48
51
|
|
49
52
|
attr_accessor :colors
|
53
|
+
attr_accessor :colorize
|
54
|
+
|
50
55
|
attr_reader :world
|
51
56
|
|
52
57
|
def self.dress(arg, &bl)
|
@@ -434,6 +439,16 @@ module Webspicy
|
|
434
439
|
end
|
435
440
|
private :default_rspec_options
|
436
441
|
|
442
|
+
# Returns the default reporter to use.
|
443
|
+
def default_reporter
|
444
|
+
@reporter = Tester::Reporter::Composite.new
|
445
|
+
@reporter << Tester::Reporter::Documentation.new
|
446
|
+
@reporter << Tester::Reporter::Exceptions.new
|
447
|
+
@reporter << Tester::Reporter::Summary.new
|
448
|
+
@reporter << Tester::Reporter::ErrorCount.new
|
449
|
+
end
|
450
|
+
attr_accessor :reporter
|
451
|
+
|
437
452
|
# Returns the Data system to use for parsing schemas
|
438
453
|
#
|
439
454
|
# The data system associated with a configuration is build when the
|
@@ -23,6 +23,7 @@ module Webspicy
|
|
23
23
|
folder = config.folder
|
24
24
|
world = config.folder/"world"
|
25
25
|
fs = folder.glob("**/*.yml").reject{|f| f.to_s.start_with?(world.to_s) }
|
26
|
+
fs = fs.sort
|
26
27
|
fs = fs.select(&to_filter_proc(config.file_filter)) if apply_filter
|
27
28
|
fs.each do |file|
|
28
29
|
yield file, folder
|
@@ -94,8 +94,9 @@ module Webspicy
|
|
94
94
|
end # module Webspicy
|
95
95
|
require_relative 'specification/service'
|
96
96
|
require_relative 'specification/condition'
|
97
|
-
require_relative 'specification/
|
98
|
-
require_relative 'specification/
|
99
|
-
require_relative 'specification/
|
97
|
+
require_relative 'specification/pre'
|
98
|
+
require_relative 'specification/post'
|
99
|
+
require_relative 'specification/err'
|
100
|
+
require_relative 'specification/oldies'
|
100
101
|
require_relative 'specification/test_case'
|
101
102
|
require_relative 'specification/file_upload'
|
@@ -1,11 +1,40 @@
|
|
1
1
|
module Webspicy
|
2
2
|
class Specification
|
3
3
|
module Condition
|
4
|
+
extend Forwardable
|
4
5
|
|
5
6
|
MATCH_ALL = "__all__"
|
6
7
|
|
7
8
|
attr_accessor :matching_description
|
8
9
|
|
10
|
+
# Given a service and a condition, returns a Pre instance of there is a
|
11
|
+
# match, nil otherwise.
|
12
|
+
def self.match(service, condition)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Bind the condition instance to a current tester.
|
16
|
+
def bind(tester)
|
17
|
+
@tester = tester
|
18
|
+
self
|
19
|
+
end
|
20
|
+
attr_reader :tester
|
21
|
+
|
22
|
+
def_delegators :@tester, *[
|
23
|
+
:config, :scope, :client,
|
24
|
+
:specification, :spec_file,
|
25
|
+
:service, :test_case,
|
26
|
+
:invocation, :result,
|
27
|
+
:reporter
|
28
|
+
]
|
29
|
+
|
30
|
+
def sooner_or_later(*args, &bl)
|
31
|
+
Webspicy::Support.sooner_or_later(*args, &bl)
|
32
|
+
end
|
33
|
+
|
34
|
+
def fail!(msg)
|
35
|
+
raise Tester::Failure, msg
|
36
|
+
end
|
37
|
+
|
9
38
|
def to_s
|
10
39
|
if matching_description == MATCH_ALL
|
11
40
|
self.class.name
|
@@ -14,10 +43,6 @@ module Webspicy
|
|
14
43
|
end
|
15
44
|
end
|
16
45
|
|
17
|
-
def sooner_or_later(*args, &bl)
|
18
|
-
Webspicy::Support.sooner_or_later(*args, &bl)
|
19
|
-
end
|
20
|
-
|
21
46
|
end # module Condition
|
22
47
|
end # class Specification
|
23
48
|
end # module Webspicy
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Webspicy
|
2
|
+
class Specification
|
3
|
+
module Err
|
4
|
+
include Condition
|
5
|
+
|
6
|
+
# Instrument the current test_case so as to prepare for errcondition
|
7
|
+
# check later
|
8
|
+
def instrument
|
9
|
+
end
|
10
|
+
|
11
|
+
# Check that the errcondition is met on last invocation & result
|
12
|
+
# of an counterexample
|
13
|
+
def check!
|
14
|
+
end
|
15
|
+
|
16
|
+
end # module Err
|
17
|
+
end # module Specification
|
18
|
+
end # module Webspicy
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Webspicy
|
2
|
+
class Specification
|
3
|
+
module Oldies
|
4
|
+
class Bridge
|
5
|
+
include Condition
|
6
|
+
|
7
|
+
def initialize(target)
|
8
|
+
@target = target
|
9
|
+
end
|
10
|
+
attr_reader :target
|
11
|
+
|
12
|
+
def instrument
|
13
|
+
return unless target.respond_to?(:instrument)
|
14
|
+
target.instrument(test_case, client)
|
15
|
+
end
|
16
|
+
|
17
|
+
def check!
|
18
|
+
return unless target.respond_to?(:check)
|
19
|
+
res = target.check(invocation)
|
20
|
+
res ? fail!(res) : nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
"#{target} (backward compatibility bridge)"
|
25
|
+
end
|
26
|
+
|
27
|
+
end # class Bridge
|
28
|
+
end # module Errcondition
|
29
|
+
end # module Specification
|
30
|
+
Precondition = Specification::Precondition
|
31
|
+
Postcondition = Specification::Postcondition
|
32
|
+
end # module Webspicy
|
@@ -1,8 +1,13 @@
|
|
1
1
|
module Webspicy
|
2
2
|
class Specification
|
3
|
+
# Deprecated, use Pre instead
|
3
4
|
module Precondition
|
4
5
|
include Condition
|
5
6
|
|
7
|
+
def bind(tester)
|
8
|
+
Oldies::Bridge.new(self).bind(tester)
|
9
|
+
end
|
10
|
+
|
6
11
|
def self.match(service, pre)
|
7
12
|
end
|
8
13
|
|
@@ -16,5 +21,3 @@ module Webspicy
|
|
16
21
|
end # module Precondition
|
17
22
|
end # class Specification
|
18
23
|
end # module Webspicy
|
19
|
-
require_relative 'precondition/global_request_headers'
|
20
|
-
require_relative 'precondition/robust_to_invalid_input'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Webspicy
|
2
|
+
class Specification
|
3
|
+
module Post
|
4
|
+
include Condition
|
5
|
+
|
6
|
+
# Instrument the current test_case so as to prepare for postcondition
|
7
|
+
# check later
|
8
|
+
def instrument
|
9
|
+
end
|
10
|
+
|
11
|
+
# Check that the postcondition is met on last invocation & result
|
12
|
+
# of an example
|
13
|
+
def check!
|
14
|
+
end
|
15
|
+
|
16
|
+
end # module Post
|
17
|
+
end # module Specification
|
18
|
+
end # module Webspicy
|
19
|
+
require_relative "post/missing_condition_impl"
|
20
|
+
require_relative "post/unexpected_condition_impl"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Webspicy
|
2
|
+
class Specification
|
3
|
+
module Postcondition
|
4
|
+
class MissingConditionImpl
|
5
|
+
include Post
|
6
|
+
|
7
|
+
def check!
|
8
|
+
msg = matching_description.gsub(/\(x\)/, "<!>")
|
9
|
+
fail!("#{msg} (not instrumented)")
|
10
|
+
end
|
11
|
+
|
12
|
+
end # class MissingConditionImpl
|
13
|
+
end # module Postcondition
|
14
|
+
end # class Specification
|
15
|
+
end # module Webspicy
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Webspicy
|
2
|
+
class Specification
|
3
|
+
module Postcondition
|
4
|
+
class UnexpectedConditionImpl
|
5
|
+
include Post
|
6
|
+
|
7
|
+
def check!
|
8
|
+
msg = matching_description.gsub(/\( \)/, "<x>")
|
9
|
+
fail!("#{msg} (is instrumented)")
|
10
|
+
end
|
11
|
+
|
12
|
+
end # class UnexpectedConditionImpl
|
13
|
+
end # module Postcondition
|
14
|
+
end # class Specification
|
15
|
+
end # module Webspicy
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Webspicy
|
2
|
+
class Specification
|
3
|
+
module Pre
|
4
|
+
include Condition
|
5
|
+
|
6
|
+
# Instrument the current test_case so as to meet the precondition
|
7
|
+
def instrument
|
8
|
+
end
|
9
|
+
|
10
|
+
# Provide counterexamples of this precondition for a given service.
|
11
|
+
def counterexamples(service)
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
|
15
|
+
end # module Pre
|
16
|
+
end # class Specification
|
17
|
+
end # module Webspicy
|
18
|
+
require_relative 'pre/global_request_headers'
|
19
|
+
require_relative 'pre/robust_to_invalid_input'
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Webspicy
|
2
2
|
class Specification
|
3
|
-
module
|
3
|
+
module Pre
|
4
4
|
class GlobalRequestHeaders
|
5
|
-
include
|
5
|
+
include Pre
|
6
6
|
|
7
7
|
DEFAULT_OPTIONS = {}
|
8
8
|
|
@@ -22,7 +22,7 @@ module Webspicy
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def instrument
|
25
|
+
def instrument
|
26
26
|
extra = headers.reject{|k|
|
27
27
|
test_case.headers.has_key?(k)
|
28
28
|
}
|
@@ -30,6 +30,6 @@ module Webspicy
|
|
30
30
|
end
|
31
31
|
|
32
32
|
end # class GlobalRequestHeaders
|
33
|
-
end # module
|
33
|
+
end # module Pre
|
34
34
|
end # class Specification
|
35
35
|
end # module Webspicy
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Webspicy
|
2
2
|
class Specification
|
3
|
-
module
|
3
|
+
module Pre
|
4
4
|
class RobustToInvalidInput
|
5
|
-
include
|
5
|
+
include Pre
|
6
6
|
|
7
7
|
def self.match(service, pre)
|
8
8
|
self.new
|
@@ -49,7 +49,7 @@ module Webspicy
|
|
49
49
|
status: Support::StatusRange.str("4xx")
|
50
50
|
},
|
51
51
|
:assert => []
|
52
|
-
})]
|
52
|
+
})]
|
53
53
|
else
|
54
54
|
[]
|
55
55
|
end
|
@@ -63,6 +63,6 @@ module Webspicy
|
|
63
63
|
end
|
64
64
|
|
65
65
|
end # class RobustToInvalidInput
|
66
|
-
end # module
|
66
|
+
end # module Pre
|
67
67
|
end # class Specification
|
68
68
|
end # module Webspicy
|
@@ -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
|
@@ -112,16 +115,37 @@ module Webspicy
|
|
112
115
|
# Because we want pre & post to be able to match in all cases
|
113
116
|
# we need at least one condition
|
114
117
|
descriptions = [Condition::MATCH_ALL] if descriptions.empty?
|
115
|
-
|
118
|
+
mapping = {}
|
119
|
+
instances = conditions.map{|c|
|
116
120
|
instance = nil
|
117
121
|
descr = descriptions.find do |d|
|
118
122
|
instance = c.match(self, d)
|
119
123
|
end
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
+
instance.tap{|i|
|
125
|
+
mapping[descr] ||= i if i
|
126
|
+
i.matching_description = descr if i.respond_to?(:matching_description=)
|
127
|
+
}
|
124
128
|
}.compact
|
129
|
+
mapped = descriptions
|
130
|
+
.select{|d| mapping[d] }
|
131
|
+
.map{|d| mapping[d] }
|
132
|
+
unmapped = descriptions
|
133
|
+
.reject{|d| mapping[d] }
|
134
|
+
.select{|d| d.strip =~ /^(\(\w+\))?\(x\)/ }
|
135
|
+
.map{|d|
|
136
|
+
Postcondition::MissingConditionImpl.new.tap{|mc|
|
137
|
+
mc.matching_description = d
|
138
|
+
}
|
139
|
+
}
|
140
|
+
unexpected = descriptions
|
141
|
+
.select{|d| mapping[d] }
|
142
|
+
.select{|d| d.strip =~ /^(\(\w+\))?\( \)/ }
|
143
|
+
.map{|d|
|
144
|
+
Postcondition::UnexpectedConditionImpl.new.tap{|mc|
|
145
|
+
mc.matching_description = d
|
146
|
+
}
|
147
|
+
}
|
148
|
+
mapped + unmapped + unexpected
|
125
149
|
end
|
126
150
|
|
127
151
|
def bind_examples
|