modspec 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/.rubocop_todo.yml +118 -0
- data/Gemfile +4 -2
- data/README.adoc +508 -17
- data/lib/modspec/conformance_class.rb +39 -10
- data/lib/modspec/conformance_test.rb +40 -13
- data/lib/modspec/identifier.rb +5 -3
- data/lib/modspec/normative_statement.rb +49 -14
- data/lib/modspec/normative_statements_class.rb +39 -12
- data/lib/modspec/suite.rb +242 -5
- data/lib/modspec/version.rb +1 -1
- data/lib/modspec.rb +14 -4
- data/modspec.gemspec +8 -14
- data/spec/conformance_class.liquid +98 -0
- data/spec/fixtures/advanced-cc.yaml +52 -0
- data/spec/fixtures/advanced-json-cc.yaml +24 -0
- data/spec/fixtures/advanced-json-rc.yaml +16 -0
- data/spec/fixtures/advanced-rc.yaml +43 -0
- data/spec/fixtures/basic-quaternion-cc.yaml +44 -0
- data/spec/fixtures/basic-quaternion-json-cc.yaml +24 -0
- data/spec/fixtures/basic-quaternion-json-rc.yaml +17 -0
- data/spec/fixtures/basic-quaternion-json-strict-cc.yaml +22 -0
- data/spec/fixtures/basic-quaternion-json-strict-rc.yaml +19 -0
- data/spec/fixtures/basic-quaternion-rc.yaml +34 -0
- data/spec/fixtures/basic-ypr-cc.yaml +39 -0
- data/spec/fixtures/basic-ypr-json-cc.yaml +23 -0
- data/spec/fixtures/basic-ypr-json-rc.yaml +21 -0
- data/spec/fixtures/basic-ypr-rc.yaml +32 -0
- data/spec/fixtures/chain-cc.yaml +50 -0
- data/spec/fixtures/chain-json-cc.yaml +24 -0
- data/spec/fixtures/chain-json-rc.yaml +20 -0
- data/spec/fixtures/chain-rc.yaml +36 -0
- data/spec/fixtures/frame-spec-cc.yaml +43 -0
- data/spec/fixtures/frame-spec-rc.yaml +27 -0
- data/spec/fixtures/global-cc.yaml +38 -0
- data/spec/fixtures/global-rc.yaml +23 -0
- data/spec/fixtures/graph-cc.yaml +48 -0
- data/spec/fixtures/graph-json-cc.yaml +24 -0
- data/spec/fixtures/graph-json-rc.yaml +20 -0
- data/spec/fixtures/graph-rc.yaml +38 -0
- data/spec/fixtures/series-irregular-cc.yaml +58 -0
- data/spec/fixtures/series-irregular-json-cc.yaml +24 -0
- data/spec/fixtures/series-irregular-json-rc.yaml +20 -0
- data/spec/fixtures/series-irregular-rc.yaml +41 -0
- data/spec/fixtures/series-regular-cc.yaml +63 -0
- data/spec/fixtures/series-regular-json-cc.yaml +24 -0
- data/spec/fixtures/series-regular-json-rc.yaml +20 -0
- data/spec/fixtures/series-regular-rc.yaml +46 -0
- data/spec/fixtures/stream-cc.yaml +49 -0
- data/spec/fixtures/stream-json-cc.yaml +48 -0
- data/spec/fixtures/stream-json-rc.yaml +32 -0
- data/spec/fixtures/stream-rc.yaml +36 -0
- data/spec/fixtures/tangent-point-cc.yaml +43 -0
- data/spec/fixtures/tangent-point-rc.yaml +38 -0
- data/spec/fixtures/time-cc.yaml +32 -0
- data/spec/fixtures/time-rc.yaml +20 -0
- data/spec/modspec/conformance_class_spec.rb +154 -0
- data/spec/modspec/conformance_test_spec.rb +76 -0
- data/spec/modspec/normative_statement_spec.rb +81 -0
- data/spec/modspec/normative_statements_class_spec.rb +61 -0
- data/spec/modspec/suite_spec.rb +109 -0
- data/spec/modspec_spec.rb +25 -0
- data/spec/requirements_class.liquid +93 -0
- data/spec/spec_helper.rb +16 -0
- metadata +67 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e872dc5ba6f3f5108de783fd4dffe75cdafda9c36e30fada467a0955003e21df
|
4
|
+
data.tar.gz: e1c98c303fa34c9f1d7565545031b95e96062dfd513ed4b378a13de3d216552c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57e6d5c5e5d2300b464fecdf0ca7277c3c1da94739c89209b6ca8f158bd1002ea0de081f5da38342a4bbb714486c45e70a9beec588758d3bc12df80c80c5bcb1
|
7
|
+
data.tar.gz: bbd9e71cc21b306075d30c105043399ea94665e9b3e7ddcf56e942e240c97c254a908bd593bf3566e7b76c54c6dae61f78abd252bb80cfbb513c347ad76a0151
|
data/.rubocop.yml
CHANGED
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
data/README.adoc
CHANGED
@@ -2,44 +2,535 @@
|
|
2
2
|
|
3
3
|
== Purpose
|
4
4
|
|
5
|
-
The `modspec` Ruby
|
5
|
+
The `modspec` Ruby library allows you to work with OGC ModSpec instances
|
6
|
+
and export/load them from/to YAML.
|
6
7
|
|
7
|
-
|
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
|
-
|
13
|
+
This library allows you to:
|
11
14
|
|
12
|
-
|
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
|
-
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
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.]
|