package jhydra.core.testcase; import jhydra.core.exceptions.RecoverableException; import jhydra.core.lexicon.ILexicon; import jhydra.core.lexicon.exceptions.NameNotInLexiconException; import jhydra.core.logging.ILog; import jhydra.core.properties.INameValue; import jhydra.core.properties.NameValue; import jhydra.core.properties.exceptions.NameNotValidException; import jhydra.core.scripting.IScript; import jhydra.core.scripting.IScriptFactory; import jhydra.core.scripting.exceptions.CompileErrorException; import jhydra.core.scripting.exceptions.ScriptFatalException; import jhydra.core.testcase.result.FatalExitTestCaseResult; import jhydra.core.testcase.result.ITestCaseResult; import jhydra.core.testcase.result.NonFatalExitTestCaseResult; import jhydra.core.testcase.result.NormalTestCaseResult; import jhydra.core.uinav.IMasterNavigator; import jhydra.core.valuemap.IValueMap; import jhydra.core.valuemap.ValueMap; import org.joda.time.DateTime; import java.util.ArrayList; import java.util.List; /** * Author: jantic * Date: 3/3/13 */ public class TestCase implements ITestCase{ private final ITestInfo testInfo; private final IScriptFactory scriptFactory; private final String entryScriptName; private final ILexicon lexicon; private final IMasterNavigator masterNavigator; private final ITestDataAnalyzer testDataAnalyzer; private final ILog log; public TestCase(ITestInfo testInfo, IScriptFactory scriptFactory, String entryScriptName, ILexicon lexicon, IMasterNavigator masterNavigator, ITestDataAnalyzer testDataAnalyzer, ILog log){ this.testInfo = testInfo; this.scriptFactory = scriptFactory; this.entryScriptName = entryScriptName; this.lexicon = lexicon; this.masterNavigator = masterNavigator; this.testDataAnalyzer = testDataAnalyzer; this.log = log; } //Summary: We want the test cases to be completely contained and "sand boxed" so that error conditions from the //scripts contained within can't escape these confines. Hence the error handling logic below, and the use of //the ITestCaseResult type. @Override public ITestCaseResult execute(){ final DateTime runStartTime = DateTime.now(); try{ final IValueMap valueMap = this.getInitializedValueMap(); final IScript entryScript = getEntryScript(valueMap); entryScript.execute(); final List<INameValue> actualValues = extractActualValues(valueMap); final DateTime runCompleteTime = DateTime.now(); return new NormalTestCaseResult(this.testDataAnalyzer,actualValues, runStartTime, runCompleteTime); } catch(RecoverableException e){ log.error("Test case " + this.getName() + ", number " + this.getTestNumber().toString() + " ran into a" + " potentially recoverable error: " + e.getMessage()); final DateTime runCompleted = DateTime.now(); return new NonFatalExitTestCaseResult(runStartTime, runCompleted, generateErrorList(e.getMessage())); } catch(Throwable e){ log.error("Test case " + this.getName() + ", number " + this.getTestNumber().toString() + " ran into a" + " fatal error, and therefore will be aborted: " + e.getMessage()); final DateTime runCompleted = DateTime.now(); return new FatalExitTestCaseResult(runStartTime, runCompleted, generateErrorList(e.getMessage())); } } private List<String> generateErrorList(String errorMessage){ final List<String> errorMessages = new ArrayList<>(); errorMessages.add(errorMessage); return errorMessages; } @Override public String getName() { return testInfo.getName(); } @Override public String getDescription() { return testInfo.getDescription(); } @Override public Integer getTestNumber() { return testInfo.getTestNumber(); } private List<INameValue> extractActualValues(IValueMap valueMap) throws NameNotInLexiconException, NameNotValidException { final List<INameValue> expectedValues = testDataAnalyzer.getAllExpectedValues(); final List<INameValue> actualValues = new ArrayList<>(); for(INameValue expectedPair : expectedValues){ final String actualValue = valueMap.getValue(expectedPair.getName()); final INameValue actualPair = NameValue.getInstance(expectedPair.getName(), actualValue); actualValues.add(actualPair); } return actualValues; } private IValueMap getInitializedValueMap() throws NameNotInLexiconException, NameNotValidException { final IValueMap valueMap = new ValueMap(this.lexicon); valueMap.updateValues(testDataAnalyzer.getAllTestInputs()); return valueMap; } private IScript getEntryScript(IValueMap valueMap) throws ScriptFatalException, CompileErrorException { return scriptFactory.getScript(this.entryScriptName, valueMap, this.masterNavigator); } }