webspicy 0.16.3 → 0.17.0

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -3
  3. data/examples/restful/Gemfile.lock +14 -13
  4. data/examples/restful/webspicy/config.rb +1 -0
  5. data/examples/restful/webspicy/{todo/deleteTodo.yml → formaldef/todo/_one/delete.yml} +3 -0
  6. data/examples/restful/webspicy/{todo/getTodoSingleServiceFormat.yml → formaldef/todo/_one/get.simpler.yml} +0 -0
  7. data/examples/restful/webspicy/{todo/getTodo.yml → formaldef/todo/_one/get.yml} +0 -0
  8. data/examples/restful/webspicy/{todo/patchTodo.yml → formaldef/todo/_one/patch.yml} +0 -0
  9. data/examples/restful/webspicy/{todo/putTodo.yml → formaldef/todo/_one/put.yml} +0 -0
  10. data/examples/restful/webspicy/{todo/getTodos.yml → formaldef/todo/get.yml} +0 -0
  11. data/examples/restful/webspicy/{todo → formaldef/todo}/options.yml +0 -0
  12. data/examples/restful/webspicy/{todo/postCsv.yml → formaldef/todo/post.csv.yml} +0 -0
  13. data/examples/restful/webspicy/{todo/postFile.yml → formaldef/todo/post.file.yml} +0 -0
  14. data/examples/restful/webspicy/{todo/postTodos.yml → formaldef/todo/post.yml} +0 -0
  15. data/examples/restful/webspicy/{todo → formaldef/todo}/todos.csv +0 -0
  16. data/examples/restful/webspicy/support/todo_not_removed.rb +21 -0
  17. data/examples/restful/webspicy/support/todo_removed.rb +5 -3
  18. data/lib/webspicy.rb +1 -0
  19. data/lib/webspicy/checker.rb +5 -20
  20. data/lib/webspicy/configuration.rb +9 -0
  21. data/lib/webspicy/configuration/scope.rb +0 -8
  22. data/lib/webspicy/formaldoc.fio +2 -0
  23. data/lib/webspicy/rspec/checker.rb +2 -0
  24. data/lib/webspicy/rspec/checker/rspec_checker.rb +24 -0
  25. data/lib/webspicy/rspec/support/rspec_runnable.rb +27 -0
  26. data/lib/webspicy/rspec/tester.rb +4 -0
  27. data/lib/webspicy/{tester → rspec/tester}/rspec_asserter.rb +23 -10
  28. data/lib/webspicy/{tester → rspec/tester}/rspec_matchers.rb +10 -0
  29. data/lib/webspicy/rspec/tester/rspec_tester.rb +63 -0
  30. data/lib/webspicy/specification.rb +5 -7
  31. data/lib/webspicy/specification/errcondition.rb +16 -0
  32. data/lib/webspicy/specification/service.rb +27 -19
  33. data/lib/webspicy/specification/test_case.rb +3 -9
  34. data/lib/webspicy/support.rb +1 -0
  35. data/lib/webspicy/support/data_object.rb +25 -0
  36. data/lib/webspicy/tester.rb +4 -78
  37. data/lib/webspicy/tester/asserter.rb +9 -4
  38. data/lib/webspicy/tester/assertions.rb +8 -9
  39. data/lib/webspicy/tester/failure.rb +6 -0
  40. data/lib/webspicy/tester/invocation.rb +8 -156
  41. data/lib/webspicy/version.rb +2 -2
  42. data/spec/unit/configuration/scope/test_each_service.rb +2 -2
  43. data/spec/unit/configuration/scope/test_each_specification.rb +7 -7
  44. data/spec/unit/test_configuration.rb +1 -1
  45. data/spec/unit/tester/test_asserter.rb +198 -3
  46. data/spec/unit/tester/test_assertions.rb +8 -6
  47. metadata +27 -18
@@ -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)
@@ -46,7 +48,7 @@ module Webspicy
46
48
  end
47
49
 
48
50
  def services
49
- @raw[:services]
51
+ @raw[:services] || []
50
52
  end
51
53
 
52
54
  def url_placeholders
@@ -62,10 +64,6 @@ module Webspicy
62
64
  [ url, rest ]
63
65
  end
64
66
 
65
- def to_info
66
- @raw
67
- end
68
-
69
67
  def to_singleservice
70
68
  raise NotImplementedError
71
69
  end
@@ -87,7 +85,7 @@ module Webspicy
87
85
  end
88
86
 
89
87
  def bind_services
90
- (@raw[:services] ||= []).each do |s|
88
+ services.each do |s|
91
89
  s.specification = self
92
90
  end
93
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
@@ -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'
@@ -78,14 +78,19 @@ module Webspicy
78
78
  expected = id
79
79
  id, path = path, ''
80
80
  end
81
- unless @assertions.idFD(@target, path, id, expected)
82
- _! "Expected #{_s(@target, path)} to meet FD #{expected.inspect}"
81
+ element = @assertions.element_with_id(@target, path, id)
82
+ unless element
83
+ _! "Expected an element with id #{id} to contain the key(s) and value(s) #{expected}, but there is no element with that id"
84
+ end
85
+
86
+ unless @assertions.idFD(element, expected)
87
+ _! "Expected #{_s(@target, path)} to contain the key(s) and value(s) #{expected}"
83
88
  end
84
89
  end
85
90
 
86
91
  def pathFD(path, expected)
87
92
  unless @assertions.pathFD(@target, path, expected)
88
- _! "#{expected.inspect} vs. #{_s(@target, path)}"
93
+ _! "Expected #{_s(@target, path)} to contain the key(s) and value(s) #{expected}"
89
94
  end
90
95
  end
91
96
 
@@ -121,7 +126,7 @@ module Webspicy
121
126
  end
122
127
 
123
128
  def _!(msg)
124
- raise msg
129
+ raise Failure, msg
125
130
  end
126
131
 
127
132
  end # class Asserter
@@ -63,16 +63,15 @@ module Webspicy
63
63
  (ids.to_set & expected.to_set).empty?
64
64
  end
65
65
 
66
- def idFD(target, path, id, expected = NO_ARG)
67
- if expected == NO_ARG
68
- expected = id
69
- id, path = path, ''
70
- end
66
+ def element_with_id(target, path, id)
71
67
  target = extract_path(target, path)
72
- found = an_array(target).find{|t| t[:id] == id }
73
- expected.keys.all?{|k|
74
- value_equal(expected[k], found[k])
75
- }
68
+ an_array(target).find { |t| t[:id] == id }
69
+ end
70
+
71
+ def idFD(element, expected)
72
+ expected.keys.all? do |k|
73
+ value_equal(expected[k], element[k])
74
+ end
76
75
  end
77
76
 
78
77
  def pathFD(target, path, expected)