package com.capitalone.dashboard.collector;
import com.capitalone.dashboard.model.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* Transforms a Cucumber result JSON string into a TestResult
*/
@Component
public class CucumberJsonToTestResultTransformer implements Transformer<String, List<TestSuite>> {
private static final Log LOG = LogFactory.getLog(CucumberJsonToTestResultTransformer.class);
@Override
public List<TestSuite> transformer(String json) {
if (StringUtils.isEmpty(json)) {
throw new IllegalArgumentException("json must not be empty");
}
JSONParser parser = new JSONParser();
List<TestSuite> suites = new ArrayList<>();
try {
// Parse features
for (Object featureObj : (JSONArray) parser.parse(json)) {
JSONObject feature = (JSONObject) featureObj;
suites.add(parseFeatureAsTestSuite(feature));
}
} catch (ParseException e) {
LOG.error(e);
}
return suites;
}
private TestSuite parseFeatureAsTestSuite(JSONObject featureElement) {
TestSuite suite = new TestSuite();
suite.setType(TestSuiteType.Functional);
suite.setDescription(getString(featureElement, "name"));
long duration = 0;
int testCaseTotalCount = getJsonArray(featureElement, "elements").size();
int testCaseSkippedCount = 0, testCaseErrorCount = 0, testCaseFailCount = 0;
for (Object scenarioElement : getJsonArray(featureElement, "elements")) {
TestCase testCase = parseScenarioAsTestCase((JSONObject) scenarioElement);
duration += testCase.getDuration();
suite.getTestCases().add(testCase);
switch(testCase.getStatus()) {
case Error:
testCaseErrorCount++;
break;
case Failure:
testCaseFailCount++;
break;
case Skipped:
testCaseSkippedCount++;
break;
}
}
suite.setErrorCount(testCaseErrorCount);
suite.setFailureCount(testCaseFailCount);
suite.setSkippedCount(testCaseSkippedCount);
suite.setTotalCount(testCaseTotalCount);
suite.setDuration(duration);
return suite;
}
private TestCase parseScenarioAsTestCase(JSONObject scenarioElement) {
TestCase testCase = new TestCase();
testCase.setId(getString(scenarioElement, "name"));
testCase.setDescription(getString(scenarioElement, "name")); //TODO determine if change is necessary
// Parse each step as a TestCase
int testStepErrorCount = 0, testStepFailCount = 0, testStepSkippedCount = 0;
long testDuration = 0;
for (Object step : getJsonArray(scenarioElement, "steps")) {
TestCaseStatus stepStatus;
Object resultObj = ((JSONObject) step).get("result");
if (resultObj == null) {
stepStatus = TestCaseStatus.Unknown;
} else {
JSONObject result = (JSONObject) resultObj;
// Add the duration of this step to the overall duration of the test case
testDuration += getLong(result, "duration") / 1000l;
stepStatus = parseStatus(result);
}
// Count Statuses
switch(stepStatus) {
case Error:
testStepErrorCount++;
break;
case Failure:
testStepFailCount++;
break;
case Skipped:
testStepSkippedCount++;
break;
}
}
// Set Duration
testCase.setDuration(testDuration);
// Set Status
if(testStepErrorCount > 0) {
testCase.setStatus(TestCaseStatus.Error);
} else if(testStepFailCount > 0) {
testCase.setStatus(TestCaseStatus.Failure);
} else if(testStepSkippedCount > 0) {
testCase.setStatus(TestCaseStatus.Skipped);
} else {
testCase.setStatus(TestCaseStatus.Success);
}
return testCase;
}
private TestCaseStatus parseStatus(JSONObject result) {
String status = getString(result, "status");
return "passed".equalsIgnoreCase(status) ? TestCaseStatus.Success
: "failed".equalsIgnoreCase(status) ? TestCaseStatus.Failure
: TestCaseStatus.Unknown;
}
private JSONArray getJsonArray(JSONObject json, String key) {
Object array = json.get(key);
return array == null ? new JSONArray() : (JSONArray) array;
}
private String getString(JSONObject json, String key) {
return (String) json.get(key);
}
private long getLong(JSONObject json, String key) {
Object obj = json.get(key);
return obj == null ? 0 : (long) obj;
}
}