earl-report 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|