Best Carina code snippet using com.qaprosoft.carina.core.foundation.log.ThreadLogAppender
Source:AbstractTest.java  
...54import com.qaprosoft.carina.core.foundation.api.APIMethodBuilder;55import com.qaprosoft.carina.core.foundation.dataprovider.core.DataProviderFactory;56import com.qaprosoft.carina.core.foundation.jira.Jira;57import com.qaprosoft.carina.core.foundation.listeners.AbstractTestListener;58import com.qaprosoft.carina.core.foundation.log.ThreadLogAppender;59import com.qaprosoft.carina.core.foundation.report.Artifacts;60import com.qaprosoft.carina.core.foundation.report.HtmlReportGenerator;61import com.qaprosoft.carina.core.foundation.report.ReportContext;62import com.qaprosoft.carina.core.foundation.report.TestResultItem;63import com.qaprosoft.carina.core.foundation.report.TestResultType;64import com.qaprosoft.carina.core.foundation.report.email.EmailManager;65import com.qaprosoft.carina.core.foundation.report.email.EmailReportGenerator;66import com.qaprosoft.carina.core.foundation.report.email.EmailReportItemCollector;67import com.qaprosoft.carina.core.foundation.report.spira.Spira;68import com.qaprosoft.carina.core.foundation.report.testrail.TestRail;69import com.qaprosoft.carina.core.foundation.utils.Configuration;70import com.qaprosoft.carina.core.foundation.utils.Configuration.DriverMode;71import com.qaprosoft.carina.core.foundation.utils.Configuration.Parameter;72import com.qaprosoft.carina.core.foundation.utils.DateUtils;73import com.qaprosoft.carina.core.foundation.utils.JsonUtils;74import com.qaprosoft.carina.core.foundation.utils.Messager;75import com.qaprosoft.carina.core.foundation.utils.R;76import com.qaprosoft.carina.core.foundation.utils.SpecialKeywords;77import com.qaprosoft.carina.core.foundation.utils.metadata.MetadataCollector;78import com.qaprosoft.carina.core.foundation.utils.metadata.model.ElementsInfo;79import com.qaprosoft.carina.core.foundation.utils.naming.TestNamingUtil;80import com.qaprosoft.carina.core.foundation.utils.resources.I18N;81import com.qaprosoft.carina.core.foundation.utils.resources.L10N;82import com.qaprosoft.carina.core.foundation.utils.resources.L10Nparser;83import com.qaprosoft.carina.core.foundation.webdriver.DriverPool;84import com.qaprosoft.carina.core.foundation.webdriver.device.DevicePool;85/*86 * AbstractTest - base test for UI and API tests.87 * 88 * @author Alex Khursevich89 */90@Listeners({AbstractTestListener.class})91public abstract class AbstractTest // extends DriverHelper92{93    protected static final Logger LOGGER = Logger.getLogger(AbstractTest.class);94    protected APIMethodBuilder apiMethodBuilder;95    protected static final long IMPLICIT_TIMEOUT = Configuration.getLong(Parameter.IMPLICIT_TIMEOUT);96    protected static final long EXPLICIT_TIMEOUT = Configuration.getLong(Parameter.EXPLICIT_TIMEOUT);97    protected static final String SUITE_TITLE = "%s%s%s - %s (%s%s)";98    protected static final String XML_SUITE_NAME = " (%s)";99    protected static ThreadLocal<String> suiteNameAppender = new ThreadLocal<String>();100    101    // 3rd party integrations102    protected String browserVersion = "";103    protected long startDate;104    @BeforeSuite(alwaysRun = true)105    public void executeBeforeTestSuite(ITestContext context) throws Throwable {106    	107    	DevicePool.addDevices();108        // Add shutdown hook109        Runtime.getRuntime().addShutdownHook(new ShutdownHook());110        // Set log4j properties111        PropertyConfigurator.configure(ClassLoader.getSystemResource("log4j.properties"));112        // Set SoapUI log4j properties113        System.setProperty("soapui.log4j.config", "./src/main/resources/soapui-log4j.xml");114        try {115            Logger root = Logger.getRootLogger();116            Enumeration<?> allLoggers = root.getLoggerRepository().getCurrentCategories();117            while (allLoggers.hasMoreElements()) {118                Category tmpLogger = (Category) allLoggers.nextElement();119                if (tmpLogger.getName().equals("com.qaprosoft.carina.core")) {120                    tmpLogger.setLevel(Level.toLevel(Configuration.get(Parameter.CORE_LOG_LEVEL)));121                }122            }123        } catch (NoSuchMethodError e) {124            LOGGER.error("Unable to redefine logger level due to the conflicts between log4j and slf4j!");125        }126        startDate = new Date().getTime();127        LOGGER.info(Configuration.asString());128        // Configuration.validateConfiguration();129        LOGGER.debug("Default thread_count=" + context.getCurrentXmlTest().getSuite().getThreadCount());130        context.getCurrentXmlTest().getSuite().setThreadCount(Configuration.getInt(Parameter.THREAD_COUNT));131        LOGGER.debug("Updated thread_count=" + context.getCurrentXmlTest().getSuite().getThreadCount());132        // update DataProviderThreadCount if any property is provided otherwise sync with value from suite xml file133        int count = Configuration.getInt(Parameter.DATA_PROVIDER_THREAD_COUNT);134        if (count > 0) {135            LOGGER.debug("Updated 'data_provider_thread_count' from "136                    + context.getCurrentXmlTest().getSuite().getDataProviderThreadCount() + " to " + count);137            context.getCurrentXmlTest().getSuite().setDataProviderThreadCount(count);138        } else {139            LOGGER.debug("Synching data_provider_thread_count with values from suite xml file...");140            R.CONFIG.put(Parameter.DATA_PROVIDER_THREAD_COUNT.getKey(), String.valueOf(context.getCurrentXmlTest().getSuite().getDataProviderThreadCount()));141            LOGGER.debug("Updated 'data_provider_thread_count': " + Configuration.getInt(Parameter.DATA_PROVIDER_THREAD_COUNT));142        }143        LOGGER.debug("Default data_provider_thread_count="144                + context.getCurrentXmlTest().getSuite().getDataProviderThreadCount());145        LOGGER.debug("Updated data_provider_thread_count="146                + context.getCurrentXmlTest().getSuite().getDataProviderThreadCount());147        if (!Configuration.isNull(Parameter.URL)) {148            if (!Configuration.get(Parameter.URL).isEmpty()) {149                RestAssured.baseURI = Configuration.get(Parameter.URL);150            }151        }152        try {153            L10N.init();154        } catch (Exception e) {155            LOGGER.error("L10N bundle is not initialized successfully!", e);156        }157        try {158            I18N.init();159        } catch (Exception e) {160            LOGGER.error("I18N bundle is not initialized successfully!", e);161        }162        try {163            L10Nparser.init();164        } catch (Exception e) {165            LOGGER.error("L10Nparser bundle is not initialized successfully!", e);166        }167        try {168        	TestRail.updateBeforeSuite(context, this.getClass().getName(), getTitle(context));169        } catch (Exception e) {170        	LOGGER.error("TestRail is not initialized successfully!", e);171        }172		try {173			if (!Configuration.get(Parameter.ACCESS_KEY_ID).isEmpty()) {174				LOGGER.info("Initializing AWS S3 client...");175				AmazonS3Manager.getInstance().initS3client(Configuration.get(Parameter.ACCESS_KEY_ID),176						Configuration.get(Parameter.SECRET_KEY));177				updateS3AppPath();178			}179		} catch (Exception e) {180            LOGGER.error("AWS S3 client is not initialized successfully!", e);181		}182        183        // moved from UITest->executeBeforeTestSuite184        String customCapabilities = Configuration.get(Parameter.CUSTOM_CAPABILITIES);185        if (!customCapabilities.isEmpty()) {186            //redefine core properties using custom capabilities file187        	Map<String, String> properties = Configuration.loadCoreProperties(customCapabilities);188            //reregister device if mobile core properties are redefined 189            DevicePool.addDevice(properties);190        }191    }192    193    @BeforeClass(alwaysRun = true)194    public void executeBeforeTestClass(ITestContext context) throws Throwable {195        // do nothing for now196    }197    @AfterClass(alwaysRun = true)198    public void executeAfterTestClass(ITestContext context) throws Throwable {199        if (Configuration.getDriverMode() == DriverMode.CLASS_MODE) {200            LOGGER.debug("Deinitialize driver(s) in UITest->AfterClass.");201            quitDrivers();202        }203    }204    @BeforeMethod(alwaysRun = true)205    public void executeBeforeTestMethod(XmlTest xmlTest, Method testMethod,206                                        ITestContext context) throws Throwable {207        // do nothing for now208        Spira.registerStepsFromAnnotation(testMethod);209        210        apiMethodBuilder = new APIMethodBuilder();211    }212    213    214    @AfterMethod(alwaysRun = true)215    public void executeAfterTestMethod(ITestResult result) {216        try {217            DriverMode driverMode = Configuration.getDriverMode();218            if (driverMode == DriverMode.METHOD_MODE) {219                LOGGER.debug("Deinitialize driver(s) in @AfterMethod.");220                quitDrivers();221            }222            // TODO: improve later removing duplicates with AbstractTestListener223            //handle Zafira already passed exception for re-run and do nothing. maybe return should be enough224            if (result.getThrowable() != null && result.getThrowable().getMessage() != null225                    && result.getThrowable().getMessage().startsWith(SpecialKeywords.ALREADY_PASSED)) {226                // [VD] it is prohibited to release TestInfoByThread in this place.!227                return;228            }229            //handle AbstractTest->SkipExecution230            if (result.getThrowable() != null && result.getThrowable().getMessage() != null231                    && result.getThrowable().getMessage().startsWith(SpecialKeywords.SKIP_EXECUTION)) {232                // [VD] it is prohibited to release TestInfoByThread in this place.!233                return;234            }235            String test = TestNamingUtil.getCanonicalTestName(result);236            List<String> tickets = Jira.getTickets(result);237            result.setAttribute(SpecialKeywords.JIRA_TICKET, tickets);238            Jira.updateAfterTest(result);239            // Populate Spira Steps240            Spira.updateAfterTest(result, (String) result.getTestContext().getAttribute(SpecialKeywords.TEST_FAILURE_MESSAGE), tickets);241            Spira.clear();242            // Populate TestRail Cases243            if (!R.ZAFIRA.getBoolean("zafira_enabled")){244                result.setAttribute(SpecialKeywords.TESTRAIL_CASES_ID, TestRail.getCases(result));245                TestRail.updateAfterTest(result, (String) result.getTestContext().getAttribute(SpecialKeywords.TEST_FAILURE_MESSAGE));246                TestRail.clearCases();247            }248            //we shouldn't deregister info here as all retries will not work249            //TestNamingUtil.releaseZafiraTest();250            // clear jira tickets to be sure that next test is not affected.251            Jira.clearTickets();252            Artifacts.clearArtifacts();253            try {254                ThreadLogAppender tla = (ThreadLogAppender) Logger.getRootLogger().getAppender("ThreadLogAppender");255                if (tla != null) {256                    tla.closeResource(test);257                }258            } catch (NoSuchMethodError e) {259                LOGGER.error("Unable to redefine logger level due to the conflicts between log4j and slf4j!");260            }261        } catch (Exception e) {262            LOGGER.error("Exception in AbstractTest->executeAfterTestMethod: " + e.getMessage());263            e.printStackTrace();264        }265    }266    @AfterSuite(alwaysRun = true)267    public void executeAfterTestSuite(ITestContext context) {268        try {...Source:AbstractTestListener.java  
...33import org.testng.ITestResult;3435import com.qaprosoft.carina.core.foundation.dataprovider.parser.DSBean;36import com.qaprosoft.carina.core.foundation.jira.Jira;37import com.qaprosoft.carina.core.foundation.log.ThreadLogAppender;38import com.qaprosoft.carina.core.foundation.report.Artifacts;39import com.qaprosoft.carina.core.foundation.report.ReportContext;40import com.qaprosoft.carina.core.foundation.report.TestResultItem;41import com.qaprosoft.carina.core.foundation.report.TestResultType;42import com.qaprosoft.carina.core.foundation.report.email.EmailReportItemCollector;43import com.qaprosoft.carina.core.foundation.retry.RetryAnalyzer;44import com.qaprosoft.carina.core.foundation.retry.RetryCounter;45import com.qaprosoft.carina.core.foundation.utils.Configuration;46import com.qaprosoft.carina.core.foundation.utils.Configuration.Parameter;47import com.qaprosoft.carina.core.foundation.utils.DateUtils;48import com.qaprosoft.carina.core.foundation.utils.Messager;49import com.qaprosoft.carina.core.foundation.utils.ParameterGenerator;50import com.qaprosoft.carina.core.foundation.utils.R;51import com.qaprosoft.carina.core.foundation.utils.SpecialKeywords;52import com.qaprosoft.carina.core.foundation.utils.StringGenerator;53import com.qaprosoft.carina.core.foundation.utils.naming.TestNamingUtil;54import com.qaprosoft.carina.core.foundation.webdriver.DriverPool;55import com.qaprosoft.carina.core.foundation.webdriver.Screenshot;56import com.qaprosoft.carina.core.foundation.webdriver.device.DevicePool;5758@SuppressWarnings("deprecation")59public class AbstractTestListener extends TestArgsListener60{61	private static final Logger LOGGER = Logger.getLogger(AbstractTestListener.class);6263	protected static ThreadLocal<TestResultItem> configFailures = new ThreadLocal<TestResultItem>();6465	private void startItem(ITestResult result, Messager messager)66	{6768		String test = TestNamingUtil.getCanonicalTestName(result);69		test = TestNamingUtil.associateTestInfo2Thread(test, Thread.currentThread().getId());7071		String deviceName = getDeviceName();72		messager.info(deviceName, test, DateUtils.now());73	}7475	private void passItem(ITestResult result, Messager messager)76	{77		String test = TestNamingUtil.getCanonicalTestName(result);7879		String deviceName = getDeviceName();8081		messager.info(deviceName, test, DateUtils.now());8283		EmailReportItemCollector84				.push(createTestResult(result, TestResultType.PASS, null, result.getMethod().getDescription()));85		result.getTestContext().removeAttribute(SpecialKeywords.TEST_FAILURE_MESSAGE);8687		TestNamingUtil.releaseTestInfoByThread();88	}8990	private String failItem(ITestResult result, Messager messager)91	{92		String test = TestNamingUtil.getCanonicalTestName(result);9394		String errorMessage = getFailureReason(result);95		96		takeScreenshot(result, "TEST FAILED - " + errorMessage);97		98		String deviceName = getDeviceName();99100		// TODO: remove hard-coded text101		if (!errorMessage.contains("All tests were skipped! Analyze logs to determine possible configuration issues."))102		{103			messager.info(deviceName, test, DateUtils.now(), errorMessage);104			if (!R.EMAIL.getBoolean("fail_full_stacktrace_in_report") && result.getThrowable() != null105					&& result.getThrowable().getMessage() != null106					&& !StringUtils.isEmpty(result.getThrowable().getMessage()))107			{108				EmailReportItemCollector.push(createTestResult(result, TestResultType.FAIL,109						result.getThrowable().getMessage(), result.getMethod().getDescription()));110			} else111			{112				EmailReportItemCollector.push(createTestResult(result, TestResultType.FAIL, errorMessage, result113						.getMethod().getDescription()));114			}115		}116117		result.getTestContext().removeAttribute(SpecialKeywords.TEST_FAILURE_MESSAGE);118		TestNamingUtil.releaseTestInfoByThread();119		return errorMessage;120	}121122	private String failRetryItem(ITestResult result, Messager messager, int count, int maxCount)123	{124		String test = TestNamingUtil.getCanonicalTestName(result);125126		String errorMessage = getFailureReason(result);127		128		takeScreenshot(result, "TEST FAILED - " + errorMessage);129		130		String deviceName = getDeviceName();131132		messager.info(deviceName, test, String.valueOf(count), String.valueOf(maxCount), errorMessage);133134		result.getTestContext().removeAttribute(SpecialKeywords.TEST_FAILURE_MESSAGE);135		TestNamingUtil.releaseTestInfoByThread();136		return errorMessage;137	}138139	private String skipItem(ITestResult result, Messager messager)140	{141		String test = TestNamingUtil.getCanonicalTestName(result);142143		String errorMessage = getFailureReason(result);144		if (errorMessage.isEmpty())145		{146			// identify is it due to the dependent failure or exception in before suite/class/method147			String[] methods = result.getMethod().getMethodsDependedUpon();148149			// find if any parent method failed/skipped150			boolean dependentMethod = false;151			String dependentMethodName = "";152			for (ITestResult failedTest : result.getTestContext().getFailedTests().getAllResults())153			{154				for (int i = 0; i < methods.length; i++)155				{156					if (methods[i].contains(failedTest.getName()))157					{158						dependentMethodName = failedTest.getName();159						dependentMethod = true;160						break;161					}162				}163			}164165			for (ITestResult skippedTest : result.getTestContext().getSkippedTests().getAllResults())166			{167				for (int i = 0; i < methods.length; i++)168				{169					if (methods[i].contains(skippedTest.getName()))170					{171						dependentMethodName = skippedTest.getName();172						dependentMethod = true;173						break;174					}175				}176			}177178			if (dependentMethod)179			{180				errorMessage = "Test skipped due to the dependency from: " + dependentMethodName;181			} else182			{183				// Try to find error details from last configuration failure in this thread184				TestResultItem resultItem = getConfigFailure();185				if (resultItem != null)186				{187					errorMessage = resultItem.getFailReason();188				}189			}190		}191192		String deviceName = getDeviceName();193194		messager.info(deviceName, test, DateUtils.now(), errorMessage);195196		EmailReportItemCollector197				.push(createTestResult(result, TestResultType.SKIP, errorMessage, result.getMethod().getDescription()));198199		result.getTestContext().removeAttribute(SpecialKeywords.TEST_FAILURE_MESSAGE);200		TestNamingUtil.releaseTestInfoByThread();201		return errorMessage;202	}203	204	private void skipAlreadyPassedItem(ITestResult result, Messager messager)205	{206		String test = TestNamingUtil.getCanonicalTestName(result);207		String deviceName = getDeviceName();208		messager.info(deviceName, test, DateUtils.now());209	}210211	private String getDeviceName()212	{213		String deviceName = DevicePool.getDevice().getName();214		String deviceUdid = DevicePool.getDevice().getUdid();215216		if (!deviceName.isEmpty() && !deviceUdid.isEmpty())217		{218			deviceName = deviceName + " - " + deviceUdid;219		}220221		return deviceName;222	}223	224	private void afterConfiguration(ITestResult result) {225		//register configuration step as test artifact226		String test = TestNamingUtil.getCanonicalTestName(result);227		Artifacts.add("LOG-" + test, ReportContext.getTestLogLink(test));228		Artifacts.add("DEMO-" + test, ReportContext.getTestScreenshotsLink(test));229		TestNamingUtil.releaseTestInfoByThread();230	}231232	@Override233	public void beforeConfiguration(ITestResult result)234	{235		// startItem(result, Messager.CONFIG_STARTED);236		// // do failure test cleanup in this place as right after the test237		// // context doesn't have up-to-date information.238		// // This context cleanup is required to launch dependent steps if parent method pass from Nth retry!239		removeIncorrectlyFailedTests(result.getTestContext());240		241		242		// added 3 below lines to be able to track log/screenshots for before suite/class/method actions too243		TestNamingUtil.releaseTestInfoByThread();244		String test = TestNamingUtil.getCanonicalTestName(result);245		TestNamingUtil.associateCanonicTestName(test);246		247		super.beforeConfiguration(result);248	}249250	@Override251	public void onConfigurationSuccess(ITestResult result)252	{253		afterConfiguration(result);254		// passItem(result, Messager.CONFIG_PASSED);255		super.onConfigurationSuccess(result);256	}257258	@Override259	public void onConfigurationSkip(ITestResult result)260	{261		afterConfiguration(result);262		// skipItem(result, Messager.CONFIG_SKIPPED);263		super.onConfigurationSkip(result);264	}265266	@Override267	public void onConfigurationFailure(ITestResult result)268	{269		afterConfiguration(result);		270		// failItem(result, Messager.CONFIG_FAILED);271		// String test = TestNamingUtil.getCanonicalTestName(result);272		// closeLogAppender(test);273274		String errorMessage = getFailureReason(result);275		takeScreenshot(result, "CONFIGURATION FAILED - " + errorMessage);276		277		TestResultItem resultItem = createTestResult(result, TestResultType.FAIL, errorMessage,278				result.getMethod().getDescription());279		setConfigFailure(resultItem);280281		super.onConfigurationFailure(result);282	}283284	@Override285	public void onStart(ITestContext context)286	{287		String uuid = StringGenerator.generateNumeric(8);288		ParameterGenerator.setUUID(uuid);289290		ReportContext.getBaseDir(); // create directory for logging as soon as possible291292		/*293		 * //dropbox client initialization if (!Configuration.get(Parameter.DROPBOX_ACCESS_TOKEN).isEmpty()) {294		 * dropboxClient = new DropboxClient(Configuration.get(Parameter.DROPBOX_ACCESS_TOKEN)); }295		 */296		super.onStart(context);297	}298299	@Override300	public void onTestStart(ITestResult result)301	{302		super.onTestStart(result);303304		if (!result.getTestContext().getCurrentXmlTest().getTestParameters()305				.containsKey(SpecialKeywords.EXCEL_DS_CUSTOM_PROVIDER) &&306				result.getParameters().length > 0) // set parameters from XLS only if test contains any parameter at307													// all)308		{309			if (result.getTestContext().getCurrentXmlTest().getTestParameters()310					.containsKey(SpecialKeywords.EXCEL_DS_ARGS))311			{312				DSBean dsBean = new DSBean(result.getTestContext());313				int index = 0;314				for (String arg : dsBean.getArgs())315				{316					dsBean.getTestParams().put(arg, (String) result.getParameters()[index++]);317				}318				result.getTestContext().getCurrentXmlTest().setParameters(dsBean.getTestParams());319320			}321		}322		// obligatory reset any registered canonical name because for ALREADY_PASSED methods we can't do this in323		// onTestSkipped method324		TestNamingUtil.releaseTestInfoByThread();325		String test = TestNamingUtil.getCanonicalTestName(result);326		RetryCounter.initCounter(test);327328		startItem(result, Messager.TEST_STARTED);329330		TestNamingUtil.associateCanonicTestName(test);331	}332333	@Override334	public void onTestSuccess(ITestResult result)335	{336		passItem(result, Messager.TEST_PASSED);337338		// TestNamingUtil.releaseTestInfoByThread();339		super.onTestSuccess(result);340	}341342	@Override343	public void onTestFailure(ITestResult result)344	{345		String test = TestNamingUtil.getTestNameByThread();346		347		// String test = TestNamingUtil.getCanonicalTestName(result);348		int count = RetryCounter.getRunCount(test);349		int maxCount = RetryAnalyzer.getMaxRetryCountForTest();350		LOGGER.debug("count: " + count + "; maxCount:" + maxCount);351352		IRetryAnalyzer retry = result.getMethod().getRetryAnalyzer();353		if (count < maxCount && retry == null)354		{355			LOGGER.error("retry_count will be ignored as RetryAnalyzer is not declared for "356					+ result.getMethod().getMethodName());357		}358359		if (count < maxCount && retry != null && !Jira.isRetryDisabled(result))360		{361			TestNamingUtil.decreaseRetryCounter(test);362			failRetryItem(result, Messager.RETRY_RETRY_FAILED, count, maxCount);363		} else364		{365			failItem(result, Messager.TEST_FAILED);366			closeLogAppender(test);367		}368369		// TestNamingUtil.releaseTestInfoByThread();370		super.onTestFailure(result);371	}372373	@Override374	public void onTestSkipped(ITestResult result)375	{376		// TODO: improve later removing duplicates with AbstractTest377		// handle Zafira already passed exception for re-run and do nothing. maybe return should be enough378		if (result.getThrowable() != null && result.getThrowable().getMessage() != null379				&& result.getThrowable().getMessage().startsWith(SpecialKeywords.ALREADY_PASSED))380		{381			// [VD] it is prohibited to release TestInfoByThread in this place.!382			skipAlreadyPassedItem(result, Messager.TEST_SKIPPED_AS_ALREADY_PASSED);383			return;384		}385386		// handle AbstractTest->SkipExecution387		if (result.getThrowable() != null && result.getThrowable().getMessage() != null388				&& result.getThrowable().getMessage().startsWith(SpecialKeywords.SKIP_EXECUTION))389		{390			// [VD] it is prohibited to release TestInfoByThread in this place.!391			return;392		}393394		skipItem(result, Messager.TEST_SKIPPED);395		// TestNamingUtil.releaseTestInfoByThread();396		super.onTestSkipped(result);397	}398399	@Override400	public void onFinish(ITestContext context)401	{402		removeIncorrectlyFailedTests(context);403		// printContextTestsSummary(context);404		super.onFinish(context);405	}406407	/**408	 * When the test is restarted this method cleans fail statistics in test context.409	 *410	 */411	private void removeIncorrectlyFailedTests(ITestContext context)412	{413		// List of test results which we will delete later414		List<ITestResult> testsToBeRemoved = new ArrayList<>();415416		// collect all id's from passed test417		Set<Long> passedTestIds = new HashSet<>();418		for (ITestResult passedTest : context.getPassedTests().getAllResults())419		{420			// adding passed test421			long passedTestId = getMethodId(passedTest);422			LOGGER.debug("Adding passedTest info: " + passedTestId + "; " + passedTest.getName());423			passedTestIds.add(passedTestId);424		}425426		LOGGER.debug("---------------- ANALYZE FAILED RESULTS FOR DUPLICATES -----------------------");427428		Set<Long> failedTestIds = new HashSet<>();429		for (ITestResult failedTest : context.getFailedTests().getAllResults())430		{431432			// id = class + method + dataprovider433			long failedTestId = getMethodId(failedTest);434435			// if we saw this test as a failed test before we mark as to be deleted436			// or delete this failed test if there is at least one passed version437			if (failedTestIds.contains(failedTestId)438					|| passedTestIds.contains(failedTestId))439			{440				LOGGER.debug("Test to be removed from context: " + failedTestId + "; " + failedTest.getName());441				testsToBeRemoved.add(failedTest);442			} else443			{444				LOGGER.debug("Test to mark as failed: " + failedTestId + "; " + failedTest.getName());445				failedTestIds.add(failedTestId);446			}447		}448449		LOGGER.debug("---------------- REMOVE DUPLICATES FAILURES -----------------------");450		// finally delete all tests that are marked for removal451		for (Iterator<ITestResult> iterator = context.getFailedTests()452				.getAllResults().iterator(); iterator.hasNext();)453		{454			ITestResult testResult = iterator.next();455			if (testsToBeRemoved.contains(testResult))456			{457				LOGGER.debug("Removing test from context: " + testResult.getName());458				iterator.remove();459			}460		}461	}462463	@SuppressWarnings("unused")464	private void printContextTestsSummary(ITestContext context)465	{466		LOGGER.debug("getAllTestMethods length: " + context.getAllTestMethods().length);467		LOGGER.debug("---------------- PRINT SUMMARIZED SUCCESS -----------------------");468		// print messages about all tests in context469		LOGGER.debug("passed tests size: " + context.getPassedTests().getAllResults().size());470		for (Iterator<ITestResult> iterator = context.getPassedTests()471				.getAllResults().iterator(); iterator.hasNext();)472		{473			ITestResult testResult = iterator.next();474475			long testId = getMethodId(testResult);476			LOGGER.debug("Pass test in context: " + testId + "; "477					+ testResult.getName());478		}479480		LOGGER.debug("---------------- PRINT SUMMARIZED FAILURE -----------------------");481		// print messages about all tests in context482		LOGGER.debug("failed tests size: " + context.getFailedTests().getAllResults().size());483		for (Iterator<ITestResult> iterator = context.getFailedTests()484				.getAllResults().iterator(); iterator.hasNext();)485		{486			ITestResult testResult = iterator.next();487488			long testId = getMethodId(testResult);489			LOGGER.debug("Failed test in context: " + testId + "; "490					+ testResult.getName());491		}492493		LOGGER.debug("---------------- PRINT SUMMARIZED SKIP -----------------------");494		// print messages about all tests in context495		LOGGER.debug("skipped tests size: " + context.getSkippedTests().getAllResults().size());496		for (Iterator<ITestResult> iterator = context.getSkippedTests()497				.getAllResults().iterator(); iterator.hasNext();)498		{499			ITestResult testResult = iterator.next();500501			long testId = getMethodId(testResult);502			LOGGER.debug("Skipped test in context: " + testId + "; "503					+ testResult.getName());504		}505506		LOGGER.debug("---------------- PRINT SUMMARIZED CONFIGURATION SUCCESS -----------------------");507		LOGGER.debug("passed configurations size: " + context.getPassedConfigurations().getAllResults().size());508		for (Iterator<ITestResult> iterator = context.getPassedConfigurations()509				.getAllResults().iterator(); iterator.hasNext();)510		{511			ITestResult testResult = iterator.next();512513			long testId = getMethodId(testResult);514			LOGGER.debug("passed configurations in context: " + testId + "; "515					+ testResult.getName());516		}517518		LOGGER.debug("---------------- PRINT SUMMARIZED CONFIGURATION FAILURE -----------------------");519		LOGGER.debug("failed configurations size: " + context.getFailedConfigurations().getAllResults().size());520		for (Iterator<ITestResult> iterator = context.getFailedConfigurations()521				.getAllResults().iterator(); iterator.hasNext();)522		{523			ITestResult testResult = iterator.next();524525			long testId = getMethodId(testResult);526			LOGGER.debug("failed configurations in context: " + testId + "; "527					+ testResult.getName());528		}529530		LOGGER.debug("---------------- PRINT SUMMARIZED CONFIGURATION SKIP -----------------------");531		LOGGER.debug("skipped configurations size: " + context.getSkippedConfigurations().getAllResults().size());532		for (Iterator<ITestResult> iterator = context.getSkippedConfigurations()533				.getAllResults().iterator(); iterator.hasNext();)534		{535			ITestResult testResult = iterator.next();536537			long testId = getMethodId(testResult);538			LOGGER.debug("failed configurations in context: " + testId + "; "539					+ testResult.getName());540		}541	}542543	private long getMethodId(ITestResult result)544	{545		long id = result.getTestClass().getName().hashCode();546		id = 31 * id + result.getMethod().getMethodName().hashCode();547		id = 31548				* id549				+ (result.getParameters() != null ? Arrays.hashCode(result550						.getParameters()) : 0);551		// LOGGER.debug("Calculated id for " + result.getMethod().getMethodName() + " is " + id);552		return id;553	}554555	protected TestResultItem createTestResult(ITestResult result, TestResultType resultType, String failReason,556			String description)557	{558		String group = TestNamingUtil.getPackageName(result);559		String test = TestNamingUtil.getCanonicalTestName(result);560		String linkToLog = ReportContext.getTestLogLink(test);561		String linkToVideo = ReportContext.getTestVideoLink(test);562		// String linkToScreenshots = ReportContext.getTestScreenshotsLink(testName);563		String linkToScreenshots = null;564565		if (TestResultType.FAIL.equals(resultType))566		{567			String bugInfo = Jira.processBug(result);568			if (bugInfo != null)569			{570				if (failReason != null)571				{572					failReason = bugInfo.concat("\n").concat(failReason);573				} else574				{575					failReason = bugInfo;576				}577			}578		}579580		if (!FileUtils.listFiles(ReportContext.getTestDir(test), new String[]581		{ "png" }, false).isEmpty())582		{583			if (TestResultType.PASS.equals(resultType) && !Configuration.getBoolean(Parameter.KEEP_ALL_SCREENSHOTS))584			{585				// remove physically all screenshots if test/config pass and KEEP_ALL_SCREENSHOTS=false to improve586				// cooperation with CI tools587				ReportContext.removeTestScreenshots(test);588			} else589			{590				linkToScreenshots = ReportContext.getTestScreenshotsLink(test);591			}592		}593		TestResultItem testResultItem = new TestResultItem(group, test, resultType, linkToScreenshots, linkToLog,594				linkToVideo, failReason);595		testResultItem.setDescription(description);596		// AUTO-1081 eTAF report does not show linked Jira tickets if test PASSED597		// jira tickets should be used for tracking tasks. application issues will be tracked by planned zafira feature598		testResultItem.setJiraTickets(Jira.getTickets(result));599		return testResultItem;600	}601602	protected String getFailureReason(ITestResult result)603	{604		String errorMessage = "";605		String message = "";606607		if (result.getThrowable() != null)608		{609			Throwable thr = result.getThrowable();610			errorMessage = getFullStackTrace(thr);611			message = thr.getMessage();612			result.getTestContext().setAttribute(SpecialKeywords.TEST_FAILURE_MESSAGE, message);613		}614615		return errorMessage;616	}617618	private String getFullStackTrace(Throwable thr)619	{620		String stackTrace = "";621622		if (thr != null)623		{624			stackTrace = thr.getMessage() + "\n";625626			StackTraceElement[] elems = thr.getStackTrace();627			for (StackTraceElement elem : elems)628			{629				stackTrace = stackTrace + "\n" + elem.toString();630			}631		}632		return stackTrace;633	}634635	private void closeLogAppender(String test)636	{637		if (test == null) {638			LOGGER.error("Unable to close appender for null test!");639			return;640		}641		try642		{643			ThreadLogAppender tla = (ThreadLogAppender) Logger.getRootLogger().getAppender("ThreadLogAppender");644			if (tla != null)645			{646				tla.closeResource(test);647			}648		} catch (Throwable e)649		{650			LOGGER.error("close log appender was not successful.");651			e.printStackTrace();652		}653	}654655	private TestResultItem getConfigFailure()656	{657		return configFailures.get();
...Source:ThreadLogAppender.java  
...13import com.qaprosoft.carina.core.foundation.webdriver.device.DevicePool;14/*15 *  This appender logs groups test outputs by test method so they don't mess up each other even they runs in parallel.16 */17public class ThreadLogAppender extends AppenderSkeleton18{19	private final ConcurrentHashMap<String, BufferedWriter> test2file = new ConcurrentHashMap<String, BufferedWriter>();20	@Override21	public synchronized void append(LoggingEvent event)22	{23		if (!ReportContext.isBaseDireCreated()) {24			System.out.println(event.getMessage().toString());25			return;26		}27		try28		{29			String test = "";30			if (TestNamingUtil.isTestNameRegistered()) {31				test = TestNamingUtil.getTestNameByThread();...ThreadLogAppender
Using AI Code Generation
1package com.qaprosoft.carina.core.foundation.log;2import org.apache.log4j.Logger;3import org.testng.annotations.Test;4public class ThreadLogAppenderTest {5    public void testThreadLogAppender() {6        Logger logger = Logger.getLogger(ThreadLogAppenderTest.class);7        logger.info("Test info message");8    }9}10package com.qaprosoft.carina.core.foundation.log;11import org.apache.log4j.Logger;12import org.testng.annotations.Test;13public class ThreadLogAppenderTest {14    public void testThreadLogAppender() {15        Logger logger = Logger.getLogger(ThreadLogAppenderTest.class);16        logger.info("Test info message");17    }18}19package com.qaprosoft.carina.core.foundation.log;20import org.apache.log4j.Logger;21import org.testng.annotations.Test;22public class ThreadLogAppenderTest {23    public void testThreadLogAppender() {24        Logger logger = Logger.getLogger(ThreadLogAppenderTest.class);25        logger.info("Test info message");26    }27}28package com.qaprosoft.carina.core.foundation.log;29import org.apache.log4j.Logger;30import org.testng.annotations.Test;31public class ThreadLogAppenderTest {32    public void testThreadLogAppender() {33        Logger logger = Logger.getLogger(ThreadLogAppenderTest.class);34        logger.info("Test info message");35    }36}37package com.qaprosoft.carina.core.foundation.log;38import org.apache.log4j.Logger;39import org.testng.annotations.Test;40public class ThreadLogAppenderTest {41    public void testThreadLogAppender() {42        Logger logger = Logger.getLogger(ThreadLogAppenderTest.class);43        logger.info("Test info message");44    }45}ThreadLogAppender
Using AI Code Generation
1import com.qaprosoft.carina.core.foundation.log.ThreadLogAppender;2public class 1 {3    public static void main(String[] args) {4        ThreadLogAppender appender = new ThreadLogAppender();5        appender.start();6        appender.addLog("INFO", "Test message");7        appender.addLog("ERROR", "Test error message");8        appender.stop();9    }10}11import com.qaprosoft.carina.core.foundation.log.ThreadLogAppender;12public class 2 {13    public static void main(String[] args) {14        ThreadLogAppender appender = new ThreadLogAppender();15        appender.start();16        appender.addLog("INFO", "Test message");17        appender.addLog("ERROR", "Test error message");18        appender.stop();19    }20}21import com.qaprosoft.carina.core.foundation.log.ThreadLogAppender;22public class 3 {23    public static void main(String[] args) {24        ThreadLogAppender appender = new ThreadLogAppender();25        appender.start();26        appender.addLog("INFO", "Test message");27        appender.addLog("ERROR", "Test error message");28        appender.stop();29    }30}31import com.qaprosoft.carina.core.foundation.log.ThreadLogAppender;32public class 4 {33    public static void main(String[] args) {34        ThreadLogAppender appender = new ThreadLogAppender();35        appender.start();36        appender.addLog("INFO", "Test message");37        appender.addLog("ERROR", "Test error message");38        appender.stop();39    }40}41import com.qaprosoft.carina.core.foundation.log.ThreadLogAppender;42public class 5 {43    public static void main(String[] args) {44        ThreadLogAppender appender = new ThreadLogAppender();45        appender.start();46        appender.addLog("INFO", "ThreadLogAppender
Using AI Code Generation
1import static com.qaprosoft.carina.core.foundation.log.ThreadLogAppender.addThreadLog;2import static com.qaprosoft.carina.core.foundation.log.ThreadLogAppender.addThreadLogDirect;3import org.testng.annotations.Test;4public class TestClass {5	public void test1() {6		addThreadLog("test1: Test is started");7		addThreadLog("test1: Test is finished");8	}9	public void test2() {10		addThreadLogDirect("test2: Test is started");11		addThreadLogDirect("test2: Test is finished");12	}13}14import static com.qaprosoft.carina.core.foundation.log.ThreadLogAppender.addThreadLog;15import static com.qaprosoft.carina.core.foundation.log.ThreadLogAppender.addThreadLogDirect;16import org.testng.annotations.Test;17public class TestClass {18	public void test1() {19		addThreadLog("test1: Test is started");20		addThreadLog("test1: Test is finished");21	}22	public void test2() {23		addThreadLogDirect("test2: Test is started");24		addThreadLogDirect("test2: Test is finished");25	}26}27import static com.qaprosoft.carina.core.foundation.log.ThreadLogAppender.addThreadLog;28import static com.qaprosoft.carina.core.foundation.log.ThreadLogAppender.addThreadLogDirect;29import org.testng.annotations.Test;30public class TestClass {31	public void test1() {32		addThreadLog("test1: Test is started");33		addThreadLog("test1: Test is finished");34	}35	public void test2() {ThreadLogAppender
Using AI Code Generation
1import org.apache.log4j.Logger;2public class ThreadLogAppenderTest {3    private static final Logger LOGGER = Logger.getLogger(ThreadLogAppenderTest.class);4    public static void main(String[] args) {5        LOGGER.info("Message 1");6        LOGGER.info("Message 2");7        LOGGER.info("Message 3");8    }9}10import org.apache.log4j.Logger;11public class ThreadLogAppenderTest2 {12    private static final Logger LOGGER = Logger.getLogger(ThreadLogAppenderTest2.class);13    public static void main(String[] args) {14        LOGGER.info("Message 1");15        LOGGER.info("Message 2");16        LOGGER.info("Message 3");17    }18}19import org.apache.log4j.Logger;20public class ThreadLogAppenderTest3 {21    private static final Logger LOGGER = Logger.getLogger(ThreadLogAppenderTest3.class);22    public static void main(String[] args) {23        LOGGER.info("Message 1");24        LOGGER.info("Message 2");25        LOGGER.info("Message 3");26    }27}28import org.apache.log4j.Logger;29public class ThreadLogAppenderTest4 {30    private static final Logger LOGGER = Logger.getLogger(ThreadLogAppenderTest4.class);31    public static void main(String[] args) {32        LOGGER.info("Message 1");33        LOGGER.info("Message 2");34        LOGGER.info("Message 3");35    }36}37import org.apacheThreadLogAppender
Using AI Code Generation
1ThreadLogAppender.init();2ThreadLogAppender.info("test execution info");3ThreadLogAppender.stop();4Log4jAppender.init();5Log4jAppender.info("test execution info");6Log4jAppender.stop();7Log4jAppender.init();8Log4jAppender.info("test execution info");9Log4jAppender.stop();10Log4jAppender.init();11Log4jAppender.info("test execution info");12Log4jAppender.stop();13Log4jAppender.init();14Log4jAppender.info("test execution info");15Log4jAppender.stop();16Log4jAppender.init();17Log4jAppender.info("test execution info");Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
