earl-report 0.1.2 → 0.2.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.
- data/README.md +1 -1
- data/VERSION +1 -1
- data/bin/earl-report +3 -6
- data/lib/earl_report.rb +114 -61
- data/lib/earl_report/views/earl_report.html.haml +113 -51
- data/spec/earl_report_spec.rb +181 -186
- data/spec/test-files/results.html +123 -79
- data/spec/test-files/results.jsonld +65 -48
- data/spec/test-files/results.ttl +18 -10
- metadata +3 -3
data/README.md
CHANGED
@@ -78,7 +78,7 @@ The `earl-report` command may be used to directly create a report from zero or m
|
|
78
78
|
|
79
79
|
gem install earl-report
|
80
80
|
|
81
|
-
earl \
|
81
|
+
earl-report \
|
82
82
|
--base # Base URI to use when loading test manifest
|
83
83
|
--bibRef # ReSpec BibRef of specification being reported upon
|
84
84
|
--format # Format of output, one of 'ttl', 'json', or 'html'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/bin/earl-report
CHANGED
@@ -6,15 +6,12 @@ require 'earl_report'
|
|
6
6
|
require 'getoptlong'
|
7
7
|
require 'yaml'
|
8
8
|
|
9
|
-
def run(input, options)
|
10
|
-
end
|
11
|
-
|
12
9
|
OPT_ARGS = [
|
13
10
|
["--base", GetoptLong::REQUIRED_ARGUMENT,"Base URI to use when loading test manifest"],
|
14
11
|
["--bibRef", GetoptLong::REQUIRED_ARGUMENT,"ReSpec BibRef of specification being reported upon"],
|
15
12
|
["--format", "-f", GetoptLong::REQUIRED_ARGUMENT,"Format of output, one of 'ttl', 'json', or 'html'"],
|
16
13
|
["--json", GetoptLong::NO_ARGUMENT, "Input is a JSON-LD formatted result"],
|
17
|
-
["--manifest", GetoptLong::REQUIRED_ARGUMENT,"Test manifest"],
|
14
|
+
["--manifest", GetoptLong::REQUIRED_ARGUMENT,"Test manifest(s)"],
|
18
15
|
["--name", GetoptLong::REQUIRED_ARGUMENT,"Name of specification"],
|
19
16
|
["--output", "-o", GetoptLong::REQUIRED_ARGUMENT,"Output report to file"],
|
20
17
|
["--query", GetoptLong::REQUIRED_ARGUMENT,"Query, or file containing query for extracting information from Test manifest"],
|
@@ -58,8 +55,8 @@ opts.each do |opt, arg|
|
|
58
55
|
when '--base' then options[:base] = arg
|
59
56
|
when '--bibRef' then options[:bibRef] = arg
|
60
57
|
when '--format' then options[:format] = arg.to_sym
|
61
|
-
when '--manifest' then options[:manifest] = arg
|
62
|
-
when '--query' then options[:
|
58
|
+
when '--manifest' then options[:manifest] = arg.split(',').map(&:strip)
|
59
|
+
when '--query' then options[:query] = arg
|
63
60
|
when '--base' then options[:base] = arg
|
64
61
|
when '--json' then options[:json] = true
|
65
62
|
when '--name' then options[:name] = arg
|
data/lib/earl_report.rb
CHANGED
@@ -11,18 +11,26 @@ class EarlReport
|
|
11
11
|
|
12
12
|
attr_reader :graph
|
13
13
|
|
14
|
+
# Return information about each test, and for the first test in the
|
15
|
+
# manifest, about the manifest itself
|
14
16
|
MANIFEST_QUERY = %(
|
15
17
|
PREFIX dc: <http://purl.org/dc/terms/>
|
16
18
|
PREFIX mf: <http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#>
|
17
19
|
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
18
20
|
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
19
21
|
|
20
|
-
SELECT ?lh ?uri ?title ?description ?testAction ?testResult
|
22
|
+
SELECT ?lh ?uri ?type ?title ?description ?testAction ?testResult ?manUri ?manComment
|
21
23
|
WHERE {
|
22
|
-
?uri
|
23
|
-
|
24
|
-
|
25
|
-
OPTIONAL {
|
24
|
+
?uri a ?type;
|
25
|
+
mf:name ?title;
|
26
|
+
mf:action ?testAction .
|
27
|
+
OPTIONAL { ?uri rdfs:comment ?description . }
|
28
|
+
OPTIONAL { ?uri mf:result ?testResult . }
|
29
|
+
OPTIONAL {
|
30
|
+
?manUri a mf:Manifest; mf:entries ?lh .
|
31
|
+
?lh rdf:first ?uri .
|
32
|
+
OPTIONAL { ?manUri rdfs:comment ?manComment . }
|
33
|
+
}
|
26
34
|
}
|
27
35
|
).freeze
|
28
36
|
|
@@ -37,9 +45,9 @@ class EarlReport
|
|
37
45
|
OPTIONAL { ?uri doap:homepage ?homepage . }
|
38
46
|
OPTIONAL { ?uri doap:description ?doapDesc . }
|
39
47
|
OPTIONAL { ?uri doap:programming-language ?language . }
|
48
|
+
OPTIONAL { ?developer a ?devType .}
|
40
49
|
OPTIONAL { ?developer foaf:name ?devName .}
|
41
|
-
OPTIONAL { ?developer
|
42
|
-
OPTIONAL { ?developer foaf:homepage ?devHomepage . }
|
50
|
+
OPTIONAL { ?developer foaf:homepage ?devHomepage .}
|
43
51
|
}
|
44
52
|
).freeze
|
45
53
|
|
@@ -101,7 +109,7 @@ class EarlReport
|
|
101
109
|
test: {"@type" => "@id"},
|
102
110
|
testAction: {"@id" => "mf:action", "@type" => "@id"},
|
103
111
|
testResult: {"@id" => "mf:result", "@type" => "@id"},
|
104
|
-
|
112
|
+
entries: {"@id" => "mf:entries", "@type" => "@id", "@container" => "@list"},
|
105
113
|
testSubjects: {"@type" => "@id", "@container" => "@list"},
|
106
114
|
title: {"@id" => "dc:title"},
|
107
115
|
xsd: {"@id" => "http://www.w3.org/2001/XMLSchema#"}
|
@@ -120,14 +128,14 @@ class EarlReport
|
|
120
128
|
# @option options [String] :bibRef
|
121
129
|
# ReSpec bibliography reference for specification being tested
|
122
130
|
# @option options [String] :json Result of previous JSON-LD generation
|
123
|
-
# @option options [String] :manifest Test manifest
|
131
|
+
# @option options [String, Array<String>] :manifest Test manifest
|
124
132
|
# @option options [String] :name Name of specification
|
125
133
|
# @option options [String] :query
|
126
|
-
# Query, or file containing query for extracting information from Test
|
134
|
+
# Query, or file containing query for extracting information from Test manifests
|
127
135
|
def initialize(*files)
|
128
136
|
@options = files.last.is_a?(Hash) ? files.pop.dup : {}
|
129
137
|
@options[:query] ||= MANIFEST_QUERY
|
130
|
-
raise "Test
|
138
|
+
raise "Test Manifests must be specified with :manifest option" unless @options[:manifest] || @options[:json]
|
131
139
|
raise "Require at least one input file" if files.empty?
|
132
140
|
@files = files
|
133
141
|
@prefixes = {}
|
@@ -136,12 +144,16 @@ class EarlReport
|
|
136
144
|
return
|
137
145
|
end
|
138
146
|
|
139
|
-
# Load
|
140
|
-
status "read #{@options[:manifest]}"
|
147
|
+
# Load manifests, possibly with base URI
|
148
|
+
status "read #{@options[:manifest].inspect}"
|
141
149
|
man_opts = {}
|
142
150
|
man_opts[:base_uri] = RDF::URI(@options[:base]) if @options[:base]
|
143
|
-
@graph = RDF::Graph.
|
144
|
-
|
151
|
+
@graph = RDF::Graph.new
|
152
|
+
[@options[:manifest]].flatten.compact.each do |man|
|
153
|
+
g = RDF::Graph.load(man, man_opts)
|
154
|
+
status " loaded #{g.count} triples from #{man}"
|
155
|
+
@graph << g
|
156
|
+
end
|
145
157
|
|
146
158
|
# Read test assertion files
|
147
159
|
files.flatten.each do |file|
|
@@ -244,8 +256,8 @@ class EarlReport
|
|
244
256
|
{
|
245
257
|
"@context" => TEST_CONTEXT,
|
246
258
|
"@id" => "",
|
247
|
-
"@type" =>
|
248
|
-
'
|
259
|
+
"@type" => %w(earl:Software doap:Project),
|
260
|
+
'name' => @options[:name],
|
249
261
|
'bibRef' => @options[:bibRef],
|
250
262
|
'generatedBy' => {
|
251
263
|
"@id" => "http://rubygems.org/gems/earl-report",
|
@@ -270,9 +282,9 @@ class EarlReport
|
|
270
282
|
"foaf:homepage" => "http://greggkellogg.net/"
|
271
283
|
}
|
272
284
|
},
|
273
|
-
"assertions"
|
274
|
-
'testSubjects'
|
275
|
-
'
|
285
|
+
"assertions" => @files,
|
286
|
+
'testSubjects' => json_test_subject_info,
|
287
|
+
'entries' => json_result_info
|
276
288
|
}
|
277
289
|
end
|
278
290
|
end
|
@@ -298,7 +310,7 @@ class EarlReport
|
|
298
310
|
dev['foaf:homepage'] = solution[:devHomepage].to_s if solution[:devHomepage]
|
299
311
|
(info['developer'] ||= []) << dev
|
300
312
|
end
|
301
|
-
info['developer'] = info['developer'].uniq
|
313
|
+
info['developer'] = info['developer'].uniq if info['developer']
|
302
314
|
end
|
303
315
|
|
304
316
|
# Map ids and values to array entries
|
@@ -319,8 +331,9 @@ class EarlReport
|
|
319
331
|
# Return result information for each test.
|
320
332
|
# This counts on hash maintaining insertion order
|
321
333
|
#
|
322
|
-
# @return [Array]
|
334
|
+
# @return [Array<Hash>] List of manifests
|
323
335
|
def json_result_info
|
336
|
+
manifests = []
|
324
337
|
test_cases = {}
|
325
338
|
subjects = json_test_subject_info.map {|s| s['@id']}
|
326
339
|
|
@@ -330,44 +343,67 @@ class EarlReport
|
|
330
343
|
.inject({}) {|memo, soln| memo[soln[:uri]] = soln; memo}
|
331
344
|
|
332
345
|
# If test cases are in a list, maintain order
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
346
|
+
solutions.values.select {|s| s[:manUri]}.each do |man_soln|
|
347
|
+
# Get tests for this manifest in list order
|
348
|
+
solution_list = RDF::List.new(man_soln[:lh], @graph)
|
349
|
+
|
350
|
+
# Set up basic manifest information
|
351
|
+
man_info = manifests.detect {|m| m['@id'] == man_soln[:manUri].to_s}
|
352
|
+
unless man_info
|
353
|
+
status "manifest: #{man_soln[:manUri]}"
|
354
|
+
man_info = {
|
355
|
+
'@id' => man_soln[:manUri].to_s,
|
356
|
+
"@type" => %w{earl:Report mf:Manifest},
|
357
|
+
'title' => man_soln[:manComment].to_s,
|
358
|
+
'entries' => []
|
359
|
+
}
|
360
|
+
manifests << man_info
|
361
|
+
end
|
338
362
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
'
|
344
|
-
'@
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
# Pre-initialize results for each subject to untested
|
353
|
-
subjects.each do |siri|
|
354
|
-
tc_hash['assertions'] << {
|
355
|
-
'@type' => 'earl:Assertion',
|
356
|
-
'test' => uri.to_s,
|
357
|
-
'subject' => siri,
|
358
|
-
'result' => {
|
359
|
-
'@type' => 'earl:TestResult',
|
360
|
-
'outcome' => 'earl:untested'
|
363
|
+
# Collect each TestCase
|
364
|
+
solution_list.each do |uri|
|
365
|
+
solution = solutions[uri]
|
366
|
+
|
367
|
+
# Create entry for this test case, if it doesn't already exist
|
368
|
+
tc = man_info['entries'].detect {|t| t['@id'] == uri}
|
369
|
+
unless tc
|
370
|
+
tc = {
|
371
|
+
'@id' => uri.to_s,
|
372
|
+
'@type' => %w(earl:TestCriterion earl:TestCase),
|
373
|
+
'title' => solution[:title].to_s,
|
374
|
+
'testAction' => solution[:testAction].to_s,
|
375
|
+
'assertions' => []
|
361
376
|
}
|
362
|
-
|
377
|
+
tc['@type'] << solution[:type].to_s if solution[:type]
|
378
|
+
tc['description'] = solution[:description].to_s if solution[:description]
|
379
|
+
tc['testResult'] = solution[:testResult].to_s if solution[:testResult]
|
380
|
+
|
381
|
+
# Pre-initialize results for each subject to untested
|
382
|
+
subjects.each do |siri|
|
383
|
+
tc['assertions'] << {
|
384
|
+
'@type' => 'earl:Assertion',
|
385
|
+
'test' => uri.to_s,
|
386
|
+
'subject' => siri,
|
387
|
+
'mode' => 'earl:automatic',
|
388
|
+
'result' => {
|
389
|
+
'@type' => 'earl:TestResult',
|
390
|
+
'outcome' => 'earl:untested'
|
391
|
+
}
|
392
|
+
}
|
393
|
+
end
|
394
|
+
|
395
|
+
test_cases[uri.to_s] = tc
|
396
|
+
man_info['entries'] << tc
|
397
|
+
end
|
363
398
|
end
|
364
399
|
|
365
|
-
|
400
|
+
raise "No test cases found" if man_info['entries'].empty?
|
401
|
+
status "Test cases:\n #{man_info['entries'].map {|tc| tc['@id']}.join("\n ")}"
|
366
402
|
end
|
367
403
|
|
368
|
-
raise "No
|
404
|
+
raise "No manifests found" if manifests.empty?
|
405
|
+
status "Manifests:\n #{manifests.map {|m| m['@id']}.join("\n ")}"
|
369
406
|
|
370
|
-
status "Test cases:\n #{test_cases.keys.join("\n ")}"
|
371
407
|
# Iterate through assertions and add to appropriate test case
|
372
408
|
SPARQL.execute(ASSERTION_QUERY, @graph).each do |solution|
|
373
409
|
tc = test_cases[solution[:test].to_s]
|
@@ -380,7 +416,7 @@ class EarlReport
|
|
380
416
|
ta_hash['result']['outcome'] = "earl:#{solution[:outcome].to_s.split('#').last}"
|
381
417
|
end
|
382
418
|
|
383
|
-
|
419
|
+
manifests.sort_by {|m| m['title']}
|
384
420
|
end
|
385
421
|
|
386
422
|
##
|
@@ -407,18 +443,17 @@ class EarlReport
|
|
407
443
|
io.puts
|
408
444
|
|
409
445
|
# Write earl:Software for the report
|
446
|
+
man_defs = json_hash['entries'].map {|defn| as_resource(defn['@id'])}.join("\n ")
|
410
447
|
io.puts %{
|
411
448
|
#{as_resource(json_hash['@id'])} a #{[json_hash['@type']].flatten.join(', ')};
|
412
|
-
|
449
|
+
doap:name "#{json_hash['name']}";
|
413
450
|
dc:bibliographicCitation "#{json_hash['bibRef']}";
|
414
451
|
earl:generatedBy #{as_resource json_hash['generatedBy']['@id']};
|
415
452
|
earl:assertions
|
416
453
|
#{json_hash['assertions'].map {|a| as_resource(a)}.join(",\n ")};
|
417
454
|
earl:testSubjects (
|
418
455
|
#{json_hash['testSubjects'].map {|a| as_resource(a['@id'])}.join("\n ")});
|
419
|
-
|
420
|
-
#{json_hash['tests'].map {|a| as_resource(a['@id'])}.join("\n ")}) .
|
421
|
-
|
456
|
+
mf:entries (\n #{man_defs}) .
|
422
457
|
}.gsub(/^ /, '')
|
423
458
|
|
424
459
|
# Write generating software information
|
@@ -435,16 +470,34 @@ class EarlReport
|
|
435
470
|
|
436
471
|
}.gsub(/^ /, '')
|
437
472
|
|
473
|
+
# Output Manifest definitions
|
474
|
+
# along with test cases and assertions
|
475
|
+
test_cases = []
|
476
|
+
io.puts %(\n# Manifests)
|
477
|
+
json_hash['entries'].each do |man|
|
478
|
+
io.puts %(#{as_resource(man['@id'])} a earl:Report, mf:Manifest;)
|
479
|
+
io.puts %( dc:title "#{man['title']}";)
|
480
|
+
io.puts %( mf:name "#{man['title']}";)
|
481
|
+
|
482
|
+
# Test Cases
|
483
|
+
test_defs = man['entries'].map {|defn| as_resource(defn['@id'])}.join("\n ")
|
484
|
+
io.puts %( mf:entries (\n #{test_defs}) .\n\n)
|
485
|
+
|
486
|
+
test_cases += man['entries']
|
487
|
+
end
|
488
|
+
|
438
489
|
# Write out each earl:TestSubject
|
439
490
|
io.puts %(#\n# Subject Definitions\n#)
|
440
491
|
json_hash['testSubjects'].each do |ts_desc|
|
441
492
|
io.write(test_subject_turtle(ts_desc))
|
442
493
|
end
|
443
|
-
|
494
|
+
|
444
495
|
# Write out each earl:TestCase
|
445
496
|
io.puts %(#\n# Test Case Definitions\n#)
|
446
|
-
json_hash['
|
447
|
-
|
497
|
+
json_hash['entries'].each do |manifest|
|
498
|
+
manifest['entries'].each do |test_case|
|
499
|
+
io.write(tc_turtle(test_case))
|
500
|
+
end
|
448
501
|
end
|
449
502
|
end
|
450
503
|
|
@@ -5,7 +5,7 @@
|
|
5
5
|
-# "@context": {...},
|
6
6
|
-# "@id": "",
|
7
7
|
-# "@type": "earl:Software",
|
8
|
-
-# "
|
8
|
+
-# "name": "...",
|
9
9
|
-# "bibRef": "[[...]]",
|
10
10
|
-# "assertions": ["./rdf.rb-earl.ttl"],
|
11
11
|
-# "testSubjects": [
|
@@ -38,15 +38,15 @@
|
|
38
38
|
-# ]
|
39
39
|
-# }]
|
40
40
|
-# }
|
41
|
+
- require 'cgi'
|
41
42
|
|
42
43
|
!!! 5
|
43
44
|
%html{:prefix => "earl: http://www.w3.org/ns/earl# doap: http://usefulinc.com/ns/doap# mf: http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#"}
|
44
45
|
- subjects = tests['testSubjects']
|
45
|
-
- test_cases = tests['tests']
|
46
46
|
%head
|
47
47
|
%meta{"http-equiv" => "Content-Type", :content => "text/html;charset=utf-8"}
|
48
48
|
%title
|
49
|
-
= tests['
|
49
|
+
= tests['name']
|
50
50
|
%script.remove{:type => "text/javascript", :src => "http://www.w3.org/Tools/respec/respec-w3c-common"}
|
51
51
|
:javascript
|
52
52
|
var respecConfig = {
|
@@ -148,79 +148,139 @@
|
|
148
148
|
background-color: white;
|
149
149
|
-moz-border-radius: ;
|
150
150
|
}
|
151
|
-
|
152
|
-
|
151
|
+
tr.summary {font-weight: bold;}
|
152
|
+
td.passed-all {color: green;}
|
153
|
+
td.passed-most {color: darkorange;}
|
154
|
+
td.passed-some {color: red;}
|
155
|
+
%body{:prefix => "earl: http://www.w3.org/ns/earl# doap: http://usefulinc.com/ns/doap# mf: http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#"}
|
156
|
+
%section#abstract{:about => tests['@id'], :typeof => [tests['@type']].flatten.join(" ")}
|
153
157
|
%p
|
154
|
-
This document report
|
155
|
-
%span{:property => "
|
158
|
+
This document report test subject conformance for and related specifications for
|
159
|
+
%span{:property => "doap:name"}<=tests['name']
|
156
160
|
%span{:property => "dc:bibliographicCitation"}<
|
157
161
|
= tests['bibRef']
|
158
162
|
according to the requirements of the Evaluation and Report Language (EARL) 1.0 Schema [[EARL10-SCHEMA]].
|
163
|
+
%p
|
164
|
+
This report is also available in alternate formats:
|
165
|
+
%a{:href => "earl.ttl"}
|
166
|
+
Turtle
|
167
|
+
and
|
168
|
+
%a{:href => "earl.jsonld"}
|
169
|
+
JSON-LD
|
159
170
|
%section#sodt
|
160
171
|
%section
|
172
|
+
- test_info = {}
|
161
173
|
- test_refs = {}
|
162
174
|
- subject_refs = {}
|
163
175
|
%h2
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
176
|
+
Test Manifests
|
177
|
+
- tests['entries'].each do |manifest|
|
178
|
+
- test_cases = manifest['entries']
|
179
|
+
%section{:typeof => manifest['@type'].join(" "), :resource => manifest['@id']}
|
180
|
+
%h2<=manifest['title']
|
181
|
+
- [manifest['description']].flatten.compact.each do |desc|
|
182
|
+
%p<
|
183
|
+
~ CGI.escapeHTML desc
|
184
|
+
%table.report
|
185
|
+
- skip_subject = {}
|
186
|
+
- passed_tests = []
|
187
|
+
%tr
|
188
|
+
%th
|
189
|
+
Test
|
190
|
+
- subjects.each_with_index do |subject, index|
|
191
|
+
- subject_refs[subject['@id']] = "subj_#{index}"
|
192
|
+
-# If subject is untested for every test in this manifest, skip it
|
193
|
+
- skip_subject[subject['@id']] = manifest['entries'].all? {|t| t['assertions'][index]['result']['outcome'] == 'earl:untested'}
|
194
|
+
- unless skip_subject[subject['@id']]
|
195
|
+
%th
|
196
|
+
%a{:href => '#' + subject_refs[subject['@id']]}<=subject['name']
|
197
|
+
- test_cases.each do |test|
|
198
|
+
- tid = 'test_' + (test['@id'][0,2] == '_:' ? test['@id'][2..-1] : test['@id'].split('#').last)
|
199
|
+
- (test_info[tid] ||= []) << test
|
200
|
+
- test_refs[test['@id']] = tid
|
201
|
+
%tr{:rel => "mf:entries", :typeof => test['@type'].join(" "), :resource => test['@id'], :inlist => true}
|
202
|
+
%td
|
203
|
+
%a{:href => "##{tid}"}<
|
204
|
+
~ CGI.escapeHTML test['title']
|
205
|
+
- test['assertions'].each_with_index do |assertion, ndx|
|
206
|
+
- next if skip_subject[assertion['subject']]
|
207
|
+
- pass_fail = assertion['result']['outcome'].split(':').last.upcase.sub(/(PASS|FAIL)ED$/, '\1')
|
208
|
+
- passed_tests[ndx] = (passed_tests[ndx] || 0) + (pass_fail == 'PASS' ? 1 : 0)
|
209
|
+
%td{:class => pass_fail, :property => "earl:assertions", :typeof => assertion['@type'], :inlist => true}
|
210
|
+
- if assertion['assertedBy']
|
211
|
+
%link{:property => "earl:assertedBy", :href => assertion['assertedBy']}
|
212
|
+
%link{:property => "earl:test", :href => assertion['test']}
|
213
|
+
%link{:property => "earl:subject", :href => assertion['subject']}
|
214
|
+
- if assertion['mode']
|
215
|
+
%link{:property => 'earl:mode', :href => assertion['mode']}
|
216
|
+
%span{:property => "earl:result", :typeof => assertion['result']['@type']}
|
217
|
+
%span{:property => 'earl:outcome', :resource => assertion['result']['outcome']}
|
218
|
+
= pass_fail
|
219
|
+
%tr.summary
|
220
|
+
%td
|
221
|
+
= "Percentage passed out of #{manifest['entries'].length} Tests"
|
222
|
+
- passed_tests.compact.each do |r|
|
223
|
+
- pct = (r * 100.0) / manifest['entries'].length
|
224
|
+
%td{:class => (pct == 100.0 ? 'passed-all' : (pct >= 95.0 ? 'passed-most' : 'passed-some'))}
|
225
|
+
= "#{'%.1f' % pct}%"
|
190
226
|
%section.appendix
|
191
227
|
%h2
|
192
228
|
Test Subjects
|
193
229
|
%p
|
194
230
|
This report was tested using the following test subjects:
|
195
231
|
%dl
|
196
|
-
- subjects.
|
197
|
-
%dt{:id => subject_refs[subject['@id']]}
|
232
|
+
- subjects.each_with_index do |subject, index|
|
233
|
+
%dt{:id => subject_refs[subject['@id']]}
|
198
234
|
%a{:href => subject['@id']}
|
199
235
|
%span{:about => subject['@id'], :property => "doap:name"}<= subject['name']
|
200
236
|
%dd{:property => "earl:testSubjects", :resource => subject['@id'], :typeof => [subject['@type']].flatten.join(" "), :inlist => true}
|
201
237
|
%dl
|
202
238
|
- if subject['doapDesc']
|
203
239
|
%dt= "Description"
|
204
|
-
%dd{:property => "doap:description", :lang => 'en'}
|
240
|
+
%dd{:property => "doap:description", :lang => 'en'}<
|
241
|
+
~ CGI.escapeHTML subject['doapDesc']
|
205
242
|
- if subject['language']
|
206
243
|
%dt= "Programming Language"
|
207
|
-
%dd{:property => "doap:programming-language"}
|
244
|
+
%dd{:property => "doap:programming-language"}<
|
245
|
+
~ CGI.escapeHTML subject['language']
|
246
|
+
- if subject['homepage']
|
247
|
+
%dt= "Home Page"
|
248
|
+
%dd{:property => "doap:homepage"}
|
249
|
+
%a{:href=> subject['homepage']}
|
250
|
+
~ CGI.escapeHTML subject['homepage']
|
208
251
|
- if subject['developer']
|
209
252
|
%dt= "Developer"
|
210
253
|
%dd{:rel => "doap:developer"}
|
211
254
|
- subject['developer'].each do |dev|
|
212
|
-
%div{:resource => dev['@id'], :typeof => dev['@type']}
|
255
|
+
%div{:resource => dev['@id'], :typeof => [dev['@type']].flatten.join(" ")}
|
213
256
|
- if dev.has_key?('@id')
|
214
257
|
%a{:href => dev['@id']}
|
215
|
-
%span{:property => "foaf:name"}
|
258
|
+
%span{:property => "foaf:name"}<
|
259
|
+
~ CGI.escapeHTML dev['foaf:name']
|
216
260
|
- else
|
217
|
-
%span{:property => "foaf:name"}
|
261
|
+
%span{:property => "foaf:name"}<
|
262
|
+
~ CGI.escapeHTML dev['foaf:name']
|
218
263
|
- if dev['foaf:homepage']
|
219
264
|
%dt
|
220
265
|
Home Page
|
221
266
|
%dd
|
222
267
|
%a{:property => "foaf:homepage", :href=> dev['foaf:homepage']}
|
223
|
-
|
268
|
+
~ CGI.escapeHTML dev['foaf:homepage']
|
269
|
+
%dt
|
270
|
+
Test Suite Compliance
|
271
|
+
%dd
|
272
|
+
%table.report
|
273
|
+
%tbody
|
274
|
+
- tests['entries'].each do |manifest|
|
275
|
+
- passed = manifest['entries'].select {|t| t['assertions'][index]['result']['outcome'] == 'earl:passed' }.length
|
276
|
+
- next if passed == 0
|
277
|
+
- total = manifest['entries'].length
|
278
|
+
- pct = (passed * 100.0) / total
|
279
|
+
%tr
|
280
|
+
%td
|
281
|
+
~ manifest['title']
|
282
|
+
%td{:class => (pct == 100.0 ? 'passed-all' : (pct >= 85.0 ? 'passed-most' : 'passed-some'))}
|
283
|
+
= "#{passed}/#{total} (#{'%.1f' % pct}%)"
|
224
284
|
- unless tests['assertions'].empty?
|
225
285
|
%section.appendix{:rel => "earl:assertions"}
|
226
286
|
%h2
|
@@ -235,19 +295,21 @@
|
|
235
295
|
%h2
|
236
296
|
Test Definitions
|
237
297
|
%dl
|
238
|
-
- tests['
|
239
|
-
%
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
%
|
298
|
+
- tests['entries'].each do |manifest|
|
299
|
+
%div{:property => "mf:entries", :inlist => true, :resource => manifest['@id']}
|
300
|
+
- manifest['entries'].each do |test|
|
301
|
+
%dt{:id => test_refs[test['@id']], :resource => test['@id']}
|
302
|
+
Test
|
303
|
+
%span{:property => "dc:title mf:name"}<
|
304
|
+
~ CGI.escapeHTML test['title']
|
305
|
+
%dd{:resource => test['@id']}
|
306
|
+
%p{:property => "dc:description", :lang => 'en'}<
|
307
|
+
~ CGI.escapeHTML test['description']
|
246
308
|
%pre{:class => "example actionDoc", :property => "mf:action", :resource => test['testAction'], :title => "#{test['title']} Input"}<
|
247
|
-
~ Kernel.open(test['testAction']) {|f| CGI.escapeHTML(f.read).gsub(/\n/, '<br/>')} rescue "#{test['testAction']} not loaded"
|
309
|
+
~ CGI.escapeHTML Kernel.open(test['testAction']) {|f| CGI.escapeHTML(f.read).gsub(/\n/, '<br/>')} rescue "#{test['testAction']} not loaded"
|
248
310
|
- if test['testResult']
|
249
311
|
%pre{:class => "example resultDoc", :property => "mf:result", :resource => test['testResult'], :title => "#{test['title']} Result"}<
|
250
|
-
~ Kernel.open(test['testResult']) {|f| CGI.escapeHTML(f.read).gsub(/\n/, '<br/>')} rescue "#{test['testResult']} not loaded"
|
312
|
+
~ CGI.escapeHTML Kernel.open(test['testResult']) {|f| CGI.escapeHTML(f.read).gsub(/\n/, '<br/>')} rescue "#{test['testResult']} not loaded"
|
251
313
|
%section#appendix{:property => "earl:generatedBy", :resource => tests['generatedBy']['@id'], :typeof => tests['generatedBy']['@type']}
|
252
314
|
%h2
|
253
315
|
Report Generation Software
|