-# This template is used for generating a rollup EARL report. It expects to be -# called with a single tests local with the following structure -# -# { -# “@context”: {…}, -# “@id”: “”, -# “@type”: “earl:Software”, -# “name”: “…”, -# “bibRef”: “[[…]]”, -# “assertions”: [“./rdf.rb-earl.ttl”], -# “testSubjects”: [ -# { -# “@id”: “rubygems.org/gems/rdf-turtle”, -# “@type”: “earl:TestSubject”, -# “name”: “RDF::Turtle” -# }, -# … -# ], -# “tests”: [{ -# “@id”: “dvcs.w3.org/hg/rdf/raw-file/default/rdf-turtle/tests-ttl/manifest.ttl#turtle-syntax-file-01”, -# “@type”: [“earl:TestCriterion”, “earl:TestCase”], -# “title”: “subm-test-00”, -# “description”: “Blank subject”, -# “testAction”: “dvcs.w3.org/hg/rdf/raw-file/default/rdf-turtle/tests-ttl/turtle-syntax-file-01.ttl”, -# “testResult”: “dvcs.w3.org/hg/rdf/raw-file/default/rdf-turtle/tests-ttl/turtle-syntax-file-01.out” -# “mode”: “earl:automatic”, -# “assertions”: [ -# { -# “@type”: “earl:Assertion”, -# “assertedBy”: “greggkellogg.net/foaf#me”, -# “test”: “svn.apache.org/repos/asf/jena/Experimental/riot-reader/testing/RIOT/Lang/TurtleSubm/manifest.ttl#testeval00”, -# “subject”: “rubygems.org/gems/rdf-turtle”, -# “result”: { -# “@type”: “earl:TestResult”, -# “outcome”: “earl:passed” -# } -# } -# ] -# }] -# }
-
require 'cgi'
-
require 'digest'
-
editors = [{ name: “Gregg Kellogg”, url: “greggkellogg.net/”}]
-
foaf = {name: “Gregg Kellogg”, url: “greggkellogg.net/foaf#me” }
!!! 5 %html
- subjects = tests['testSubjects'].sort_by {|s| s['name'].to_s.downcase} %head %meta{"http-equiv" => "Content-Type", content: "text/html;charset=utf-8"} %link{rel: "alternate", href: "earl.ttl"} %link{rel: "alternate", href: "earl.jsonld"} %link{rel: "stylesheet", href: "https://www.w3.org/StyleSheets/TR/base"} - tests['assertions'].each do |file| %link{rel: "related", href: file} %title = tests['name'] Implementation Report :css span[property='dc:description rdfs:comment'] { display: none; } td.PASS { color: green; } td.FAIL { color: red; } table.report { border-width: 1px; border-spacing: 2px; border-style: outset; border-color: gray; border-collapse: separate; background-color: white; } table.report th { border-width: 1px; padding: 1px; border-style: inset; border-color: gray; background-color: white; -moz-border-radius: ; } table.report td { border-width: 1px; padding: 1px; border-style: inset; border-color: gray; background-color: white; -moz-border-radius: ; } tr.summary {font-weight: bold;} td.passed-all {color: green;} td.passed-most {color: darkorange;} td.passed-some {color: red;} em.rfc2119 { text-transform: lowercase; font-variant: small-caps; font-style: normal; color: #900; } a.testlink { color: inherit; text-decoration: none; } a.testlink:hover { text-decoration: underline; } pre > code { color: #C83500; } %body{prefix: "bibo: http://purl.org/ontology/bibo/ earl: http://www.w3.org/ns/earl# doap: http://usefulinc.com/ns/doap# mf: http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#", vocab: "http://www.w3.org/ns/earl#"} - test_info = {} - test_refs = {} - subject_refs = {} - passed_tests = [] - tests['entries'].each {|m| m['title'] ||= m['rdfs:label'] || m['description'] || m['rdfs:comment']} - subjects.each_with_index do |subject, index| - subject_refs[subject['@id']] = "subj_#{index}" %div.head{role: :contentinfo} %p %a{href: "http://www.w3.org/"} %img{width: 72, height: 48, src: "https://www.w3.org/Icons/w3c_home", alt: "W3C"} %h1.title.p-name#title{property: "dc:title"}=tests['name'] %h2#w3c-document-28-october-2015 %abbr{title: "World Wide Web Consortium"}="W3C" Document %time.dt-published{property: "dc:issued", datetime: Time.now.strftime('%Y-%m-%d')} = Time.now.strftime("%d %B %Y") %dl %dt="Editor:" - editors.each do |ed| %dd.p-author.h-card.vcard{property: "bibo:editor", inlist: true}<> %span{property: "rdf:first", typeof: "foaf:Person"}<> %meta{property: "foaf:name", content: ed[:name]}<> %a.url.fn.u-url.p-name{property: "foaf:homepage", href: ed[:url]}<> = ed[:name] %p This document is also available in these non-normative formats: %a{re: "alternate", href: "earl.ttl"} and %a{re: "alternate", href: "earl.jsonld"} = "." %p.copyright %a{href: "http://www.w3.org/Consortium/Legal/ipr-notice#Copyright"} Copyright © 2010-2015 %a{href: "http://www.w3.org/"} %sup="®" ( %a{href: "http://www.csail.mit.edu/"}<> %abbr{title: "Massachusetts Institute of Technology"}<>="MIT" = ", " %a{href: "http://www.ercim.eu/"}<> %abbr{title: "European Research Consortium for Informatics and Mathematics"}<>="ERCIM" = ", " %a{href: "http://www.keio.ac.jp/"}<>="Keio" = ", " %a{href: "http://ev.buaa.edu.cn/"}<>="Beihang" ). %abbr{title: "World Wide Web Consortium"}="W3C" %a{href: "http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer"}="liability" = "," %a{href: "http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks"}="trademark" and %a{rel: "license", href: "http://www.w3.org/Consortium/Legal/copyright-documents"}="document use" rules apply. %hr %section#abstract{about: tests['@id'], typeof: Array(tests['@type']).join(" ")} %h2="Abstract" %p This document report test subject conformance for and related specifications for %span{property: "doap:name"}<=tests['name'] %span{property: "dc:bibliographicCitation"}< = tests['bibRef'] according to the requirements of the Evaluation and Report Language (EARL) 1.0 Schema [[EARL10-SCHEMA]]. %p This report is also available in alternate formats: %a{rel: "xhv:alternate", href: "earl.ttl"} Turtle and %a{rel: "xhv:alternate", href: "earl.jsonld"} JSON-LD %section#sodt %h2#h-sotd{resource: "#h-sotd"} %span{property: "xhv:role", resource: "xhv:heading"} Status of This Document %p This document is merely a %abbr{title: "World Wide Web Consortium"}<>="W3C" ="-internal document." It has no official standing of any kind and does not represent consensus of the %abbr{title: "World Wide Web Consortium"}="W3C" Membership. %p This report describes the state of implementation conformance at the time of publication. %section#toc %h2.introductory#h-toc{resource: "#h-toc"} %span{property: "xhv:role", resource: "xhv:heading"} Table of Contents %ul.toc#respecContents{role: "directory"} %li.tocline %a.tocxref{href: "#instructions-for-submitting-implementation-reports"} %span.secno="1." Instructions for submitting implementation reports %li.tocline %a.tocxref{href: "#test-manifests"} %span.secno="2." Test Manifests %ul.toc - tests['entries'].sort_by {|m| m['title'].to_s.downcase}.each_with_index do |manifest, ndx| %li.tocline %span.secno="2.#{ndx+1}" %a.tocxref{href: "##{manifest['rdfs:comment'].gsub(' ', '-')}"} ~ manifest['rdfs:comment'] %li.tocline %a.tocxref{href: "#test-subjects"} %span.secno="A." Test Subjects %ul.toc - subjects.each_with_index do |subject, ndx| %li.tocline %span.secno="A.#{ndx+1}" %a.tocxref{href: "#" + subject_refs[subject['@id']]}= subject['name'] %li.tocline %a.tocxref{href: "#individual-test-results"} %span.secno="B." Individual Test Results %li.tocline %a.tocxref{href: "#test-definitions"} %span.secno="C." Test Definitions %li.tocline %a.tocxref{href: "#report-generation-software"} %span.secno="D." Report Generation Software %section#instructions-for-submitting-implementation-reports :markdown ## Instructions for submitting implementation reports Tests should be run using the test manifests defined in the [Test Manifests](#test-manifests) Section. The assumed base URI for the tests is `<http://example/base/>` if needed. Reports should be submitted in Turtle format to [xxx](xxx) and include an `earl:Assertion` for each test, referencing the test resource from the associated manifest and the test subject being reported upon. An example test entry is be the following: [ a earl:Assertion; earl:assertedBy <#{foaf[:url]}>; earl:subject <--your-software-identifier-->; earl:test <--uri-of-test-from-manifest>; earl:result [ a earl:TestResult; earl:outcome earl:passed; dc:date "2016-12-26T10:18:04-08:00"^^xsd:dateTime]; earl:mode earl:automatic ] . The Test Subject should be defined as a `doap:Project`, including the name, homepage and developer(s) of the software (see [DOAP](https://github.com/edumbill/doap/wiki)). Optionally, including the project description and programming language. An example test subject description is the following: <> foaf:primaryTopic <--your-software-identifier--> ; dc:issued "2016-12-26T10:18:04-08:00"^^xsd:dateTime ; foaf:maker <#{foaf[:url]}> . <--your-software-identifier--> a doap:Project, earl:TestSubject, earl:Software ; doap:name "#{foaf[:name]}" ; doap:homepage <--your-software-homepace--> ; doap:license <--license-for-your-software--> ; doap:shortdesc "--your-short-project-description--"@en ; doap:description "--your-project-description--"@en ; doap:created "2016-12-09"^^xsd:date ; doap:programming-language "--your-implementation-language--" ; doap:implements <--specification-uri--> ; doap:category <--category-uris-for-specification-framework-and-implementation-language--> ; doap:download-page <--your-project-repository--> ; doap:mailing-list <--specification-public-mailing-list--@w3.org> ; doap:bug-database <--your-project-repository--/issues> ; doap:blog <--your-blog--> ; doap:developer <#{foaf[:url]}> ; foaf:maker <#{foaf[:url]}> ; dc:title "--your-project-name--" ; dc:description "--your-project-description--"@en ; dc:date "2016-12-09"^^xsd:date ; dc:creator <#{foaf[:url]}> ; dc:isPartOf <--your-implementation-framework--> . The software developer, either an organization or one or more individuals SHOULD be referenced from `doap:developer` using [FOAF](http://xmlns.com/foaf/spec). For example: <--your-software-identifier--> a foaf:Person, earl:Assertor; foaf:name "#{foaf[:name]}"; foaf:title "Implementor"; foaf:homepage <#{foaf[:url]}> . %section#test-manifests %h2 %span.secno="2." Test Manifests - tests['entries'].each_with_index do |manifest, ndx2| - test_cases = manifest['entries'] %section{id: manifest['rdfs:comment'].gsub(' ', '-'), typeof: manifest['@type'].join(" "), resource: manifest['@id']} %h2 %span.secno="2.#{ndx2+1}" %span{property: "dc:title mf:name"}< = manifest['title'] || 'Test Manifest' - Array(manifest['description']).each do |desc| - desc = desc['@value'] if desc.is_a?(Hash) %p{property: "rdfs:comment", lang: 'en'}< ~ CGI.escapeHTML desc.to_s %table.report - skip_subject = {} - passed_tests[ndx2] = [] %tr %th Test - subjects.each_with_index do |subject, index| -# If subject is untested for every test in this manifest, skip it - skip_subject[subject['@id']] = manifest['entries'].all? {|t| t['assertions'][index]['result']['outcome'] == 'earl:untested'} - unless skip_subject[subject['@id']] %th %a{href: '#' + subject_refs[subject['@id']]}<=subject['name'] - test_cases.each do |test| - test['title'] ||= test['rdfs:label'] - test['title'] = Array(test['title']).first - tid = "test_#{Digest::MD5.hexdigest(test['@id'])}" - (test_info[tid] ||= []) << test - test_refs[test['@id']] = tid %tr{rel: "mf:entries", typeof: test['@type'].join(" "), resource: test['@id'], inlist: true} %td %a{href: "##{tid}"}< ~ CGI.escapeHTML test['title'].to_s -# Order assertions by subject name - subjects.each_with_index do |subject, ndx| - next if skip_subject[subject['@id']] - assertion = test['assertions'].detect {|a| a['subject'] == subject['@id']} - pass_fail = assertion['result']['outcome'].split(':').last.upcase.sub(/(PASS|FAIL)ED$/, '\1') - passed_tests[ndx2][ndx] = (passed_tests[ndx2][ndx] || 0) + (pass_fail == 'PASS' ? 1 : 0) %td{class: pass_fail, typeof: assertion['@type']} - if assertion['assertedBy'] && !assertion['assertedBy'].start_with?('_:') %link{property: "earl:assertedBy", href: assertion['assertedBy']} - if assertion['test'] && !assertion['test'].start_with?('_:') %link{property: "earl:test", href: assertion['test']} - if assertion['subject'] && !assertion['subject'].start_with?('_:') %link{property: "earl:subject", href: assertion['subject']} - if assertion['mode'] %link{property: 'earl:mode', href: assertion['mode']} %span{property: "earl:result", typeof: assertion['result']['@type']} %span{property: 'earl:outcome', resource: assertion['result']['outcome']} = pass_fail %tr.summary %td = "Percentage passed out of #{manifest['entries'].length} Tests" - passed_tests[ndx2].compact.each do |r| - pct = (r * 100.0) / manifest['entries'].length %td{class: (pct == 100.0 ? 'passed-all' : (pct >= 95.0 ? 'passed-most' : 'passed-some'))} = "#{'%.1f' % pct}%" %section.appendix#test-subjects %h2 %span.secno="A." Test Subjects %p This report was tested using the following test subjects: %dl - subjects.each_with_index do |subject, index| %dt{id: subject_refs[subject['@id']]} %span.secno="A.#{index+1}" %a{href: subject['@id']} %span{about: subject['@id'], property: "doap:name"}<= subject['name'] %dd{property: "earl:testSubjects", resource: subject['@id'], typeof: Array(subject['@type']).join(" ")} %dl - if subject['doapDesc'] - subject['doapDesc'] = subject['doapDesc']['@value'] if subject['doapDesc'].is_a?(Hash) %dt= "Description" %dd{property: "doap:description", lang: 'en'}< ~ CGI.escapeHTML subject['doapDesc'] - if subject['release'] - subject['release'] = subject['release'].first if subject['release'].is_a?(Array) - subject['release']['revision'] = subject['release']['revision']['@value'] if subject['release']['revision'].is_a?(Hash) %dt= "Release" %dd{property: "doap:release"}< %span{property: "doap:revision"}< ~ CGI.escapeHTML subject['release']['revision'].to_s - if subject['language'] - subject['language'] = subject['language']['@value'] if subject['language'].is_a?(Hash) %dt= "Programming Language" %dd{property: "doap:programming-language"}< ~ CGI.escapeHTML subject['language'].to_s - if subject['homepage'] %dt= "Home Page" %dd %a{property: "doap:homepage", href: subject['homepage']} ~ CGI.escapeHTML subject['homepage'].to_s - if subject['developer'] %dt= "Developer" - subject['developer'].each do |dev| %dd{rel: "doap:developer"} %div{resource: dev['@id'], typeof: Array(dev['@type']).join(" ")} - if dev.has_key?('@id') %a{href: dev['@id']} %span{property: "foaf:name"}< ~ CGI.escapeHTML dev['foaf:name'].to_s - else %span{property: "foaf:name"}< - if dev['foaf:homepage'] %a{property: "foaf:homepage", href: dev['foaf:homepage']} ~ CGI.escapeHTML dev['foaf:homepage'] %dt Test Suite Compliance %dd %table.report %tbody - tests['entries'].each_with_index do |manifest, ndx| - passed = passed_tests[ndx][index].to_i - next if passed == 0 - total = manifest['entries'].length - pct = (passed * 100.0) / total %tr %td ~ manifest['title'] %td{class: (pct == 100.0 ? 'passed-all' : (pct >= 85.0 ? 'passed-most' : 'passed-some'))} = "#{passed}/#{total} (#{'%.1f' % pct}%)" - unless tests['assertions'].empty? %section.appendix#individual-test-results{rel: "xhv:related mf:report"} %h2 %span.secno="B." Individual Test Results %p Individual test results used to construct this report are available here: %ul - tests['assertions'].each do |file| %li %a.source{href: file}<= file %section.appendix#test-definitions %h2 %span.secno="C." Test Definitions %dl - tests['entries'].each do |manifest| %div{property: "mf:entries", inlist: true, resource: manifest['@id']} - manifest['entries'].each do |test| - test['description'] = test['description']['@value'] if test['description'].is_a?(Hash) %dt{id: test_refs[test['@id']], resource: test['@id']} Test %span{property: "dc:title mf:name"}< ~ CGI.escapeHTML test['title'].to_s %dd{resource: test['@id']} %p{property: "dc:description rdfs:comment"}< ~ CGI.escapeHTML test['description'].to_s %pre{class: "example actionDoc", property: "mf:action", resource: test['testAction'], title: "#{test['title']} Input"}< ~ URI.open(test['testAction']) {|f| f.set_encoding(Encoding::UTF_8); CGI.escapeHTML(f.read).gsub(/\n/, '<br/>')} rescue "#{test['testAction']} not loaded" - if test['testResult'] %pre{class: "example resultDoc", property: "mf:result", resource: test['testResult'], title: "#{test['title']} Result"}< ~ URI.open(test['testResult']) {|f| f.set_encoding(Encoding::UTF_8); CGI.escapeHTML(f.read).gsub(/\n/, '<br/>')} rescue "#{test['testResult']} not loaded" %section.appendix#report-generation-software{property: "earl:generatedBy", resource: tests['generatedBy']['@id'], typeof: tests['generatedBy']['@type'].join(' ')} %h2 %span.secno="D." Report Generation Software - doap = tests['generatedBy'] - rel = doap['release'] %p This report generated by %span{property: "doap:name"}< %a{href: tests['generatedBy']['@id']}< = doap['name'] %meta{property: "doap:shortdesc", content: doap['shortdesc']} %meta{property: "doap:description", content: doap['doapDesc']} version %span{property: "doap:release", resource: rel['@id'], typeof: 'doap:Version'} %span{property: "doap:revision"}<=rel['revision'] %meta{property: "doap:name", content: rel['name']} - if rel['created'] %meta{property: "doap:created", content: rel['created'], datatype: "xsd:date"} an %a{property: "doap:license", href: doap['license']}<="Unlicensed" %span{property: "doap:programming-language"}<="Ruby" application. More information is available at %a{property: "doap:homepage", href: doap['homepage']}<=doap['homepage'] = "." %p{property: "doap:developer", resource: "https://greggkellogg.net/foaf#me", typeof: "foaf:Person"} This software is provided by %a{property: "foaf:homepage", href: "https://greggkellogg.net/"}< %span{about: "https://greggkellogg.net/foaf#me", property: "foaf:name"}< Gregg Kellogg in hopes that it might make the lives of conformance testers easier.