webspicy 0.16.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -5
  3. data/examples/restful/webspicy/config.rb +1 -0
  4. data/examples/restful/webspicy/{todo/deleteTodo.yml → formaldef/todo/_one/delete.yml} +3 -0
  5. data/examples/restful/webspicy/{todo/getTodoSingleServiceFormat.yml → formaldef/todo/_one/get.simpler.yml} +0 -0
  6. data/examples/restful/webspicy/{todo/getTodo.yml → formaldef/todo/_one/get.yml} +0 -0
  7. data/examples/restful/webspicy/{todo/patchTodo.yml → formaldef/todo/_one/patch.yml} +0 -0
  8. data/examples/restful/webspicy/{todo/putTodo.yml → formaldef/todo/_one/put.yml} +0 -0
  9. data/examples/restful/webspicy/{todo/getTodos.yml → formaldef/todo/get.yml} +0 -0
  10. data/examples/restful/webspicy/{todo → formaldef/todo}/options.yml +0 -0
  11. data/examples/restful/webspicy/{todo/postCsv.yml → formaldef/todo/post.csv.yml} +0 -0
  12. data/examples/restful/webspicy/{todo/postFile.yml → formaldef/todo/post.file.yml} +0 -0
  13. data/examples/restful/webspicy/{todo/postTodos.yml → formaldef/todo/post.yml} +0 -0
  14. data/examples/restful/webspicy/{todo → formaldef/todo}/todos.csv +0 -0
  15. data/examples/restful/webspicy/support/todo_not_removed.rb +21 -0
  16. data/examples/restful/webspicy/support/todo_removed.rb +5 -3
  17. data/examples/website/specification/get-http.yml +20 -24
  18. data/examples/website/specification/get-https.yml +20 -24
  19. data/lib/webspicy.rb +4 -3
  20. data/lib/webspicy/checker.rb +5 -20
  21. data/lib/webspicy/configuration.rb +9 -0
  22. data/lib/webspicy/configuration/scope.rb +0 -8
  23. data/lib/webspicy/formaldoc.fio +8 -6
  24. data/lib/webspicy/mocker/config.ru +5 -0
  25. data/lib/webspicy/rspec/checker.rb +2 -0
  26. data/lib/webspicy/rspec/checker/rspec_checker.rb +24 -0
  27. data/lib/webspicy/rspec/support/rspec_runnable.rb +27 -0
  28. data/lib/webspicy/rspec/tester.rb +4 -0
  29. data/lib/webspicy/{tester → rspec/tester}/rspec_asserter.rb +24 -11
  30. data/lib/webspicy/{tester → rspec/tester}/rspec_matchers.rb +10 -0
  31. data/lib/webspicy/rspec/tester/rspec_tester.rb +63 -0
  32. data/lib/webspicy/specification.rb +10 -10
  33. data/lib/webspicy/specification/errcondition.rb +16 -0
  34. data/lib/webspicy/specification/precondition/robust_to_invalid_input.rb +1 -1
  35. data/lib/webspicy/specification/service.rb +27 -19
  36. data/lib/webspicy/specification/test_case.rb +3 -9
  37. data/lib/webspicy/support.rb +1 -0
  38. data/lib/webspicy/support/data_object.rb +25 -0
  39. data/lib/webspicy/tester.rb +4 -78
  40. data/lib/webspicy/tester/asserter.rb +9 -4
  41. data/lib/webspicy/tester/assertions.rb +8 -9
  42. data/lib/webspicy/tester/failure.rb +6 -0
  43. data/lib/webspicy/tester/invocation.rb +8 -156
  44. data/lib/webspicy/version.rb +1 -1
  45. data/spec/unit/configuration/scope/test_each_service.rb +2 -2
  46. data/spec/unit/configuration/scope/test_each_specification.rb +7 -7
  47. data/spec/unit/test_configuration.rb +1 -1
  48. data/spec/unit/tester/test_asserter.rb +198 -3
  49. data/spec/unit/tester/test_assertions.rb +8 -6
  50. metadata +33 -25
  51. data/LICENSE.md +0 -22
  52. data/examples/restful/Gemfile.lock +0 -105
@@ -0,0 +1,4 @@
1
+ require_relative 'support/rspec_runnable'
2
+ require_relative 'tester/rspec_matchers'
3
+ require_relative 'tester/rspec_asserter'
4
+ require_relative 'tester/rspec_tester'
@@ -8,6 +8,10 @@ module Webspicy
8
8
  end
9
9
  attr_reader :rspec, :invocation
10
10
 
11
+ def self.call(rspec, invocation)
12
+ new(rspec, invocation).send(:assert!)
13
+ end
14
+
11
15
  def response
12
16
  invocation.response
13
17
  end
@@ -20,15 +24,20 @@ module Webspicy
20
24
  test_case.service
21
25
  end
22
26
 
27
+ protected
28
+
23
29
  def assert!
24
- assert_status_met
25
- assert_content_type_met
26
- assert_expected_headers
30
+ rspec.aggregate_failures do
31
+ assert_status_met
32
+ assert_content_type_met
33
+ assert_expected_headers
34
+ end
27
35
  assert_output_schema_met
28
- assert_assertions_met
29
- assert_postconditions_met
30
-
31
- assert_no_other_errors
36
+ rspec.aggregate_failures do
37
+ assert_assertions_met
38
+ assert_postconditions_met
39
+ assert_errconditions_met
40
+ end
32
41
  end
33
42
 
34
43
  def assert_status_met
@@ -45,7 +54,7 @@ module Webspicy
45
54
  if ect.nil?
46
55
  rspec.expect(ect).to rspec.have_no_response_type
47
56
  else
48
- rspec.expect(ect).to rspec.match_content_type(got)
57
+ rspec.expect(got).to rspec.match_content_type(ect)
49
58
  end
50
59
  end
51
60
 
@@ -98,9 +107,13 @@ module Webspicy
98
107
  end
99
108
  end
100
109
 
101
- def assert_no_other_errors
102
- errors = invocation.errors
103
- rspec.expect(errors).to rspec.be_an_empty_errors_array
110
+ def assert_errconditions_met
111
+ return unless service.has_errconditions?
112
+ return unless test_case.counterexample?
113
+ service.errconditions.each do |post|
114
+ msg = post.check(invocation)
115
+ rspec.expect(msg).to rspec.meet_errcondition(post)
116
+ end
104
117
  end
105
118
 
106
119
  end # class RSpecAsserter
@@ -94,6 +94,16 @@ RSpec::Matchers.define :meet_postcondition do |post|
94
94
  end
95
95
  end
96
96
 
97
+ RSpec::Matchers.define :meet_errcondition do |post|
98
+ match do |actual|
99
+ actual.nil?
100
+ end
101
+ failure_message_for_should do |actual|
102
+ "expected errcondition `#{post.class.name}` to be met, got following error:\n" + \
103
+ " #{actual}"
104
+ end
105
+ end
106
+
97
107
  RSpec::Matchers.define :be_an_empty_errors_array do
98
108
  match do |actual|
99
109
  actual.empty?
@@ -0,0 +1,63 @@
1
+ module Webspicy
2
+ class Tester
3
+ class RSpecTester
4
+ include Webspicy::Support::RSpecRunnable
5
+
6
+ protected
7
+
8
+ def load_rspec_examples
9
+ tester = self
10
+ RSpec.describe "Webspicy test suite" do
11
+ before(:all) do
12
+ tester.config.listeners(:before_all).each do |l|
13
+ l.call(tester.config)
14
+ end
15
+ end
16
+ after(:all) do
17
+ tester.config.listeners(:after_all).each do |l|
18
+ l.call(tester.config)
19
+ end
20
+ end
21
+ tester.config.each_scope do |scope|
22
+ client = scope.get_client
23
+ scope.each_specification do |specification|
24
+ scope.each_service(specification) do |service|
25
+ scope.each_testcase(service) do |test_case|
26
+ str = "#{service} #{test_case}"
27
+ str = Webspicy::Support::Colorize.colorize_highlight(str, tester.config)
28
+ describe(str) do
29
+
30
+ around(:each) do |example|
31
+ client.around(test_case) do
32
+ client.before(test_case)
33
+ test_case.instrument(client)
34
+ client.instrument(test_case)
35
+ @response = client.call(test_case)
36
+ @invocation = Tester::Invocation.new(test_case, @response, client)
37
+ example.run
38
+ client.after(test_case, @invocation)
39
+ @invocation
40
+ end
41
+ end
42
+
43
+ let(:invocation) do
44
+ @invocation
45
+ end
46
+
47
+ it "meets its specification" do
48
+ raise "Test not ran" unless invocation.done?
49
+ RSpecAsserter.call(self, invocation)
50
+ end
51
+
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ self
59
+ end
60
+
61
+ end # class RSpecTester
62
+ end # class Tester
63
+ end # module Webspicy
@@ -1,11 +1,13 @@
1
1
  module Webspicy
2
2
  class Specification
3
+ include Support::DataObject
3
4
 
4
5
  def initialize(raw, location = nil)
5
- @raw = raw
6
+ super(raw)
6
7
  @location = location
7
8
  bind_services
8
9
  end
10
+ attr_accessor :config
9
11
  attr_reader :location
10
12
 
11
13
  def self.info(raw)
@@ -14,11 +16,13 @@ module Webspicy
14
16
 
15
17
  def self.singleservice(raw)
16
18
  converted = {
17
- name: raw.has_key?(:name) ? raw[:name] : "Unamed specification",
19
+ name: raw[:name] || "Unamed specification",
18
20
  url: raw[:url],
19
- services: [raw.reject{|k, _| k == :name || k == :url}]
21
+ services: [
22
+ Webspicy.service(raw.reject{|k| k==:url or k==:name }, Webspicy.current_scope)
23
+ ]
20
24
  }
21
- self.info(raw)
25
+ info(converted)
22
26
  end
23
27
 
24
28
  def located_at!(location)
@@ -44,7 +48,7 @@ module Webspicy
44
48
  end
45
49
 
46
50
  def services
47
- @raw[:services]
51
+ @raw[:services] || []
48
52
  end
49
53
 
50
54
  def url_placeholders
@@ -60,10 +64,6 @@ module Webspicy
60
64
  [ url, rest ]
61
65
  end
62
66
 
63
- def to_info
64
- @raw
65
- end
66
-
67
67
  def to_singleservice
68
68
  raise NotImplementedError
69
69
  end
@@ -85,7 +85,7 @@ module Webspicy
85
85
  end
86
86
 
87
87
  def bind_services
88
- (@raw[:services] ||= []).each do |s|
88
+ services.each do |s|
89
89
  s.specification = self
90
90
  end
91
91
  end
@@ -0,0 +1,16 @@
1
+ module Webspicy
2
+ class Specification
3
+ module Errcondition
4
+
5
+ def self.match(service, descr)
6
+ end
7
+
8
+ def instrument(test_case, client)
9
+ end
10
+
11
+ def check(invocation)
12
+ end
13
+
14
+ end # module Errcondition
15
+ end # module Specification
16
+ end # module Webspicy
@@ -40,7 +40,7 @@ module Webspicy
40
40
  def empty_input_counterexamples(service, first)
41
41
  placeholders = service.specification.url_placeholders
42
42
  empty_input = first.params.reject{|k| !placeholders.include?(k) }
43
- if !empty_input.empty? && invalid_input?(service, empty_input)
43
+ if invalid_input?(service, empty_input)
44
44
  [first.mutate({
45
45
  :description => "it is robust to an invalid empty input (RobustToInvalidInput)",
46
46
  :dress_params => false,
@@ -1,13 +1,12 @@
1
1
  module Webspicy
2
2
  class Specification
3
3
  class Service
4
+ include Support::DataObject
4
5
 
5
6
  def initialize(raw)
6
- @raw = raw
7
+ super(raw)
7
8
  bind_examples
8
9
  bind_counterexamples
9
- @preconditions = compile_preconditions
10
- @postconditions = compile_postconditions
11
10
  end
12
11
  attr_accessor :specification
13
12
 
@@ -15,6 +14,10 @@ module Webspicy
15
14
  new(raw)
16
15
  end
17
16
 
17
+ def config
18
+ specification.config
19
+ end
20
+
18
21
  def method
19
22
  @raw[:method]
20
23
  end
@@ -24,7 +27,7 @@ module Webspicy
24
27
  end
25
28
 
26
29
  def preconditions
27
- @preconditions
30
+ @preconditions ||= compile_preconditions
28
31
  end
29
32
 
30
33
  def has_preconditions?
@@ -32,23 +35,31 @@ module Webspicy
32
35
  end
33
36
 
34
37
  def postconditions
35
- @postconditions
38
+ @postconditions ||= compile_postconditions
36
39
  end
37
40
 
38
41
  def has_postconditions?
39
42
  !postconditions.empty?
40
43
  end
41
44
 
45
+ def errconditions
46
+ @errconditions ||= compile_errconditions
47
+ end
48
+
49
+ def has_errconditions?
50
+ !errconditions.empty?
51
+ end
52
+
42
53
  def default_example
43
54
  @raw[:default_example]
44
55
  end
45
56
 
46
57
  def examples
47
- @raw[:examples]
58
+ @raw[:examples] || []
48
59
  end
49
60
 
50
61
  def counterexamples
51
- @raw[:counterexamples]
62
+ @raw[:counterexamples] || []
52
63
  end
53
64
 
54
65
  def generated_counterexamples
@@ -76,28 +87,25 @@ module Webspicy
76
87
  input_schema.dress(params)
77
88
  end
78
89
 
79
- def to_info
80
- @raw
81
- end
82
-
83
90
  def to_s
84
91
  "#{method} #{specification.url}"
85
92
  end
86
93
 
87
94
  private
88
95
 
89
- def scope
90
- Webspicy.current_scope
91
- end
92
-
93
96
  def compile_preconditions
94
97
  @raw[:preconditions] = [@raw[:preconditions]] if @raw[:preconditions].is_a?(String)
95
- compile_conditions(@raw[:preconditions] ||= [], scope.preconditions)
98
+ compile_conditions(@raw[:preconditions] ||= [], config.preconditions)
96
99
  end
97
100
 
98
101
  def compile_postconditions
99
102
  @raw[:postconditions] = [@raw[:postconditions]] if @raw[:postconditions].is_a?(String)
100
- compile_conditions(@raw[:postconditions] ||= [], scope.postconditions)
103
+ compile_conditions(@raw[:postconditions] ||= [], config.postconditions)
104
+ end
105
+
106
+ def compile_errconditions
107
+ @raw[:errconditions] = [@raw[:errconditions]] if @raw[:errconditions].is_a?(String)
108
+ compile_conditions(@raw[:errconditions] ||= [], config.errconditions)
101
109
  end
102
110
 
103
111
  def compile_conditions(descriptions, conditions)
@@ -112,13 +120,13 @@ module Webspicy
112
120
  end
113
121
 
114
122
  def bind_examples
115
- (@raw[:examples] ||= []).each do |ex|
123
+ examples.each do |ex|
116
124
  ex.bind(self, false)
117
125
  end
118
126
  end
119
127
 
120
128
  def bind_counterexamples
121
- (@raw[:counterexamples] ||= []).each do |ex|
129
+ counterexamples.each do |ex|
122
130
  ex.bind(self, true)
123
131
  end
124
132
  end
@@ -1,17 +1,15 @@
1
1
  module Webspicy
2
2
  class Specification
3
3
  class TestCase
4
+ include Support::DataObject
4
5
 
5
6
  def initialize(raw)
6
- @raw = raw
7
+ super(raw)
7
8
  @counterexample = nil
8
9
  end
9
10
  attr_reader :service
10
11
  attr_reader :counterexample
11
12
 
12
- attr_accessor :raw
13
- protected :raw, :raw=
14
-
15
13
  def bind(service, counterexample)
16
14
  @service = service
17
15
  @counterexample = counterexample
@@ -111,13 +109,9 @@ module Webspicy
111
109
  !assert.empty?
112
110
  end
113
111
 
114
- def to_info
115
- @raw
116
- end
117
-
118
112
  def instrument(client)
119
113
  service.preconditions.each do |pre|
120
- pre.instrument(self, client)
114
+ pre.instrument(self, client) if pre.respond_to?(:instrument)
121
115
  end
122
116
  service.postconditions.each do |post|
123
117
  post.instrument(self, client) if post.respond_to?(:instrument)
@@ -1,2 +1,3 @@
1
+ require_relative 'support/data_object'
1
2
  require_relative 'support/status_range'
2
3
  require_relative 'support/colorize'
@@ -0,0 +1,25 @@
1
+ module Webspicy
2
+ module Support
3
+ module DataObject
4
+
5
+ def initialize(raw)
6
+ @raw = raw
7
+ end
8
+ attr_accessor :raw
9
+ protected :raw, :raw=
10
+
11
+ def method_missing(name, *args, &bl)
12
+ if @raw.has_key?(name) && args.empty? && bl.nil?
13
+ @raw[name]
14
+ else
15
+ super
16
+ end
17
+ end
18
+
19
+ def to_info
20
+ @raw
21
+ end
22
+
23
+ end # module DataObject
24
+ end # module Support
25
+ end # module Webspicy
@@ -1,89 +1,15 @@
1
1
  module Webspicy
2
2
  class Tester
3
- include Webspicy::Support::Colorize
4
3
 
5
- def initialize(config)
6
- @config = Configuration.dress(config)
7
- @test_suite = load
8
- end
9
- attr_reader :config
10
-
11
- def call(err=$stderr, out=$stdout)
12
- $_rspec_core_load_started_at = nil
13
- options = RSpec::Core::ConfigurationOptions.new(config.rspec_options)
14
- conf = RSpec::Core::Configuration.new
15
- RSpec::Core::Runner.new(options, conf).run(err, out)
16
- end
17
-
18
- # protected
19
-
20
- def load
21
- tester = self
22
- RSpec.reset
23
- rspec_config!
24
- RSpec.describe "" do
25
- before(:all) do
26
- tester.config.listeners(:before_all).each do |l|
27
- l.call(tester.config)
28
- end
29
- end
30
- after(:all) do
31
- tester.config.listeners(:after_all).each do |l|
32
- l.call(tester.config)
33
- end
34
- end
35
- tester.config.each_scope do |scope|
36
- client = scope.get_client
37
- scope.each_specification do |specification|
38
- scope.each_service(specification) do |service|
39
- tester.rspec_service!(self, service, client, scope)
40
- end
41
- end
42
- end
43
- end
44
- self
45
- end
46
-
47
- def rspec_service!(on, service, client, scope)
48
- scope.each_testcase(service) do |test_case|
49
- str = "#{service} #{test_case}"
50
- str = colorize_highlight(str)
51
- on.describe(str) do
52
- include_examples 'a successful test case invocation', client, test_case
53
- end
54
- end
55
- end
56
-
57
- def rspec_config!
58
- RSpec.shared_examples "a successful test case invocation" do |client, test_case|
59
-
60
- around(:each) do |example|
61
- client.around(test_case) do
62
- client.before(test_case)
63
- test_case.instrument(client)
64
- client.instrument(test_case)
65
- @response = client.call(test_case)
66
- @invocation = Tester::Invocation.new(test_case, @response, client)
67
- example.run
68
- client.after(test_case, @invocation)
69
- @invocation
70
- end
71
- end
72
-
73
- let(:invocation) do
74
- @invocation
75
- end
76
-
77
- it "meets its specification" do
78
- raise "Test not ran" unless invocation.done?
79
- invocation.rspec_assert!(self)
80
- end
81
- end
4
+ def self.new(*args, &bl)
5
+ require_relative 'rspec/tester'
6
+ RSpecTester.new(*args, &bl)
82
7
  end
83
8
 
84
9
  end # class Tester
85
10
  end # module Webspicy
86
11
  require_relative 'tester/client'
87
12
  require_relative 'tester/invocation'
13
+ require_relative 'tester/failure'
88
14
  require_relative 'tester/assertions'
89
15
  require_relative 'tester/asserter'