All Downloads are FREE. Search and download functionalities are using the official Maven repository.

core.support.logger.ExtentManager Maven / Gradle / Ivy

package core.support.logger;

import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;

import com.aventstack.extentreports.AnalysisStrategy;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.gherkin.model.Feature;
import com.aventstack.extentreports.gherkin.model.Scenario;
import com.aventstack.extentreports.reporter.ExtentHtmlReporter;
import com.aventstack.extentreports.reporter.ExtentKlovReporter;
import com.aventstack.extentreports.reporter.configuration.Protocol;
import com.aventstack.extentreports.reporter.configuration.Theme;

import core.apiCore.ServiceManager;
import core.helpers.Helper;
import core.helpers.UtilityHelper;
import core.helpers.emailHelper.EmailObject;
import core.support.configReader.Config;
import core.support.listeners.ParamOverrideTestNgService;
import core.support.listeners.TestListener;
import core.support.objects.TestObject;
import core.support.objects.TestObject.testState;

//OB: ExtentReports extent instance created here. That instance can be reachable by getReporter() method.

@SuppressWarnings("deprecation")
public class ExtentManager {

	public static final String LAUNCH_AFTER_REPORT = "report.launchReportAfterTest";
	public static final String NOTIFY_SLACK_ON_FAIL_ONLY = "slack.notifyOnFailureOnly";
	public static final String NOTIFY_EMAIL_ON_FAIL_ONLY = "email.notifyOnFailureOnly";

	public static final String ENABLE_SLACK_NOTIFICATION = "slack.enableSlackNotification";
	public static final String ENABLE_EMAIL_REPORT = "email.enableEmailReport";
	public static final String REPORT_EXPIRE_DAYS = "report.reportExpireDays";
	public static final String REPORT_TYPE = "report.reporterType";
	public static final String HTML_REPORT_TYPE = "html";
	public static final String KLOV_REPORT_TYPE = "klov";
	public static final String KLOV_SERVER_URL = "klov.server.url";
	public static final String KLOV_MONGODB_URL = "klov.mongodb.url";

	// list of classes (features)
	public static Map classList = new HashMap();

	private static ExtentReports extent;

	public static String REPORT_DEFAULT_NAME = "extent";
	public static ExtentKlovReporter klovReporter;

	public static String TEST_OUTPUT_PATH = File.separator + "test-output" + File.separator;
	public static String TEST_OUTPUT_FULL_PATH = Helper.getFullPath(TEST_OUTPUT_PATH);

	public synchronized static ExtentReports getReporter() {
		if (extent == null)
			createInstance(getReportHTMLFullPath());

		return extent;
	}

	public static String getScreenshotsFolderFullPath() {
		return getReportRootFullPath() + "screenshots/";
	}

	public static String getScreenshotsFolderRelativePath() {
		return "screenshots/";
	}

	public static String getMediaFolderFullPath() {
		return getReportRootFullPath() + "media/";
	}

	public static String getMediaFolderRelativePathFromHtmlReport() {
		return "media/";
	}

	public static String getMediaFolderRelativePathFromRoot() {
		return getReportRootRelativePath() + getMediaFolderRelativePathFromHtmlReport();
	}

	public static String getReportHTMLFullPath() {
		return getReportRootFullPath() + getReportName() + ".html";
	}

	public static String getReportRootFullPath() {
		return Helper.getFullPath(getReportRootRelativePath());
	}

	/**
	 * gets report folder path eg.selenium/test-output/testReports/20181124/core/
	 * 
	 * @return
	 */
	public static String getReportRootRelativePath() {
		DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
		Date date = new Date();
		String folderName = dateFormat.format(date);
		return TEST_OUTPUT_PATH + "testReports" + File.separator + folderName + File.separator
				+ TestObject.getTestInfo(TestObject.getDefaultTestObjectId()).app + File.separator;
	}

	public static ExtentReports createInstance(String fileName) {

		extent = new ExtentReports();

		// setup html reporter
		ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(fileName);
		htmlReporter.config().setTheme(Theme.STANDARD);
		htmlReporter.config().setDocumentTitle(fileName);
		htmlReporter.config().setEncoding("utf-8");
		htmlReporter.config().setProtocol(Protocol.HTTPS);
		htmlReporter.config().setReportName(fileName);
		htmlReporter.config().enableTimeline(true);
		htmlReporter.setAnalysisStrategy(AnalysisStrategy.BDD);

		if (Config.getValue(REPORT_TYPE).equals(HTML_REPORT_TYPE))
			extent.attachReporter(htmlReporter);

		// setup klov reporter
		setKlovReportReporter();

		return extent;
	}

	// TODO: set in test listener
	public static void setupReportPage() {
		// will run only once per test run
		// initializes the test report html page
		if (TestObject.getTestInfo().runCount == 0) {
			extent = ExtentManager.getReporter();
		}
	}

	/**
	 * setup report only for test methods, including before and after test not
	 * including: before suite, after suite, before class, after class this means
	 * only logs for test methods will show up in the reports reason: test report
	 * treats before/after suite, before/after class as tests and increases test
	 * count
	 */
	public static void reportSetup() {

		// Only setup report for test method. Ignores before suite, after suite, before
		// class, after class
		String testId = TestObject.getTestInfo().testId;
		testState state = TestObject.getTestState(testId);
		if (!state.equals(testState.testMethod))
			return;

		// will run only once per test run
		// initializes the test report html page
		setupReportPage();

		// will create parent once per class
		// initializes the test instance
		String className = TestObject.getTestInfo().getClassName();

		// if service test runner, return. Service tests have different test names once
		// the test starts, based on csv data
		if (className.equals(ServiceManager.SERVICE_TEST_RUNNER_ID))
			return;

		if (!classList.containsKey(className)) {
			String testParent = className.substring(className.lastIndexOf('.') + 1).trim();
			testParent = parseTestName(testParent);
			ExtentTest feature = extent.createTest(Feature.class, testParent);
			classList.put(className, feature);
			TestObject.getTestInfo().testFeature = feature;
		}

		// will run once every test
		// initializes test report
		if (TestObject.getTestInfo().runCount == 0) {
			TestObject.getTestInfo().incremenetRunCount();
			String testChild = TestObject.getTestInfo().testName;
			testChild = parseTestName(testChild);
			ExtentTest scenario = classList.get(className).createNode(Scenario.class, testChild);
			TestObject.getTestInfo().withTestScenario(scenario);
			TestLog.Background(TestObject.getTestInfo().testName + " initialized successfully");
		}
	}

	/**
	 * if test are run through suite, set project name as suite if test are run
	 * outside of suite, use the module/app name
	 */
	public static void setKlovReportReporter() {

		if (!Config.getValue(REPORT_TYPE).equals(KLOV_REPORT_TYPE))
			return;
		
		// set project name. if suite name is set (from suite file) Then use, else get
		// test project name
		if (TestObject.SUITE_NAME.contains("Default"))
			klovReporter = new ExtentKlovReporter(TestObject.APP_IDENTIFIER);
		else
			klovReporter = new ExtentKlovReporter(TestObject.SUITE_NAME);


		// setup klov reporter
		klovReporter.initMongoDbConnection(Config.getValue(KLOV_MONGODB_URL));
		klovReporter.initKlovServerConnection(Config.getValue(KLOV_SERVER_URL));

		klovReporter.setAnalysisStrategy(AnalysisStrategy.BDD);



		// set report name as current date time
		LocalDateTime now = LocalDateTime.now();
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		String formatDateTime = now.format(formatter);
		klovReporter.setReportName(formatDateTime);

		if (Config.getValue(REPORT_TYPE).equals(KLOV_REPORT_TYPE))
			extent.attachReporter(klovReporter);
	}

	/**
	 * launches the report html page after test run
	 * 
	 * @throws Exception
	 */
	public static void launchReportAfterTest() {
		if (Config.getBooleanValue(LAUNCH_AFTER_REPORT)) {

			URI link = null;
			try {
				if (Config.getValue(REPORT_TYPE).equals(KLOV_REPORT_TYPE)) {
					link = new URI(Config.getValue(KLOV_SERVER_URL));
				}
				if (Config.getValue(REPORT_TYPE).equals(HTML_REPORT_TYPE)) {
					link = new File(getReportHTMLFullPath()).toURI();
				}

				// open the default web browser for the HTML page

				Desktop.getDesktop().browse(link);
			} catch (Exception e) {
				e.getMessage();
			}
		}
	}

	public static void writeTestReport() {
		// removeEmptyTestNodesFromReport();
		try {
			new File(getReportRootFullPath()).mkdirs();
			new File(getReportHTMLFullPath()).createNewFile();
		} catch (IOException e) {
			e.printStackTrace();
		}
		ExtentManager.getReporter().flush();
	}

	/**
	 * Note: currently disabled as we're only adding test nodes to report removes
	 * empty logs from the test report these are logs that are initialized, But no
	 * test steps have been added to them note: test suite is removed, cause the
	 * feature When empty cannot be removed. feature in code is not associated with
	 * test steps TODO: find a way to preserve suite logs
	 */
	public static void removeEmptyTestNodesFromReport() {

		// remove default test
		/*
		 * boolean hasChild =
		 * TestObject.getTestInfo(TestObject.DEFAULT_TEST).testFeature.getModel().
		 * isChildNode(); ExtentTest test =
		 * TestObject.getTestInfo(TestObject.DEFAULT_TEST).testFeature;
		 * ExtentManager.getReporter().removeTest(test);
		 */
		// remove suite logs
		// TODO: find way to remove empty before suite from report
		for (Entry entry : TestObject.testInfo.entrySet()) {
			if (entry.getValue().testName.contains("Beforesuite") || entry.getValue().testName.contains("Aftersuite")) {
				try {
					ExtentManager.getReporter().removeTest(entry.getValue().testFeature);
				} catch (Exception e) {
					e.getMessage();
				}
			}
		}

		for (Entry entry : TestObject.testInfo.entrySet()) {
			if (entry.getValue().testName.contains("Beforeclass") || entry.getValue().testName.contains("Aftersuite")) {
				try {
					ExtentManager.getReporter().removeTest(entry.getValue().testFeature);
				} catch (Exception e) {
					e.getMessage();
				}
			}
		}

		// remove all tests with no test substeps. this means, no logging was done for
		// the test
		for (Entry entry : TestObject.testInfo.entrySet()) {
			if (entry.getValue().testScenerio != null && entry.getValue().testSubSteps.size() <= 1) {
				try {
					ExtentManager.getReporter().removeTest(entry.getValue().testScenerio);
				} catch (Exception e) {
					e.getMessage();
				}
			}
		}
	}

	/**
	 * prints the test report link for klov or html or report portal report type
	 */
	public static void printReportLink() {
		String link = "";
		if (Config.getValue(REPORT_TYPE).equals(KLOV_REPORT_TYPE)) {
			link = Config.getValue(KLOV_SERVER_URL);
		}
		if (Config.getValue(REPORT_TYPE).equals(HTML_REPORT_TYPE)) {
			link = new File(getReportHTMLFullPath()).toURI().toString();
		}
		System.out.println("Extent test report link: " + link);
		
		// print out report portal link
		if(Config.getBooleanValue(ParamOverrideTestNgService.REPORT_PORTAL_ENABLE)) {
			String url = Config.getValue(ParamOverrideTestNgService.ENDPOINT);
			System.out.println("Report Portal test report link: " + url);
		}
	}

	/**
	 * returns the test report name the report name is stored in default test object
	 * if test suit runs, Then suit name is the report name if test is run without
	 * suit, Then app name is used for report name
	 * 
	 * @return
	 */
	public static String getReportName() {
		return REPORT_DEFAULT_NAME;
	}

	/**
	 * TODO: replace slack api with newer library
	 * sends test report to slack slack notification must be enabled in properties
	 * file
	 * 
	 * @param message
	 */
	public static void slackNotification(String message) {
		// return if slack is not enabled
		if (!Config.getValue(ENABLE_SLACK_NOTIFICATION).equals("true"))
			return;

		TestLog.ConsoleLog("sending slack notification");

		// zip the test report directory
		String zipFile = UtilityHelper.zipDir(getReportRootFullPath(), TEST_OUTPUT_FULL_PATH + getReportName());

		// notify slack
		String comment = getReportName() + " automated tests complete. " + message;
		UtilityHelper.slackNotificationWithFile("test report", comment, zipFile);

	}

	/**
	 * zips up And emails test report with screenshot to specified email address
	 * 
	 * @throws Exception
	 */
	public static void emailTestReport(String message) {

		// return if email report not enabled
		if (!Config.getValue(ENABLE_EMAIL_REPORT).equals("true"))
			return;

		String fromEmail = Config.getValue("email.fromEmail");
		String toEmail = Config.getValue("email.toEmail");
		String password = Config.getValue("email.emailPassword");
		String smtpPort = Config.getValue("email.smtpPort");
		String smtpHost = Config.getValue("email.smtpHost");
		Boolean smtpStarttlsEnabled = Config.getBooleanValue("email.smtpStarttlsEnable");
		Boolean smtpAuth = Config.getBooleanValue("email.smtpAuth");

		TestLog.ConsoleLog("sending email report");

		// zip the test report directory
		String zipFilePath = UtilityHelper.zipDir(getReportRootFullPath(), TEST_OUTPUT_FULL_PATH + getReportName());
		// notify slack
		String comment = getReportName() + " automated tests complete. " + message;

		EmailObject email = new EmailObject().withToEmail(toEmail).withPassword(password).withFromEmail(fromEmail)
				.withSmtpPort(smtpPort).withSmtpHost(smtpHost).withSmtpStarttlsEnabled(smtpStarttlsEnabled)
				.withSmtpAuth(smtpAuth).withRecipientEmail(toEmail).withBody(comment)
				.withSubject(getReportName() + " test report").withAttachmentPath(zipFilePath)
				.withAttachmentFile("testReport.zip");

		Helper.sendMail(email);
	}
	

	/**
	 * deletes test report for particular run based on test run name
	 */
	public static void clearTestReport() {
		clearTestReport(StringUtils.EMPTY);
	}

	/**
	 * deletes test report for particular run based on test run name
	 */
	public static void clearTestReport(String suitename) {
		
		// do not clear report if running fail test retry suite
		if (suitename.equals(TestListener.FAILED_RERUN_SUITE_NAME))
			return;
		
		try {
			FileUtils.deleteDirectory(new File(getReportRootFullPath()));
		} catch(Exception e) {
			e.getMessage();
		}
	}

	public static void clearOldTestReports() {
		int maxDays = Config.getIntValue(REPORT_EXPIRE_DAYS);
		if (maxDays < 1)
			return;

		File folder = new File(TEST_OUTPUT_FULL_PATH + "testReports/");

		// return if report folder does not exist
		if (!folder.exists())
			return;

		for (File file : folder.listFiles()) {
			if (file.isDirectory()) {
				long diff = new Date().getTime() - file.lastModified();
				long diffDays = diff / (24 * 60 * 60 * 1000);
				if (diffDays > maxDays) {
					try {
						FileUtils.deleteDirectory(file);
					} catch (Exception e) {
						e.getMessage();
					}
				}
			}
		}
	}

	/**
	 * formats test name to format from: "loginTest" to "Login Test"
	 * 
	 * @param value
	 * @return
	 */
	public static String parseTestName(String value) {
		String formatted = "";
		value = value.replace("_", " ");

		for (String w : value.split("(?




© 2015 - 2025 Weber Informatics LLC | Privacy Policy