webspicy 0.15.1 → 0.15.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7df7fb7b7355b799757a5f58d93e38d273c18e371abb8bec697da6ae0f2bd2d
4
- data.tar.gz: e1b01e07b8a00610336a8d2415a0e6b911c08515fcfbc0cb2b10631e76844814
3
+ metadata.gz: 8e1b4727e5991117fae5493694aa7a27d7de9811039d74eca4592a60b40d20c3
4
+ data.tar.gz: dd3d6d1d836dd19cda286a8de96663711b5c1682b6a8411e6a051aa6a5d7c7e7
5
5
  SHA512:
6
- metadata.gz: 341c0de577225743a1cca6cf60471210c720c7385f3c2bfad7a32db4172214ebb5ad5af2aab0719ffaca2bf2f5a29f1ecfe2b74a92a14901e1aecaa4f8032aee
7
- data.tar.gz: 6424b90b6cc4dce2336bf2076da859726c19eaeecf9d8ee33f08769c814549087326f353eef68f54663b68e8d8a633648a215ffd7c69c57e11ac520421e72243
6
+ metadata.gz: 0d37e5d27ca8f93b1745b4ef0515d710bc6e00b85023c3cf6d3e9e3fc6d2e7d2e5b55eaf0a3c1d756f8dbc5048be6a5b50b7d03ed021263af8a943a15bc883ef
7
+ data.tar.gz: af84325bb759302a20d0cb9cc96eb5015ee5e07815d8d00083bad3950024e1f70b09c03b17989e703bf448a7c6184814bd321fe2fb597c4ca6e0d209f27bd20d
@@ -29,7 +29,8 @@ if ARGV.size != 1
29
29
  exit(-1)
30
30
  elsif (p = Path(ARGV.first)).exists?
31
31
  config = Webspicy::Configuration.dress(p)
32
- Webspicy::Tester.new(config).call
32
+ res = Webspicy::Tester.new(config).call
33
+ abort("Some tests failed") unless res == 0
33
34
  else
34
35
  puts "No such file or directory `#{ARGV.first}`"
35
36
  showhelp
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- webspicy (0.15.1)
4
+ webspicy (0.15.6)
5
5
  finitio (>= 0.8.0)
6
6
  http (>= 2)
7
7
  mustermann (~> 1.0)
@@ -14,6 +14,7 @@ module Webspicy
14
14
  ### Load library
15
15
  ###
16
16
 
17
+ require 'webspicy/support'
17
18
  require 'webspicy/configuration'
18
19
  require 'webspicy/file_upload'
19
20
  require 'webspicy/scope'
@@ -11,6 +11,7 @@ module Webspicy
11
11
  @postconditions = []
12
12
  @listeners = Hash.new{|h,k| h[k] = [] }
13
13
  @rspec_options = default_rspec_options
14
+ @run_examples = default_run_examples
14
15
  @run_counterexamples = default_run_counterexamples
15
16
  @file_filter = default_file_filter
16
17
  @service_filter = default_service_filter
@@ -94,6 +95,23 @@ module Webspicy
94
95
  !children.empty?
95
96
  end
96
97
 
98
+ # Sets whether examples have to be ran or not.
99
+ def run_examples=(run_examples)
100
+ @run_examples = run_examples
101
+ end
102
+ attr_reader :run_examples
103
+
104
+ # Whether counter examples must be ran or not.
105
+ def run_examples?
106
+ @run_examples
107
+ end
108
+
109
+ # Returns the defaut value for run_examples
110
+ def default_run_examples
111
+ ENV['ROBUST'].nil? || (ENV['ROBUST'] != 'only')
112
+ end
113
+ private :default_run_examples
114
+
97
115
  # Sets whether counter examples have to be ran or not.
98
116
  def run_counterexamples=(run_counterexamples)
99
117
  @run_counterexamples = run_counterexamples
@@ -249,36 +267,36 @@ module Webspicy
249
267
  # Installs a listener that will be called before all tests
250
268
  #
251
269
  # The `listener` must respond to `call`.
252
- def before_all(&listener)
253
- register_listener(:before_all, listener)
270
+ def before_all(l = nil, &listener)
271
+ register_listener(:before_all, l || listener)
254
272
  end
255
273
 
256
274
  # Installs a listener that will be called before each web service invocation.
257
275
  #
258
276
  # The `listener` must respond to `call`.
259
- def before_each(&listener)
260
- register_listener(:before_each, listener)
277
+ def before_each(l = nil, &listener)
278
+ register_listener(:before_each, l || listener)
261
279
  end
262
280
 
263
281
  # Installs a listener that will be called after all tests
264
282
  #
265
283
  # The `listener` must respond to `call`.
266
- def after_all(&listener)
267
- register_listener(:after_all, listener)
284
+ def after_all(l = nil, &listener)
285
+ register_listener(:after_all, l || listener)
268
286
  end
269
287
 
270
288
  # Installs a listener that will be called after each web service invocation.
271
289
  #
272
290
  # The `listener` must respond to `call`.
273
- def after_each(&listener)
274
- register_listener(:after_each, listener)
291
+ def after_each(l = nil, &listener)
292
+ register_listener(:after_each, l || listener)
275
293
  end
276
294
 
277
295
  # Installs a listener that will be called around each web service invocation.
278
296
  #
279
297
  # The `listener` must respond to `call`.
280
- def around_each(&listener)
281
- register_listener(:around_each, listener)
298
+ def around_each(l = nil, &listener)
299
+ register_listener(:around_each, l || listener)
282
300
  end
283
301
 
284
302
  # Installs a listener that will be called right after all precondition
@@ -51,7 +51,7 @@ TestCase =
51
51
  requester :? String
52
52
  metadata :? { ...: .Object }
53
53
  expected :? {
54
- status :? Integer
54
+ status :? StatusRange
55
55
  content_type :? String|Nil
56
56
  error :? String
57
57
  headers :? .Hash
@@ -61,3 +61,7 @@ TestCase =
61
61
  }
62
62
 
63
63
  Params = .Array|.Hash
64
+
65
+ StatusRange = .Webspicy::Support::StatusRange
66
+ <int> Integer
67
+ <str> String(s | s =~ /^\dxx$/ )
@@ -57,7 +57,7 @@ module Webspicy
57
57
 
58
58
  def best_status_code(service)
59
59
  if ex = service.examples.first
60
- ex.expected_status || 200
60
+ (ex.expected_status && ex.expected_status.to_i) || 200
61
61
  else
62
62
  200
63
63
  end
@@ -51,8 +51,7 @@ module Webspicy
51
51
  preconditions.map{|pre|
52
52
  pre.counterexamples(self).map{|tc|
53
53
  tc = Webspicy.test_case(tc, Webspicy.current_scope)
54
- tc.service = self
55
- tc
54
+ tc.bind(self, true)
56
55
  }
57
56
  }.flatten
58
57
  end
@@ -107,13 +106,13 @@ module Webspicy
107
106
 
108
107
  def bind_examples
109
108
  (@raw[:examples] ||= []).each do |ex|
110
- ex.service = self
109
+ ex.bind(self, false)
111
110
  end
112
111
  end
113
112
 
114
113
  def bind_counterexamples
115
114
  (@raw[:counterexamples] ||= []).each do |ex|
116
- ex.service = self
115
+ ex.bind(self, true)
117
116
  end
118
117
  end
119
118
 
@@ -12,6 +12,32 @@ module Webspicy
12
12
 
13
13
  attr_reader :service, :test_case, :response, :client
14
14
 
15
+ def errors
16
+ @errors ||= begin
17
+ errs = [
18
+ [:expected_status_unmet, true],
19
+ [:expected_content_type_unmet, !test_case.is_expected_status?(204)],
20
+ [:expected_headers_unmet, test_case.has_expected_headers?],
21
+ [:expected_schema_unmet, !test_case.is_expected_status?(204)],
22
+ [:assertions_unmet, test_case.has_assertions?],
23
+ [:postconditions_unmet, test_case.service.has_postconditions? && !test_case.counterexample?],
24
+ [:expected_error_unmet, test_case.has_expected_error?]
25
+ ].map do |(expectation,only_if)|
26
+ next unless only_if
27
+ begin
28
+ self.send(expectation)
29
+ rescue => ex
30
+ ex.message
31
+ end
32
+ end
33
+ errs.compact
34
+ end
35
+ end
36
+
37
+ def has_error?
38
+ !errors.empty?
39
+ end
40
+
15
41
  ### Getters on response
16
42
 
17
43
  def response_code
@@ -27,7 +53,7 @@ module Webspicy
27
53
  end
28
54
 
29
55
  def is_expected_success?
30
- test_case.expected_status >= 200 && test_case.expected_status < 300
56
+ test_case.expected_status.to_i >= 200 && test_case.expected_status.to_i < 300
31
57
  end
32
58
 
33
59
  def is_success?
@@ -47,7 +73,7 @@ module Webspicy
47
73
  def expected_status_unmet
48
74
  expected = test_case.expected_status
49
75
  got = response.status
50
- expected == got ? nil : "#{expected} != #{got}"
76
+ expected === got ? nil : "#{expected} !== #{got}"
51
77
  end
52
78
 
53
79
  def meets_expected_status?
@@ -63,7 +89,7 @@ module Webspicy
63
89
  if ect.nil?
64
90
  got.nil? ? nil : "#{ect} != #{got}"
65
91
  else
66
- ect.to_s == got.to_s ? nil : "#{ect} != #{got}"
92
+ got.to_s.start_with?(ect.to_s) ? nil : "#{ect} != #{got}"
67
93
  end
68
94
  end
69
95
 
@@ -5,8 +5,20 @@ module Webspicy
5
5
 
6
6
  def initialize(raw)
7
7
  @raw = raw
8
+ @counterexample = nil
9
+ end
10
+ attr_reader :service
11
+ attr_reader :counterexample
12
+
13
+ def bind(service, counterexample)
14
+ @service = service
15
+ @counterexample = counterexample
16
+ self
17
+ end
18
+
19
+ def counterexample?
20
+ !!@counterexample
8
21
  end
9
- attr_accessor :service
10
22
 
11
23
  def resource
12
24
  service.resource
@@ -69,6 +81,10 @@ module Webspicy
69
81
  expected[:status]
70
82
  end
71
83
 
84
+ def is_expected_status?(status)
85
+ expected_status === status
86
+ end
87
+
72
88
  def expected_error
73
89
  expected[:error]
74
90
  end
@@ -46,23 +46,26 @@ module Webspicy
46
46
  resource.services.select(&to_filter_proc(config.service_filter)).each(&bl)
47
47
  end
48
48
 
49
- def each_example(service)
50
- service.examples.select(&to_filter_proc(config.test_case_filter)).each{|e|
51
- yield(expand_example(service, e), false)
52
- }
49
+ def each_example(service, &bl)
50
+ service.examples
51
+ .map{|e| expand_example(service, e) }
52
+ .select(&to_filter_proc(config.test_case_filter))
53
+ .each(&bl) if config.run_examples?
53
54
  end
54
55
 
55
56
  def each_counterexamples(service, &bl)
56
- service.counterexamples.select(&to_filter_proc(config.test_case_filter)).each{|e|
57
- yield(expand_example(service, e), true)
58
- } if config.run_counterexamples?
57
+ service.counterexamples
58
+ .map{|e| expand_example(service, e) }
59
+ .select(&to_filter_proc(config.test_case_filter))
60
+ .each(&bl) if config.run_counterexamples?
59
61
  end
60
62
 
61
63
  def each_generated_counterexamples(service, &bl)
62
64
  Webspicy.with_scope(self) do
63
- service.generated_counterexamples.select(&to_filter_proc(config.test_case_filter)).each{|e|
64
- yield(expand_example(service, e), true)
65
- }
65
+ service.generated_counterexamples
66
+ .map{|e| expand_example(service, e) }
67
+ .select(&to_filter_proc(config.test_case_filter))
68
+ .each(&bl) if config.run_counterexamples?
66
69
  end if config.run_counterexamples?
67
70
  end
68
71
 
@@ -128,8 +131,7 @@ module Webspicy
128
131
  h1 = service.default_example.to_info
129
132
  h2 = example.to_info
130
133
  ex = Resource::Service::TestCase.new(merge_maps(h1, h2))
131
- ex.service = service
132
- ex
134
+ ex.bind(service, example.counterexample?)
133
135
  end
134
136
 
135
137
  def merge_maps(h1, h2)
@@ -0,0 +1 @@
1
+ require_relative 'support/status_range'
@@ -0,0 +1,50 @@
1
+ module Webspicy
2
+ module Support
3
+ class StatusRange
4
+
5
+ def initialize(range)
6
+ @range = range
7
+ end
8
+ attr_reader :range
9
+
10
+ def self.int(i)
11
+ new(i..i)
12
+ end
13
+
14
+ def to_int
15
+ @range.first
16
+ end
17
+
18
+ def self.str(s)
19
+ from = s[/^(\d)/,1].to_i * 100
20
+ new(from...from+100)
21
+ end
22
+
23
+ def to_str
24
+ "#{@range.first/100}xx"
25
+ end
26
+
27
+ def to_i
28
+ @range.first
29
+ end
30
+
31
+ def ===(status)
32
+ range === status
33
+ end
34
+
35
+ def ==(other)
36
+ other.is_a?(StatusRange) && self.range == other.range
37
+ end
38
+ alias :eql? :==
39
+
40
+ def hash
41
+ @range.hash
42
+ end
43
+
44
+ def to_s
45
+ @range.to_s
46
+ end
47
+
48
+ end # class StatusRange
49
+ end # module Support
50
+ end # module Webspicy
@@ -45,16 +45,16 @@ module Webspicy
45
45
 
46
46
  def rspec_service!(on, service, client, scope)
47
47
  on.describe service do
48
- scope.each_testcase(service) do |test_case, counterexample|
48
+ scope.each_testcase(service) do |test_case|
49
49
  describe test_case do
50
- include_examples 'a successful test case invocation', client, test_case, counterexample
50
+ include_examples 'a successful test case invocation', client, test_case
51
51
  end
52
52
  end
53
53
  end
54
54
  end
55
55
 
56
56
  def rspec_config!
57
- RSpec.shared_examples "a successful test case invocation" do |client, test_case, counterexample|
57
+ RSpec.shared_examples "a successful test case invocation" do |client, test_case|
58
58
 
59
59
  around(:each) do |example|
60
60
  client.around(test_case) do
@@ -63,7 +63,8 @@ module Webspicy
63
63
  client.instrument(test_case)
64
64
  @invocation = client.call(test_case)
65
65
  example.run
66
- client.after(test_case)
66
+ client.after(test_case, @invocation)
67
+ @invocation
67
68
  end
68
69
  end
69
70
 
@@ -73,24 +74,8 @@ module Webspicy
73
74
 
74
75
  it 'works' do
75
76
  raise "Test not ran" unless invocation.done?
76
- fails = [
77
- [:expected_status_unmet, true],
78
- [:expected_content_type_unmet, true],
79
- [:expected_headers_unmet, test_case.has_expected_headers?],
80
- [:expected_schema_unmet, true],
81
- [:assertions_unmet, test_case.has_assertions?],
82
- [:postconditions_unmet, test_case.service.has_postconditions? && !counterexample],
83
- [:expected_error_unmet, test_case.has_expected_error?]
84
- ].map do |(expectation,only_if)|
85
- next unless only_if
86
- begin
87
- invocation.send(expectation)
88
- rescue => ex
89
- ex.message
90
- end
91
- end
92
- fails = fails.compact
93
- raise "\n* " + fails.join("\n* ") + "\n" unless fails.empty?
77
+ errors = invocation.errors
78
+ raise "\n* " + errors.join("\n* ") + "\n" unless errors.empty?
94
79
  end
95
80
  end
96
81
  end
@@ -2,7 +2,7 @@ module Webspicy
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 15
5
- TINY = 1
5
+ TINY = 6
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
@@ -53,7 +53,7 @@ module Webspicy
53
53
  expect(subject).to be_a(Resource::Service::TestCase)
54
54
  expect(subject.description).to eql("Hello world")
55
55
  expect(subject.expected).to eql({
56
- status: 200,
56
+ status: Support::StatusRange.int(200),
57
57
  content_type: "application/json"
58
58
  })
59
59
  end
@@ -0,0 +1,29 @@
1
+ require "spec_helper"
2
+ module Webspicy
3
+ module Support
4
+ describe StatusRange do
5
+
6
+ it 'has a int information contract' do
7
+ expect(StatusRange.int(100).range).to eql(100..100)
8
+ expect(StatusRange.int(100).to_int).to eql(100)
9
+ end
10
+
11
+ it 'has a str information contract' do
12
+ expect(StatusRange.str("3xx").range).to eql(300...400)
13
+ expect(StatusRange.str("3xx").to_str).to eql("3xx")
14
+ end
15
+
16
+ it 'has a to_i that returns the first status of the range' do
17
+ expect(StatusRange.int(300).to_i).to eql(300)
18
+ expect(StatusRange.str("3xx").to_i).to eql(300)
19
+ end
20
+
21
+ it 'has a matching method' do
22
+ expect(StatusRange.str("3xx") === 300).to eql(true)
23
+ expect(StatusRange.str("3xx") === 302).to eql(true)
24
+ expect(StatusRange.str("3xx") === 400).to eql(false)
25
+ end
26
+
27
+ end
28
+ end
29
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webspicy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.1
4
+ version: 0.15.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-28 00:00:00.000000000 Z
11
+ date: 2020-06-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -224,6 +224,8 @@ files:
224
224
  - lib/webspicy/resource/service/invocation.rb
225
225
  - lib/webspicy/resource/service/test_case.rb
226
226
  - lib/webspicy/scope.rb
227
+ - lib/webspicy/support.rb
228
+ - lib/webspicy/support/status_range.rb
227
229
  - lib/webspicy/tester.rb
228
230
  - lib/webspicy/tester/asserter.rb
229
231
  - lib/webspicy/tester/assertions.rb
@@ -239,6 +241,7 @@ files:
239
241
  - spec/unit/scope/test_expand_example.rb
240
242
  - spec/unit/scope/test_to_real_url.rb
241
243
  - spec/unit/spec_helper.rb
244
+ - spec/unit/support/test_status_range.rb
242
245
  - spec/unit/test_configuration.rb
243
246
  - spec/unit/tester/test_assertions.rb
244
247
  - tasks/gem.rake
@@ -262,7 +265,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
262
265
  - !ruby/object:Gem::Version
263
266
  version: '0'
264
267
  requirements: []
265
- rubygems_version: 3.1.2
268
+ rubygems_version: 3.1.0.pre1
266
269
  signing_key:
267
270
  specification_version: 4
268
271
  summary: Webspicy helps testing web services as software operation black boxes!