modspec 0.1.0 → 0.1.2

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -0
  3. data/.rubocop_todo.yml +118 -0
  4. data/Gemfile +4 -2
  5. data/README.adoc +508 -17
  6. data/lib/modspec/conformance_class.rb +39 -10
  7. data/lib/modspec/conformance_test.rb +40 -13
  8. data/lib/modspec/identifier.rb +5 -3
  9. data/lib/modspec/normative_statement.rb +49 -14
  10. data/lib/modspec/normative_statements_class.rb +39 -12
  11. data/lib/modspec/suite.rb +242 -5
  12. data/lib/modspec/version.rb +1 -1
  13. data/lib/modspec.rb +14 -4
  14. data/modspec.gemspec +8 -14
  15. data/spec/conformance_class.liquid +98 -0
  16. data/spec/fixtures/advanced-cc.yaml +52 -0
  17. data/spec/fixtures/advanced-json-cc.yaml +24 -0
  18. data/spec/fixtures/advanced-json-rc.yaml +16 -0
  19. data/spec/fixtures/advanced-rc.yaml +43 -0
  20. data/spec/fixtures/basic-quaternion-cc.yaml +44 -0
  21. data/spec/fixtures/basic-quaternion-json-cc.yaml +24 -0
  22. data/spec/fixtures/basic-quaternion-json-rc.yaml +17 -0
  23. data/spec/fixtures/basic-quaternion-json-strict-cc.yaml +22 -0
  24. data/spec/fixtures/basic-quaternion-json-strict-rc.yaml +19 -0
  25. data/spec/fixtures/basic-quaternion-rc.yaml +34 -0
  26. data/spec/fixtures/basic-ypr-cc.yaml +39 -0
  27. data/spec/fixtures/basic-ypr-json-cc.yaml +23 -0
  28. data/spec/fixtures/basic-ypr-json-rc.yaml +21 -0
  29. data/spec/fixtures/basic-ypr-rc.yaml +32 -0
  30. data/spec/fixtures/chain-cc.yaml +50 -0
  31. data/spec/fixtures/chain-json-cc.yaml +24 -0
  32. data/spec/fixtures/chain-json-rc.yaml +20 -0
  33. data/spec/fixtures/chain-rc.yaml +36 -0
  34. data/spec/fixtures/frame-spec-cc.yaml +43 -0
  35. data/spec/fixtures/frame-spec-rc.yaml +27 -0
  36. data/spec/fixtures/global-cc.yaml +38 -0
  37. data/spec/fixtures/global-rc.yaml +23 -0
  38. data/spec/fixtures/graph-cc.yaml +48 -0
  39. data/spec/fixtures/graph-json-cc.yaml +24 -0
  40. data/spec/fixtures/graph-json-rc.yaml +20 -0
  41. data/spec/fixtures/graph-rc.yaml +38 -0
  42. data/spec/fixtures/series-irregular-cc.yaml +58 -0
  43. data/spec/fixtures/series-irregular-json-cc.yaml +24 -0
  44. data/spec/fixtures/series-irregular-json-rc.yaml +20 -0
  45. data/spec/fixtures/series-irregular-rc.yaml +41 -0
  46. data/spec/fixtures/series-regular-cc.yaml +63 -0
  47. data/spec/fixtures/series-regular-json-cc.yaml +24 -0
  48. data/spec/fixtures/series-regular-json-rc.yaml +20 -0
  49. data/spec/fixtures/series-regular-rc.yaml +46 -0
  50. data/spec/fixtures/stream-cc.yaml +49 -0
  51. data/spec/fixtures/stream-json-cc.yaml +48 -0
  52. data/spec/fixtures/stream-json-rc.yaml +32 -0
  53. data/spec/fixtures/stream-rc.yaml +36 -0
  54. data/spec/fixtures/tangent-point-cc.yaml +43 -0
  55. data/spec/fixtures/tangent-point-rc.yaml +38 -0
  56. data/spec/fixtures/time-cc.yaml +32 -0
  57. data/spec/fixtures/time-rc.yaml +20 -0
  58. data/spec/modspec/conformance_class_spec.rb +154 -0
  59. data/spec/modspec/conformance_test_spec.rb +76 -0
  60. data/spec/modspec/normative_statement_spec.rb +81 -0
  61. data/spec/modspec/normative_statements_class_spec.rb +61 -0
  62. data/spec/modspec/suite_spec.rb +109 -0
  63. data/spec/modspec_spec.rb +25 -0
  64. data/spec/requirements_class.liquid +93 -0
  65. data/spec/spec_helper.rb +16 -0
  66. metadata +71 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04b72356e376ccef5b03148c33e1c6a06d78d8ae64610c89eda67d8d68dbcb37
4
- data.tar.gz: 6a1960bee2e234b9ca5bb29e9619b3d802831c1660167a3d7730fea0a688bec5
3
+ metadata.gz: a0808f57d0576986304dbf6cdb9e0b6d857518ad36913ad7562ca4eb6efa80db
4
+ data.tar.gz: 69ffc24df78d574268e1825e6be0d18fc892feea45bd264d1fa1f6251cd16a3d
5
5
  SHA512:
6
- metadata.gz: ce7873a1eaaea400d23e7f29cd8bc8c2e670d6857217424dced043454c863c081f783d6afb56e76dfb85b72f7fe4257ad6a96561fc7339d4b8a65b7b0c4d4d2e
7
- data.tar.gz: 8889bde3ccf4cb143d4528768cf0dc38773f2df7368777830f11d0ce7649e9dfc94fd04c8051cf390d4309cd514775932e030274815b71ad94bd81bf5851db5d
6
+ metadata.gz: 82eb97709de2f051afa526e12d8f0458be26fc9dbd691ef36298a6cea5943749018e3df1a0426e94123fbbd9796fa59814b87371cf062efaa5b617cd2772186c
7
+ data.tar.gz: f93557afe166d056ab41149bf870bd76f8a2fbb51ffcbd6a3ef7c98dc4567800d9499d109fd31f4d6272bf31de803d77590def8c75e438f9bcb8cd7d9cc65e39
data/.rubocop.yml CHANGED
@@ -1,3 +1,5 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
1
3
  AllCops:
2
4
  TargetRubyVersion: 3.0
3
5
 
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,118 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2024-09-11 00:07:51 UTC using RuboCop version 1.66.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 4
10
+ # This cop supports safe autocorrection (--autocorrect).
11
+ # Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include.
12
+ # Include: **/*.gemfile, **/Gemfile, **/gems.rb
13
+ Bundler/OrderedGems:
14
+ Exclude:
15
+ - 'Gemfile'
16
+
17
+ # Offense count: 1
18
+ # Configuration parameters: Severity, Include.
19
+ # Include: **/*.gemspec
20
+ Gemspec/RequiredRubyVersion:
21
+ Exclude:
22
+ - 'modspec.gemspec'
23
+
24
+ # Offense count: 10
25
+ # This cop supports safe autocorrection (--autocorrect).
26
+ # Configuration parameters: EnforcedStyle, IndentationWidth.
27
+ # SupportedStyles: aligned, indented, indented_relative_to_receiver
28
+ Layout/MultilineMethodCallIndentation:
29
+ Exclude:
30
+ - 'modspec.gemspec'
31
+ - 'spec/modspec/suite_spec.rb'
32
+
33
+ # Offense count: 4
34
+ # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
35
+ Metrics/AbcSize:
36
+ Max: 33
37
+
38
+ # Offense count: 6
39
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
40
+ # AllowedMethods: refine
41
+ Metrics/BlockLength:
42
+ Max: 138
43
+
44
+ # Offense count: 1
45
+ # Configuration parameters: CountComments, CountAsOne.
46
+ Metrics/ClassLength:
47
+ Max: 204
48
+
49
+ # Offense count: 1
50
+ # Configuration parameters: AllowedMethods, AllowedPatterns.
51
+ Metrics/CyclomaticComplexity:
52
+ Max: 12
53
+
54
+ # Offense count: 5
55
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
56
+ Metrics/MethodLength:
57
+ Max: 18
58
+
59
+ # Offense count: 1
60
+ # Configuration parameters: AllowedMethods, AllowedPatterns.
61
+ Metrics/PerceivedComplexity:
62
+ Max: 12
63
+
64
+ # Offense count: 1
65
+ # Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros.
66
+ # NamePrefix: is_, has_, have_
67
+ # ForbiddenPrefixes: is_, has_, have_
68
+ # AllowedMethods: is_a?
69
+ # MethodDefinitionMacros: define_method, define_singleton_method
70
+ Naming/PredicateName:
71
+ Exclude:
72
+ - 'spec/**/*'
73
+ - 'lib/modspec/normative_statement.rb'
74
+
75
+ # Offense count: 6
76
+ # Configuration parameters: AllowedConstants.
77
+ Style/Documentation:
78
+ Exclude:
79
+ - 'spec/**/*'
80
+ - 'test/**/*'
81
+ - 'lib/modspec/conformance_class.rb'
82
+ - 'lib/modspec/conformance_test.rb'
83
+ - 'lib/modspec/normative_statement.rb'
84
+ - 'lib/modspec/normative_statements_class.rb'
85
+ - 'lib/modspec/suite.rb'
86
+
87
+ # Offense count: 2
88
+ # This cop supports safe autocorrection (--autocorrect).
89
+ Style/IfUnlessModifier:
90
+ Exclude:
91
+ - 'lib/modspec/conformance_class.rb'
92
+ - 'lib/modspec/normative_statements_class.rb'
93
+
94
+ # Offense count: 27
95
+ # This cop supports safe autocorrection (--autocorrect).
96
+ # Configuration parameters: EnforcedStyleForMultiline.
97
+ # SupportedStylesForMultiline: comma, consistent_comma, no_comma
98
+ Style/TrailingCommaInArguments:
99
+ Exclude:
100
+ - 'spec/modspec/conformance_class_spec.rb'
101
+ - 'spec/modspec/conformance_test_spec.rb'
102
+ - 'spec/modspec/normative_statement_spec.rb'
103
+ - 'spec/modspec/normative_statements_class_spec.rb'
104
+
105
+ # Offense count: 6
106
+ # This cop supports safe autocorrection (--autocorrect).
107
+ # Configuration parameters: EnforcedStyleForMultiline.
108
+ # SupportedStylesForMultiline: comma, consistent_comma, no_comma
109
+ Style/TrailingCommaInArrayLiteral:
110
+ Exclude:
111
+ - 'spec/modspec/conformance_class_spec.rb'
112
+
113
+ # Offense count: 13
114
+ # This cop supports safe autocorrection (--autocorrect).
115
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
116
+ # URISchemes: http, https
117
+ Layout/LineLength:
118
+ Max: 247
data/Gemfile CHANGED
@@ -5,5 +5,7 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in modspec.gemspec
6
6
  gemspec
7
7
 
8
- gem "rake", "~> 13.0"
9
- gem "rspec", "~> 3.0"
8
+ gem "equivalent-xml"
9
+ gem "pry"
10
+ gem "rake"
11
+ gem "rspec"
data/README.adoc CHANGED
@@ -2,44 +2,535 @@
2
2
 
3
3
  == Purpose
4
4
 
5
- The `modspec` Ruby gem allows you to work with OGC ModSpec instances.
5
+ The `modspec` Ruby library allows you to work with OGC ModSpec instances
6
+ and export/load them from/to YAML.
6
7
 
7
- NOTE: This is a work-in-progress.
8
+ OGC ModSpec is a specification for specifying requirements and conformance tests
9
+ for standards, described in OGC 08-131r3.
8
10
 
11
+ == Features
9
12
 
10
- == Library
13
+ This library allows you to:
11
14
 
12
- === Usage
15
+ * Create and manipulate ModSpec instances:
16
+ ** normative statements
17
+ ** conformance tests
18
+ ** normative statements classes
19
+ ** conformance classes
20
+ ** unified ModSpec suite
13
21
 
14
- The following code generates OGC ModSpec instances in XML and YAML.
22
+ * Load and save objects from/to YAML
23
+ * Perform validations on ModSpec instances
24
+ * Combine ModSpec suites
25
+
26
+
27
+ == Installation
28
+
29
+ Add this line to your application's Gemfile:
15
30
 
16
31
  [source,ruby]
17
32
  ----
18
- require 'modspec'
19
- doc = IO.read('spec/fixtures/chain-rc.yaml')
20
- ms = Modspec::Suite.from_yaml(doc)
21
- puts ms.to_yaml
33
+ gem 'modspec'
34
+ ----
35
+
36
+ Then execute:
37
+
38
+ [source,shell]
39
+ ----
40
+ $ bundle install
41
+ ----
42
+
43
+ Or install it yourself:
44
+
45
+ [source,shell]
46
+ ----
47
+ $ gem install modspec
48
+ ----
49
+
50
+ == Basics
51
+
52
+ ModSpec instances all have the following core attributes:
53
+
54
+ `identifier`:: A unique identifier for the instance, as a URI.
55
+
56
+ ** The pattern for a ModSpec class is `/<type>/<class>`, where
57
+ *** `<type>` is the type of the instance (`req` for normative statement, `conf` for conformance test)
58
+ *** `<class>` is the name of the class (normative statements class or conformance class)
59
+
60
+ ** The pattern for a normative statement or conformance test is `/<type>/<class>/<name>`, where
61
+
62
+ *** `<type>` is the type of the instance (`req` for normative statement, `conf` for conformance test)
63
+ *** `<class>` is the name of the class (normative statements class or conformance class)
64
+ *** `<name>` is the name of the instance
65
+
66
+ `name`::
67
+ A human-readable name for the instance
68
+
69
+ `description`::
70
+ A description of the instance
71
+
72
+ `guidance`::
73
+ Guidance on how to implement the instance
74
+
75
+
76
+
77
+ == Usage
78
+
79
+ === Normative statements class
80
+
81
+ A normative statements class groups related normative statements.
82
+
83
+ A normative statements class has the following attributes in addition to the core attributes:
84
+
85
+ `subject`::
86
+ The subject of the normative statements class
87
+
88
+ `dependencies`::
89
+ URI(s) of normative statement classes that this class depends on
90
+
91
+ `normative_statements`::
92
+ A list of normative statements that belong to this class
93
+
94
+ `belongs_to`::
95
+ The normative statements class that this class belongs to
96
+
97
+ `reference`::
98
+ A reference to an external document or resource
99
+
100
+ `source`::
101
+ The source of the normative statements class
102
+
103
+
104
+ .Working with normative statements classes
105
+ [example]
106
+ ====
107
+ [source,ruby]
108
+ ----
109
+ normative_statements_class = Modspec::NormativeStatementsClass.new(
110
+ identifier: "/req/example",
111
+ name: "Requirements class",
112
+ dependencies: ["/req/baf"],
113
+ normative_statements: [normative_statement]
114
+ )
22
115
  ----
23
116
 
117
+ [source,ruby]
118
+ ----
119
+ normative_statements_class.to_yaml
120
+ ----
121
+
122
+ [source,yaml]
123
+ ----
124
+ identifier: "/req/example"
125
+ name: "Requirements class"
126
+ dependencies:
127
+ - "/req/baf"
128
+ normative_statements:
129
+ - identifier: "/req/example/foo"
130
+ name: "Example requirement"
131
+ statement: "This is an example requirement."
132
+ dependencies:
133
+ - "/req/bar"
134
+ - "/req/baz/2"
135
+ ----
24
136
 
25
137
  [source,ruby]
26
138
  ----
27
- require 'modspec'
28
- doc = IO.read('spec/fixtures/chain-cc.yaml')
29
- ms = Modspec::Suite.from_yaml(doc)
30
- puts ms.to_yaml
139
+ > yaml = IO.read('example.yaml')
140
+ > normative_statements_class = Modspec::NormativeStatementsClass.from_yaml(yaml)
141
+ > <#Modspec::NormativeStatementsClass:0x00007f8b1b8b3d08 @identifier="/req/example", @name="Requirements class", @dependencies=["/req/baf"], @normative_statements=[<#Modspec::NormativeStatement:0x00007f8b1b8b3d08 @identifier="/req/example/foo", @name="Example requirement", @statement="This is an example requirement.", @dependencies=["/req/bar", "/req/baz/2"]>]>
142
+ > normative_statements_class.name
143
+ > "Requirements class"
144
+ ----
145
+ ====
146
+
147
+ Validations:
148
+
149
+ * *Identifier prefix*: All normative statements within a normative statements
150
+ class must share the same identifier prefix as the class itself, followed by a
151
+ slash and then the statement's own identifier.
152
+
153
+
154
+ === Normative statement
155
+
156
+ A normative statement represents a single requirement in the specification.
157
+
158
+ A normative statement has the following attributes in addition to the core attributes:
159
+
160
+ `subject`::
161
+ The subject of the normative statement
162
+
163
+ `obligation`::
164
+ The obligation level of the class, one of `requirement`, `recommendation`, `permission`. Defaults to `requirement`.
165
+
166
+ `statement`::
167
+ The text of the normative statement
168
+
169
+ `condition`::
170
+ Conditions that must be met for the statement to apply
171
+
172
+ `inherit`::
173
+ URI(s) of normative statement(s) that this statement inherits from
174
+
175
+ `indirect_dependency`::
176
+ URI(s) of normative statement(s) that this statement indirectly depends on
177
+
178
+ `implements`::
179
+ The higher-level normative statement that this statement implements
180
+
181
+ `dependencies`::
182
+ A list of identifiers for other normative statements that this statement depends on.
183
+
184
+ `belongs_to`::
185
+ The normative statements class that this statement belongs to.
186
+
187
+ `reference`::
188
+ A reference to an external document or resource
189
+
190
+ `parts`::
191
+ A list of normative statements classes that this class is composed
192
+
193
+
194
+ .Working with normative statements
195
+ [example]
196
+ ====
197
+ [source,ruby]
198
+ ----
199
+ normative_statement = Modspec::NormativeStatement.new(
200
+ identifier: "/req/example/foo",
201
+ name: "Example requirement",
202
+ statement: "This is an example requirement statement.",
203
+ obligation: "requirement", # default
204
+ parts: [
205
+ "This is a part of the requirement.",
206
+ "This is another part of the requirement."
207
+ ]
208
+ dependencies: ["/req/bar", "/req/baz/2"]
209
+ )
210
+ ----
211
+
212
+ [source,ruby]
213
+ ----
214
+ normative_statement.to_yaml
215
+ ----
216
+
217
+ Will give out:
218
+
219
+ [source,yaml]
220
+ ----
221
+ identifier: /req/example/foo
222
+ name: Example requirement
223
+ statement: This is an example requirement statement.
224
+ dependencies:
225
+ - /req/bar
226
+ - /req/baz/2
227
+ ----
228
+
229
+ And to load a normative statement from a YAML file:
230
+
231
+ [source,ruby]
232
+ ----
233
+ > yaml = IO.read('example-foo.yaml')
234
+ > normative_statement = Modspec::NormativeStatement.from_yaml(yaml)
235
+ > <#Modspec::NormativeStatement:0x00007f8b1b8b3d08 @identifier="/req/example/foo", @name="Example requirement", @statement="This is an example requirement statement.", @dependencies=["/req/bar", "/req/baz/2"]>
236
+ > normative_statement.name
237
+ > "Example requirement"
238
+ ----
239
+ ====
240
+
241
+
242
+ Validations:
243
+
244
+ * *Unique identifier*: Each normative statement must have a unique identifier
245
+ within its parent normative statements class.
246
+
247
+ * *Valid dependencies*: The dependencies listed for a normative statement must
248
+ refer to valid identifiers of other normative statements.
249
+
250
+
251
+ === Conformance class
252
+
253
+ A conformance class groups related conformance tests.
254
+
255
+ A conformance class has the following attributes in addition to the core attributes:
256
+
257
+ `tests`::
258
+ A set of conformance tests that belong to this class
259
+
260
+ `classification`::
261
+ A classification of the conformance class
262
+
263
+ `dependencies`::
264
+ A list of identifiers for other conformance classes that this class depends on
265
+
266
+ `target`::
267
+ A list of identifiers of normative statement(s) that this class targets
268
+
269
+ `belongs_to`::
270
+ A conformance class that this class belongs to
271
+
272
+ `reference`::
273
+ A reference to an external document or resource
274
+
275
+
276
+ .Working with conformance classes
277
+ [example]
278
+ ====
279
+ [source,ruby]
280
+ ----
281
+ conformance_class = Modspec::ConformanceClass.new(
282
+ identifier: "/conf/example",
283
+ name: "Conformance class",
284
+ tests: [conformance_test]
285
+ )
286
+ conformance_class.to_yaml
287
+ ----
288
+
289
+ [source,yaml]
290
+ ----
291
+ identifier: "/conf/example"
292
+ name: "Conformance class"
293
+ tests:
294
+ - identifier: "/conf/example/foo"
295
+ name: "Example test"
296
+ description: "This is an example conformance test."
297
+ targets:
298
+ - "/req/example/foo"
299
+ ----
300
+
301
+ [source,ruby]
302
+ ----
303
+ > yaml = IO.read('example.yaml')
304
+ > conformance_class = Modspec::ConformanceClass.from_yaml(yaml)
305
+ > <#Modspec::ConformanceClass:0x00007f8b1b8b3d08 @identifier="/conf/example", @name="Conformance class", @tests=[<#Modspec::ConformanceTest:0x00007f8b1b8b3d08 @identifier="/conf/example/foo", @name="Example test", @description="This is an example conformance test.", @targets=["/req/example/foo"]>], @abstract=false>
306
+ > conformance_class.name
307
+ > "Conformance class"
308
+ ----
309
+ ====
310
+
311
+
312
+ Validations:
313
+
314
+ * *Identifier prefix*: All conformance tests within a conformance class must
315
+ share the same identifier prefix as the class itself, followed by a slash and
316
+ then the test's own identifier.
317
+
318
+ * *Valid targets*: The targets listed for a conformance test must refer to valid
319
+ identifiers of existing normative statements.
320
+
321
+
322
+
323
+ === Conformance test
324
+
325
+ A conformance test verifies compliance with one or more normative statements.
326
+
327
+ A conformance test has the following attributes in addition to the core attributes:
328
+
329
+ `targets`::
330
+ A list of identifiers for normative statements that this test targets
331
+
332
+ `belongs_to`::
333
+ The conformance class that this test belongs to
334
+
335
+ `guidance`::
336
+ Guidance on how to perform the test
337
+
338
+ `purpose`::
339
+ The purpose of the test
340
+
341
+ `method`::
342
+ The method used to perform the test
343
+
344
+ `type`::
345
+ The type of the test
346
+
347
+ `reference`::
348
+ A reference to an external document or resource
349
+
350
+ `abstract`::
351
+ A boolean indicating whether this test is abstract
352
+
353
+
354
+
355
+ .Working with conformance tests
356
+ [example]
357
+ ====
358
+ [source,ruby]
359
+ ----
360
+ conformance_test = Modspec::ConformanceTest.new(
361
+ identifier: "/conf/example/foo",
362
+ name: "Example test",
363
+ description: "This is an example conformance test.",
364
+ targets: ["/req/example/foo"],
365
+ test_method: "manual",
366
+ abstract: false
367
+ )
368
+ conformance_test.to_yaml
31
369
  ----
32
370
 
371
+ [source,yaml]
372
+ ----
373
+ identifier: "/conf/example/foo"
374
+ name: "Example test"
375
+ description: "This is an example conformance test."
376
+ abstract: false
377
+ test_method: "manual"
378
+ targets:
379
+ - "/req/example/foo"
380
+ ----
381
+
382
+ [source,ruby]
383
+ ----
384
+ > yaml = IO.read('example.yaml')
385
+ > conformance_test = Modspec::ConformanceTest.from_yaml(yaml)
386
+ > <#Modspec::ConformanceTest:0x00007f8b1b8b3d08 @identifier="/conf/example/foo", @name="Example test", @description="This is an example conformance test.", @targets=["/req/example/foo"], @test_method="manual", @abstract=false>
387
+ > conformance_test.name
388
+ > "Example test"
389
+ ----
390
+ ====
391
+
392
+
393
+ Validations:
394
+
395
+ * *Valid targets*: The targets listed for a conformance test must refer to valid
396
+ identifiers of existing normative statements.
397
+
398
+
399
+ === Suite
400
+
401
+ A suite represents the entire specification, including all normative statements
402
+ and conformance tests.
403
+
404
+ NOTE: This is not defined in the ModSpec specification.
405
+
406
+ .Working with suites
407
+ [example]
408
+ ====
409
+ [source,ruby]
410
+ ----
411
+ suite = Modspec::Suite.new(
412
+ identifier: "example-suite",
413
+ name: "Example suite",
414
+ normative_statements_classes: [normative_statements_class],
415
+ conformance_classes: [conformance_class]
416
+ )
417
+ suite.to_yaml
418
+ ----
419
+
420
+ [source,yaml]
421
+ ----
422
+ identifier: "example-suite"
423
+ name: "Example suite"
424
+ normative_statements_classes:
425
+ - identifier: "/req/example"
426
+ name: "Requirements class"
427
+ normative_statements:
428
+ - identifier: "/req/example/foo"
429
+ name: "Example requirement"
430
+ statement: "This is an example requirement statement."
431
+ dependencies:
432
+ - "/req/bar"
433
+ - "/req/baz/2"
434
+ conformance_classes:
435
+ - identifier: "/conf/example"
436
+ name: "Conformance class"
437
+ tests:
438
+ - identifier: "/conf/example/foo"
439
+ name: "Example test"
440
+ description: "This is an example conformance test."
441
+ targets:
442
+ - "/req/example/foo"
443
+ ----
444
+
445
+ [source,ruby]
446
+ ----
447
+ > yaml = IO.read('example-suite.yaml')
448
+ > suite = Modspec::Suite.from_yaml(yaml)
449
+ > <#Modspec::Suite:0x00007f8b1b8b3d08 @identifier="example-suite", @name="Example suite", @normative_statements_classes=[<#Modspec::NormativeStatementsClass:0x00007f8b1b8b3d08 @identifier="/req/example", @name="Requirements class", @dependencies=["/req/baf"], @normative_statements=[<#Modspec::NormativeStatement:0x00007f8b1b8b3d08 @identifier="/req/example/foo", @name="Example requirement", @statement="This is an example requirement statement.", @dependencies=["/req/bar", "/req/baz/2"]>]>], @conformance_classes=[<#Modspec::ConformanceClass:0x00007f8b1b8b3d08 @identifier="/conf/example", @name="Conformance class", @tests=[<#Modspec::ConformanceTest:0x00007f8b1b8b3d08 @identifier="/conf/example/foo", @name="Example test", @description="This is an example conformance test.", @targets=["/req/example/foo"]>], @abstract=false>]>
450
+ > suite.normative_statements_classes.first.name
451
+ > "Requirements class"
452
+ ----
453
+ ====
454
+
455
+ Validations:
456
+
457
+ * *No cyclic dependencies*: The suite ensures that there are no circular
458
+ dependencies among normative statements.
459
+
460
+ * *Label uniqueness*: Labels must be unique across all classes within the suite.
461
+
462
+ * *Dependency validation*: The suite verifies that all dependencies between
463
+ normative statements and conformance tests are valid and refer to existing
464
+ elements.
465
+
466
+
467
+ The Suite class provides a `from_yaml_files` method to load a Suite instance
468
+ from multiple YAML files. This is particularly useful when your specification is
469
+ split across several files for better organization and maintainability.
470
+
471
+ To load a Suite from multiple YAML files:
33
472
 
34
473
  [source,ruby]
35
474
  ----
36
475
  require 'modspec'
37
- doc = YAML.load(IO.read('spec/fixtures/chain-rc.yaml'))['normative-statements-classes'].first
38
- ms = Modspec::NormativeStatementsClass.from_hash(doc)
39
- puts ms.to_yaml
476
+
477
+ # Specify the paths to your YAML files
478
+ yaml_files = [
479
+ 'path/to/normative_statements.yaml',
480
+ 'path/to/conformance_tests.yaml'
481
+ ]
482
+
483
+ # Create a Suite instance from the YAML files
484
+ suite = Modspec::Suite.from_yaml_files(yaml_files)
485
+
486
+ # Now you can work with the suite object
487
+ puts suite.name
488
+ puts suite.normative_statements_classes.count
489
+ puts suite.conformance_classes.count
490
+ ----
491
+
492
+
493
+ The `Suite` class provides a `combine` method to merge two suites:
494
+
495
+ [source,ruby]
496
+ ----
497
+ combined_suite = suite1.combine(suite2)
498
+ ----
499
+
500
+ This method merges the two suites into a single suite, ensuring that the
501
+ resulting suite is consistent and free of conflicts.
502
+
503
+
504
+ === Validation process
505
+
506
+ Validations are typically performed when:
507
+
508
+ . Creating or modifying individual elements (normative statements, conformance tests, etc.)
509
+ . Adding elements to their respective classes
510
+ . Combining suites
511
+ . Loading a suite from YAML or other formats
512
+
513
+ If any validation fails, an error or a collection of errors is returned,
514
+ describing the specific validation issues encountered.
515
+
516
+ To manually trigger validation on a suite:
517
+
518
+ [source,ruby]
519
+ ----
520
+ errors = suite.validate_all
521
+ if errors.any?
522
+ puts "Validation errors:"
523
+ errors.each { |error| puts "- #{error}" }
524
+ else
525
+ puts "Suite is valid."
526
+ end
40
527
  ----
41
528
 
42
- == Credits
529
+ These validation mechanisms help ensure that the created ModSpec instances are
530
+ consistent, well-formed, and adhere to the expected structure and relationships.
531
+
532
+
533
+ == Copyright
43
534
 
44
535
  This gem is developed, maintained and funded by
45
536
  https://www.ribose.com[Ribose Inc.]