/*******************************************************************************
* ATE, Automation Test Engine
*
* Copyright 2014, Montreal PROT, or individual contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Montreal PROT.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.bigtester.ate.model.caserunner; //NOPMD
import java.io.FileNotFoundException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlRootElement;
import org.bigtester.ate.GlobalUtils;
import org.bigtester.ate.constant.LogbackTag;
import org.bigtester.ate.model.casestep.ITestCase;
import org.bigtester.ate.model.data.TestParameters;
import org.bigtester.ate.model.data.exception.TestDataException;
import org.bigtester.ate.model.page.atewebdriver.IMyWebDriver;
import org.bigtester.ate.model.project.IRunTestCase;
import org.bigtester.ate.model.project.TestProjectListener;
import org.bigtester.ate.systemlogger.LogbackWriter;
import org.eclipse.jdt.annotation.Nullable;
import org.openqa.selenium.NoSuchWindowException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.UnreachableBrowserException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.Resource;
import org.testng.ITestContext;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.TestRunner;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;//NOPMD, can't be deleted since this file will be used as a template to create runners
import org.testng.internal.Utils;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
// TODO: Auto-generated Javadoc
/**
* The Class CaseRunner runs a single test case
*
* @author Peidong Hu
*/
@XmlRootElement
public class CaseRunner implements IRunTestCase {
/** The context. */
@Nullable
@XStreamOmitField
private ApplicationContext context;
/** The main driver. */
@Nullable
private WebDriver mainDriver;
/** The my tc. */
@Nullable
private ITestCase myTestCase;
/** The current executing tc name. */
@Nullable
protected String currentExecutingTCName; // must not be null
/** The page object data files. */
private List<Resource> pageObjectDataFiles = new ArrayList<Resource>();
/**
* @return the pageObjectDataFiles
*/
public List<Resource> getPageObjectDataFiles() {
return pageObjectDataFiles;
}
/**
* @param pageObjectDataFiles
* the pageObjectDataFiles to set
*/
public void setPageObjectDataFiles(List<Resource> pageObjectDataFiles) {
this.pageObjectDataFiles = pageObjectDataFiles;
}
/**
* @return the currentExecutingTCName
*/
public String getCurrentExecutingTCName() {
final String currentExecutingTCName2 = currentExecutingTCName;
if (null == currentExecutingTCName2 ) {
throw GlobalUtils.createNotInitializedException("current tc name");
} else {
return currentExecutingTCName2;
}
}
/**
* @param currentExecutingTCName
* the currentExecutingTCName to set
*/
public void setCurrentExecutingTCName(String currentExecutingTCName) {
this.currentExecutingTCName = currentExecutingTCName;
}
/**
* @return the myTestCase
*/
public ITestCase getMyTestCase() {
final ITestCase retVal = myTestCase;
if (null == retVal) {
throw new IllegalStateException(
"myTestCase is not correctly populated");
} else {
return retVal;
}
}
/**
* @param myTestCase
* the myTestCase to set
*/
public void setMyTestCase(final ITestCase myTestCase) {
this.myTestCase = myTestCase;
}
/**
* Gets the test data.
*
* @param ctx
* the ctx
* @return the test data
*/
@DataProvider(name = "dp")
public Object[][] getTestData(ITestContext ctx) {
if (null == currentExecutingTCName) {
throw new IllegalStateException(
"xml test case name is not correctly populated.");
} else {
TestParameters params = new TestParameters(getCurrentExecutingTCName(),
getCurrentExecutingTCName());
for (int index = 0; index < ((TestRunner) ctx).getTestListeners()
.size(); index++) {
if (((TestRunner) ctx).getTestListeners().get(index) instanceof TestProjectListener) {
int thinkT = ((TestProjectListener) ((TestRunner) ctx)
.getTestListeners().get(index)).getMytp()
.getStepThinkTime();
params.setStepThinkTime(thinkT);
params.setGlobalAppCtx(((TestProjectListener) ((TestRunner) ctx)
.getTestListeners().get(index)).getMytp()
.getAppCtx());
params.setTestProject(((TestProjectListener) ((TestRunner) ctx)
.getTestListeners().get(index)).getMytp());
break;
}
}
return new Object[][] { { params } };
}
}
/**
* Test data.
*
* @param method
* the method
* @param testData
* the test data
*/
@BeforeMethod(alwaysRun = true)
public void testData(Method method, Object[] testData) { // NOPMD
String testCase;
if (testData != null && testData.length > 0) {
TestParameters testParams;
// Check if test method has actually received required parameters
for (Object testParameter : testData) {
if (testParameter instanceof TestParameters) {
testParams = (TestParameters) testParameter;
testCase = testParams.getTestName();
this.currentExecutingTCName = String.format("%s", testCase);
break;
}
}
}
}
/**
* {@inheritDoc}
*/
@Override
@Nullable
public String getTestName() {
return this.getCurrentExecutingTCName();
}
/**
* Test runner1.
*
* @param ctx
* the ctx
* @throws Throwable
*/
// @Test(dataProvider = "dp")
public void runTest(TestParameters testParams) throws Throwable {
String testname = testParams.getTestFilename();
// ApplicationContext context;
try {
context = new FileSystemXmlApplicationContext(testname);
IMyWebDriver myWebD = (IMyWebDriver) GlobalUtils
.findMyWebDriver(context);
mainDriver = myWebD.getWebDriverInstance();
myTestCase = GlobalUtils.findTestCaseBean(getContext());
getMyTestCase().setStepThinkTime(testParams.getStepThinkTime());
getMyTestCase().setCurrentWebDriver(myWebD);
getMyTestCase().setParentTestProject(testParams.getTestProject());
getMyTestCase().goSteps();
} catch (FatalBeanException fbe) {
if (fbe.getCause() instanceof FileNotFoundException) {
context = new ClassPathXmlApplicationContext(testname);
mainDriver = ((IMyWebDriver) GlobalUtils
.findMyWebDriver(context)).getWebDriverInstance();
myTestCase = GlobalUtils.findTestCaseBean(getContext());
myTestCase.setStepThinkTime(testParams.getStepThinkTime());
getMyTestCase().goSteps();
} else if (fbe instanceof BeanCreationException) { // NOPMD
ITestResult itr = Reporter.getCurrentTestResult();
if (itr.getThrowable() != null
&& itr.getThrowable() instanceof TestDataException) {
TestDataException tde = (TestDataException) itr
.getThrowable();
tde.setTestStepName(((BeanCreationException) fbe.getCause())
.getBeanName());
tde.setTestCaseName(((BeanCreationException) fbe)
.getResourceDescription());
tde.setMessage(tde.getMessage() + LogbackTag.TAG_SEPERATOR
+ tde.getTestCaseName() + LogbackTag.TAG_SEPERATOR
+ tde.getTestStepName());
throw (TestDataException) itr.getThrowable();
} else { // other test case bean creation errors. need to create
// another exception to handle it.
String[] fullST = Utils.stackTrace(fbe, false);
int TWO = 2; // NOPMD
if (fullST.length < TWO) {
LogbackWriter
.writeSysError("java internal error in stack trace.");
} else {
String errLog = fullST[1];
if (null == errLog)
LogbackWriter
.writeSysError("java internal error in stack trace.");
else
LogbackWriter.writeSysError(errLog);
}
throw fbe;
}
} else {
throw fbe;
}
}
// catch (Throwable th) {//NOPMD
// LogbackWriter.printStackTrace(th);
// throw th;
// }
}
/**
* Tear down.
*/
@AfterMethod(alwaysRun = true)
public void tearDown() {
try {
if (null != mainDriver) {
mainDriver.quit();
}
if (null != context) {
Map<String, IMyWebDriver> myWebDrivers = context
.getBeansOfType(IMyWebDriver.class);
for (IMyWebDriver myWebDriver2 : myWebDrivers.values()) {
WebDriver weD = myWebDriver2.getWebDriver();
if (null != weD)
weD.quit();
}
}
} catch (UnreachableBrowserException | NoSuchWindowException e) { // NOPMD
// browser has been closed, no action needs to be done here.
}
if (null != context) {
((ConfigurableApplicationContext) context).close();
}
}
/**
* @return the context
*/
public ApplicationContext getContext() {
final ApplicationContext retVal = context;
if (null == retVal) {
throw new IllegalStateException(
"context is not correctly populated");
} else {
return retVal;
}
}
/**
* @param context
* the context to set
*/
public void setContext(ApplicationContext context) {
this.context = context;
}
/**
* @return the mainDriver
*/
public WebDriver getMainDriver() {
final WebDriver retVal = mainDriver;
if (null == retVal) {
throw new IllegalStateException(
"mainDriver is not correctly populated");
} else {
return retVal;
}
}
/**
* @param mainDriver
* the mainDriver to set
*/
public void setMainDriver(WebDriver mainDriver) {
this.mainDriver = mainDriver;
}
}