webspicy 0.15.1 → 0.15.6

Sign up to get free protection for your applications and to get access to all the features.
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!