001package org.w3.ldp.testsuite.reporter; 002 003import java.io.IOException; 004import java.lang.reflect.Method; 005import java.util.ArrayList; 006import java.util.Arrays; 007import java.util.GregorianCalendar; 008import java.util.Iterator; 009import java.util.List; 010import java.util.Map; 011 012import org.testng.IReporter; 013import org.testng.IResultMap; 014import org.testng.ISuite; 015import org.testng.ISuiteResult; 016import org.testng.ITestContext; 017import org.testng.ITestNGMethod; 018import org.testng.ITestResult; 019import org.testng.annotations.Test; 020import org.testng.internal.Utils; 021import org.testng.xml.XmlSuite; 022import org.w3.ldp.testsuite.LdpTestSuite; 023import org.w3.ldp.testsuite.annotations.SpecTest; 024import org.w3.ldp.testsuite.annotations.SpecTest.METHOD; 025import org.w3.ldp.testsuite.vocab.Earl; 026import org.w3.ldp.testsuite.vocab.LDP; 027 028import com.hp.hpl.jena.rdf.model.Property; 029import com.hp.hpl.jena.rdf.model.Resource; 030import com.hp.hpl.jena.rdf.model.ResourceFactory; 031import com.hp.hpl.jena.sparql.vocabulary.DOAP; 032import com.hp.hpl.jena.sparql.vocabulary.FOAF; 033import com.hp.hpl.jena.vocabulary.DCTerms; 034import com.hp.hpl.jena.vocabulary.RDF; 035 036/** 037 * Earl Reporter for the LDP Test Suite. Takes in the results of the test suite 038 * and reports the information to a Turtle file and a JSON-LD file, both of 039 * which contains Earl vocabulary. 040 */ 041public class LdpEarlReporter extends AbstractEarlReporter implements IReporter { 042 043 private static final String PASS = "TEST PASSED"; 044 private static final String FAIL = "TEST FAILED"; 045 private static final String SKIP = "TEST SKIPPED"; 046 047 // private static final String DIRECT_TEST = "DirectContainerTest"; 048 // private static final String MEMBER_TEST = "MemberResourceTest"; 049 // private static final String BASIC_TEST = "BasicContainerTest"; 050 // private static final String INDIRECT_TEST = "IndirectContainerTest"; 051 // 052 // private static String direct; 053 // private static String member; 054 // private static String basic; 055 // private static String indirect; 056 057 private static String software; 058 private static String developer; 059 private static String homepage; 060 private static String assertor; 061 private static String language; 062 private static String mbox; 063 private static String description; 064 private static String shortname; 065 private static ArrayList<String> missingParms = new ArrayList<>(); 066 067 private static Property ranAsClass = ResourceFactory 068 .createProperty(LDP.LDPT_NAMESPACE + "ranAsClass"); 069 070 private static String TITLE = "ldp-testsuite"; 071 072 private IResultMap passedTests; 073 private IResultMap failedTests; 074 private IResultMap skippedTests; 075 076 private String outputDirectory = LdpTestSuite.OUTPUT_DIR; 077 078 public void setOutputDirectory(String outputDirectory) { 079 this.outputDirectory = outputDirectory; 080 } 081 082 @Override 083 public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) { 084 try { 085 createWriter(this.outputDirectory, ""); 086 } catch (IOException e) { 087 e.printStackTrace(System.err); 088 System.exit(1); 089 } 090 createModel(); 091 createAssertions(suites); 092 write(); 093 if (missingParms.size() > 0) { 094 System.out.print("EARL report missing values for parameters: "); 095 boolean first=true; 096 String o=""; 097 for (String p: missingParms) { 098 if (first) { 099 first = false; 100 o = p; 101 } else { 102 o = o + ", " + p; 103 } 104 } 105 System.out.println(o); 106 } 107 try { 108 endWriter(); 109 } catch (IOException e) { 110 e.printStackTrace(System.err); 111 System.exit(1); 112 } 113 } 114 115 private void createAssertions(List<ISuite> suites) { 116 for (ISuite suite : suites) { 117 // Acquire parameters 118 // direct = suite.getParameter("directContainer"); 119 // member = suite.getParameter("memberResource"); 120 // basic = suite.getParameter("basicContainer"); 121 // indirect = suite.getParameter("indirectContainer"); 122 123 homepage = suite.getParameter("homepage"); 124 if (homepage == null) missingParms.add("homepage"); 125 126 assertor = suite.getParameter("assertor"); 127 if (assertor == null) missingParms.add("assertor"); 128 129 software = suite.getParameter("software"); 130 if (software == null) missingParms.add("software"); 131 132 developer = suite.getParameter("developer"); 133 if (developer == null) missingParms.add("developer"); 134 135 language = suite.getParameter("language"); 136 if (language == null) missingParms.add("language"); 137 138 mbox = suite.getParameter("mail"); 139 if (mbox == null) missingParms.add("mail"); 140 141 description = suite.getParameter("description"); 142 if (description == null) missingParms.add("description"); 143 144 shortname = suite.getParameter("shortname"); 145 if (shortname == null) missingParms.add("shortname"); 146 147 // Make the Assertor Resource (the thing doing the testing) 148 Resource assertorRes = model.createResource(assertor); 149 assertorRes.addProperty(RDF.type, Earl.Assertor); 150 151 // Create the subject resource (the thing being tested) 152 Resource subjectResource = model.createResource(homepage, 153 Earl.TestSubject); 154 155 if (description != null) 156 subjectResource.addProperty(DOAP.description, description); 157 158 /* Developer Resource (Person) */ 159 Resource personResource = model.createResource(null, FOAF.Person); 160 if (mbox != null) 161 personResource.addProperty(FOAF.mbox, mbox); 162 if(developer != null) 163 personResource.addProperty(FOAF.name, developer); 164 165 subjectResource.addProperty(DOAP.developer, personResource); 166 167 /* Software Resource */ 168 Resource softResource = model 169 .createResource(homepage, Earl.Software); 170 if (software != null) 171 softResource.addProperty(DCTerms.title, software); 172 173 if(shortname != null) 174 softResource.addProperty(DOAP.name, shortname); 175 176 /* Add properties to the Test Subject Resource */ 177 subjectResource.addProperty(RDF.type, DOAP.Project); 178 179 if (homepage != null) 180 subjectResource.addProperty(DOAP.homepage, homepage); 181 182 if (language != null) 183 subjectResource 184 .addProperty(DOAP.programming_language, language); 185 186 Map<String, ISuiteResult> tests = suite.getResults(); 187 188 for (ISuiteResult results : tests.values()) { 189 ITestContext testContext = results.getTestContext(); 190 passedTests = testContext.getPassedTests(); 191 failedTests = testContext.getFailedTests(); 192 skippedTests = testContext.getSkippedTests(); 193 getResultProperties(failedTests, FAIL); 194 getResultProperties(skippedTests, SKIP); 195 getResultProperties(passedTests, PASS); 196 } 197 198 } 199 200 } 201 202 private void getResultProperties(IResultMap tests, String status) { 203 for (ITestResult result : tests.getAllResults()) { 204 makeResultResource(result, status); 205 } 206 } 207 208 private void makeResultResource(ITestResult result, String status) { 209 String className = result.getTestClass().getName(); 210 className = className.substring(className 211 .lastIndexOf(".") + 1); 212 213 Resource assertionResource = model.createResource(null, Earl.Assertion); 214 215 Resource resultResource = model.createResource(null, Earl.TestResult); 216 217 Resource subjectResource = model.getResource(homepage); 218 Resource assertorResource = model.getResource(assertor); 219 220 assertionResource.addProperty(Earl.testSubject, subjectResource); 221 222 assertionResource.addProperty( 223 Earl.test, 224 model.getResource(createTestCaseURL(className, result.getName()))); 225 226 /* Test Result Resource */ 227 Method method = result.getMethod().getConstructorOrMethod().getMethod(); 228 if(method.getAnnotation(SpecTest.class) != null){ 229 SpecTest specTest = method.getAnnotation(SpecTest.class); 230 if(specTest.coveredByGroups().length > 0 && specTest.coveredByGroups().length > 0){ 231 ArrayList<String> testResults = new ArrayList<String>(); 232 for(Class<?> classVal : specTest.coveredByTests()){ 233 Method[] classMethod = classVal.getDeclaredMethods(); 234 for(Method methodName : classMethod) { 235 if(methodName.getAnnotation(Test.class) != null) { 236 String group = Arrays.toString(methodName.getAnnotation(Test.class).groups()); 237 for(String groupCover : specTest.coveredByGroups()) { 238 if(group.contains(groupCover) && !methodName.getName().contains("Conforms")) { 239 testResults.add(findTestResult(methodName.getName())); 240 } 241 } 242 } 243 } 244 } 245 // evaluate the testResults for the Indirect Test 246 // if one of the tests fails, then the entire indirect test fails 247 // if there are only pass and skipped tests (none failed), then it passes 248 // if there are only skipped (none passed or failed), then it is skipped 249 if(testResults.size() > 0){ 250 if(testResults.contains(FAIL)) 251 status = FAIL; 252 else if(testResults.contains(PASS) && !testResults.contains(FAIL)) 253 status = PASS; 254 else if(testResults.contains(SKIP) && !testResults.contains(FAIL) && !testResults.contains(PASS)) 255 status = SKIP; 256 } 257 } 258 } 259 switch (status) { 260 case FAIL: 261 resultResource.addProperty(Earl.outcome, Earl.failed); 262 break; 263 case PASS: 264 resultResource.addProperty(Earl.outcome, Earl.passed); 265 break; 266 case SKIP: 267 resultResource.addProperty(Earl.outcome, Earl.untested); 268 break; 269 default: 270 break; 271 } 272 273 if (result.getThrowable() != null) { 274 createExceptionProperty(result.getThrowable(), resultResource); 275 } 276 277 if (result.getMethod().getConstructorOrMethod().getMethod() 278 .getAnnotation(SpecTest.class) != null) { 279 280 SpecTest test = result.getMethod().getConstructorOrMethod() 281 .getMethod().getAnnotation(SpecTest.class); 282 METHOD type = test.testMethod(); 283 284 switch (type) { 285 case AUTOMATED: 286 assertionResource.addProperty(Earl.mode, Earl.automatic); 287 break; 288 case MANUAL: 289 assertionResource.addProperty(Earl.mode, Earl.manual); 290 break; 291 case INDIRECT: 292 assertionResource.addProperty(Earl.mode, Earl.automatic); 293 break; 294 default: 295 assertionResource.addProperty(Earl.mode, Earl.notTested); 296 break; 297 } 298 } 299 300 assertionResource.addProperty(Earl.assertedBy, assertorResource); 301 assertionResource.addLiteral(ranAsClass, result.getTestClass().getRealClass().getSimpleName()); 302 303 resultResource.addProperty(DCTerms.date, model.createTypedLiteral(GregorianCalendar.getInstance())); 304 305 /* 306 * Add the above resources to the Assertion Resource 307 */ 308 assertionResource.addProperty(Earl.testResult, resultResource); 309 310 } 311 312 private void createExceptionProperty(Throwable thrown, Resource resource) { 313 if (thrown.getClass().getName().contains(SKIP)) 314 resource.addProperty(DCTerms.description, thrown.getMessage()); 315 else 316 resource.addLiteral(DCTerms.description, 317 Utils.stackTrace(thrown, false)[0]); 318 } 319 320 private String findTestResult(String methodName) { 321 Iterator<ITestNGMethod> passed = passedTests.getAllMethods().iterator(); 322 while(passed.hasNext()){ 323 ITestNGMethod method = passed.next(); 324 if(method.getMethodName().equals(methodName)){ 325 return PASS; 326 } 327 } 328 329 Iterator<ITestNGMethod> skipped = skippedTests.getAllMethods().iterator(); 330 while(skipped.hasNext()){ 331 ITestNGMethod method = skipped.next(); 332 if(method.getMethodName().equals(methodName)){ 333 return SKIP; 334 } 335 } 336 337 Iterator<ITestNGMethod> failed = failedTests.getAllMethods().iterator(); 338 while(failed.hasNext()){ 339 ITestNGMethod method = failed.next(); 340 if(method.getMethodName().equals(methodName)){ 341 return FAIL; 342 } 343 } 344 345 return null; 346 } 347 348 @Override 349 protected String getFilename() { 350 return TITLE + "-execution-report-earl"; 351 } 352 353 public void setTitle(String title){ 354 TITLE = title; 355 } 356}