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

org.tap4j.ext.testng.TestNGYAMLishUtils Maven / Gradle / Ivy

There is a newer version: 4.4.2
Show newest version
/*
 * The MIT License
 *
 * Copyright (c) <2010> 
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.tap4j.ext.testng;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.commons.lang.StringUtils;
import org.testng.ITestResult;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlInclude;
import org.testng.xml.XmlPackage;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;
import org.yaml.snakeyaml.DumperOptions.LineBreak;
import org.yaml.snakeyaml.JavaBeanLoader;
import org.yaml.snakeyaml.reader.UnicodeReader;

/**
 * @author Bruno P. Kinoshita - http://www.kinoshita.eti.br
 * @since 1.0
 */
public final class TestNGYAMLishUtils
{
	/**
	 * Date Format used to format a datetime in ISO-8061 for YAMLish diagnostic.
	 */
	public static final SimpleDateFormat ISO_8061_DATE_FORMAT = new SimpleDateFormat(
			"yyyy-MM-dd'T'HH:mm:ss");

	public static final String LINE_SEPARATOR = LineBreak.UNIX.getString();
	
	/**
	 * Default hidden constructor.
	 */
	private TestNGYAMLishUtils()
	{
		super();
	}

	/**
	 * @param testNgTestResult
	 * @return Message value
	 */
	public static String getMessage( ITestResult testNgTestResult )
	{
		return "TestNG Test " + testNgTestResult.getName();
	}

	/**
	 * @param testNgTestResult
	 * @return Severity value
	 */
	public static String getSeverity( ITestResult testNgTestResult )
	{
		String severity = "~";
		if (testNgTestResult.getThrowable() != null)
		{
			severity = "High";
		}
		return severity;
	}

	/**
	 * @param testNgTestResult
	 * @return Source value
	 */
	public static String getSource( ITestResult testNgTestResult )
	{
		String source = testNgTestResult.getTestClass().getName() 
				+ "#" + testNgTestResult.getMethod().getMethodName();
		return source;
	}

	/**
	 * Retrieves the date of the TestNG Test Result start time.
	 * @return Datetime value
	 */
	public static String getDatetime( ITestResult testNgTestResult )
	{
		long ms = testNgTestResult.getStartMillis();
		Date date = new Date(ms);
		String iso8061Datetime = ISO_8061_DATE_FORMAT.format(date);
		return iso8061Datetime;
	}

	/**
	 * @param testNgTestResult
	 * @return File value
	 */
	public static String getFile( ITestResult testNgTestResult )
	{
		String file = testNgTestResult.getTestClass().getName();
		return file;
	}

	/**
	 * @param testNgTestResult
	 * @return Line value
	 */
	public static String getLine( ITestResult testNgTestResult )
	{
		String line = "~";
		Throwable testNGException = testNgTestResult.getThrowable();
		if (testNGException != null)
		{
			StringBuilder lookFor = new StringBuilder();
			lookFor.append(testNgTestResult.getTestClass().getName());
			lookFor.append('.');
			lookFor.append(testNgTestResult.getMethod().getMethodName());
			lookFor.append('(');
			lookFor.append(testNgTestResult.getTestClass().getClass().getSimpleName());
			lookFor.append(".java:");
			
			StackTraceElement[] els = testNGException.getStackTrace();
			
			for (int i = 0; i < els.length; i++)
			{
				StackTraceElement el = els[i];
				line = getLineNumberFromExceptionTraceLine(el.toString(), lookFor.toString());
				if (line!="")
				{
					break;
				}
			}
		}
		return line;
	}
	
	/**
	 * Get the error line number from the exception stack trace
	 * @param exceptionTraceLine
	 * @param substrToSearch
	 * @return error line number
	 */
	public static String getLineNumberFromExceptionTraceLine(String exceptionTraceLine, String substrToSearch)
	{
		String lineNumber="";
		int index = exceptionTraceLine.indexOf(substrToSearch);
		if (index >= 0)
		{
			int length = substrToSearch.length() + index;
			if( exceptionTraceLine.lastIndexOf(')') > length )
			{
				lineNumber = exceptionTraceLine.substring(length, exceptionTraceLine.lastIndexOf(')'));
			}
		}
		return lineNumber;
	}
	
	/**
	 * @param testNgTestResult
	 * @return Name value
	 */
	public static String getName( ITestResult testNgTestResult )
	{
		String name = testNgTestResult.getName();
		return name;
	}

	/**
	 * @param testNgTestResult
	 * @return Extensions value
	 */
	@SuppressWarnings("unchecked")
	public static Object getExtensions( ITestResult testNgTestResult )
	{
		Object extensions = null;
		Set attributeNames = testNgTestResult.getAttributeNames();
		Iterator iterator = attributeNames.iterator();
		if ( iterator.hasNext() )
		{
			extensions = new LinkedHashMap();
			for ( ; iterator.hasNext();)
			{
				String attributeName = iterator.next();
				Object attributeValue = testNgTestResult.getAttribute( attributeName );
				((Map)extensions).put( attributeName, attributeValue );
			}
		}
		else
		{
			extensions = '~';
		}
		return extensions;
	}

	/**
	 * @param testNgTestResult
	 * @return Expected value
	 */
	public static String getExpected( ITestResult testNgTestResult )
	{
		Throwable throwable = testNgTestResult.getThrowable();

		String expected = null;

		if (throwable != null)
		{
			StringWriter sw = new StringWriter();
			PrintWriter pw = new PrintWriter(sw);
			throwable.printStackTrace(pw);

			String stringException = sw.toString();

			String expectedToken = "expected:";
			String butWasToken = " but was:";
			int index = stringException.toString().indexOf( expectedToken.toString() );
			
			if (index > 0)
			{
				expected = stringException.toString().substring(
						index + expectedToken.length(),
						stringException.toString().lastIndexOf(butWasToken));
				index = stringException.toString().indexOf(butWasToken);
			}
		}
		return expected;
	}

	/**
	 * @param testNgTestResult
	 * @return Actual value
	 */
	public static String getActual( ITestResult testNgTestResult )
	{
		Throwable throwable = testNgTestResult.getThrowable();

		String actual = "~";

		if (throwable != null)
		{
			StringWriter sw = new StringWriter();
			PrintWriter pw = new PrintWriter(sw);
			throwable.printStackTrace(pw);

			String stringException = sw.toString();

			String expectedToken = "expected:";
			String butWasToken = " but was:";
			int index = stringException.toString().indexOf(expectedToken.toString());
			if (index > 0)
			{
				index = stringException.toString().indexOf(butWasToken);
				int eolIndex = stringException.toString().indexOf( System.getProperty("line.separator"), index);
				actual = stringException.toString().substring( index + butWasToken.length(), eolIndex);
			}
		}

		return actual;
	}

	/**
	 * Returns YAMLish multi-line display entry.
	 * 
	 * @param testNgTestResult TestNG TestResult
	 * @return YAMLish multi-line
	 */
	public static String getDisplay( ITestResult testNgTestResult )
	{
		
		StringBuilder displayBuffer = new StringBuilder();

		String expected = getExpected(testNgTestResult);
		String actual = getActual(testNgTestResult);

		if (StringUtils.isNotEmpty(expected) && StringUtils.isNotEmpty(actual))
		{
			int expectedLength = expected.length();
			int actualLength = actual.length();

			int greater = expectedLength;
			if (actualLength > expectedLength)
			{
				greater = actualLength;
			} else if ("Expected".length() > greater)
			{
				greater = "Expected".length();
			}

			// Actual length plus the two spaces and an extra for next character
			int greaterPlus3 = greater + 3;

			displayBuffer.append("+" + fill(greaterPlus3, '-') + "+" + fill(greaterPlus3, '-') + "+");
			displayBuffer.append(LINE_SEPARATOR);
			
			displayBuffer.append("+" + fill(greater, "Got") + "|" + fill(greater, "Expected") + "+");
			displayBuffer.append(LINE_SEPARATOR);
			
			displayBuffer.append("+" + fill(greaterPlus3, '-') + "+" + fill(greaterPlus3, '-') + "+");
			displayBuffer.append(LINE_SEPARATOR);
			
			displayBuffer.append("+" + fill(greater, actual) + "|" + fill(greater, expected) + "+");
			displayBuffer.append(LINE_SEPARATOR);
			
			displayBuffer.append("+" + fill(greaterPlus3, '-') + "+" + fill(greaterPlus3, '-') + "+");
			
		} 
		else
		{
			displayBuffer.append('~');
		}

		return displayBuffer.toString();

	}

	/**
	 * @param greater
	 * @return
	 */
	private static String fill( int greater, char c )
	{
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < greater; ++i)
		{
			sb.append(Character.toString( c ));
		}
		return sb.toString();
	}

	/**
	 * @param greater
	 * @return
	 */
	private static String fill( int greater, String s )
	{
		StringBuilder sb = new StringBuilder();
		sb.append(' ');
		sb.append(s);
		int newgreater = greater - s.length();
		sb.append(fill(newgreater + 1, ' '));
		sb.append(' ');
		return sb.toString();
	}

	/**
	 * @param testNgTestResult
	 * @return Dump value
	 */
	@SuppressWarnings("unchecked")
	public static Object getDump( ITestResult testNgTestResult )
	{
		Object returnObject = null;
		// TBD: print names
		Object[] parameters = testNgTestResult.getParameters();
		if (parameters.length > 0)
		{
			returnObject = new LinkedHashMap();
			for (int i = 0; i < parameters.length; i++)
			{
				Object parameter = parameters[i];
				((Map) returnObject).put("param" + (i + 1), parameter);
			}
		} else
		{
			returnObject = "~";
		}
		return returnObject.toString();
	}

	/**
	 * @param testNgTestResult
	 * @return Error value
	 */
	public static String getError( ITestResult testNgTestResult )
	{
		String error = "~";

		Throwable t = testNgTestResult.getThrowable();

		if (t != null)
		{
			error = t.getMessage();
		}

		return error;
	}

	/**
	 * @param testNgTestResult
	 * @return Backtrace value
	 */
	public static String getBacktrace( ITestResult testNgTestResult )
	{
		StringBuilder stackTrace = new StringBuilder();

		Throwable throwable = testNgTestResult.getThrowable();

		if (throwable != null)
		{
			StringWriter sw = new StringWriter();
			PrintWriter pw = new PrintWriter(sw);
			throwable.printStackTrace(pw);
			String stackTraceString = sw.toString();
			stackTraceString = stackTraceString.trim().replaceAll("\\r\\n", "\n");

			StringTokenizer st = new StringTokenizer(stackTraceString, LINE_SEPARATOR );
			while (st.hasMoreTokens())
			{
				String stackTraceLine = st.nextToken();
				stackTrace.append(stackTraceLine);
				stackTrace.append( LINE_SEPARATOR );
			}
			
		} 
		else
		{
			stackTrace.append('~');
		}

		return stackTrace.toString();
	}

	/*
	 * Methods from SnakeYAML project.
	 * 
	 * See http://code.google.com/p/snakeyaml/wiki/TestingNG_YAML for more.
	 */

	public static StringBuilder toYaml( XmlSuite suite )
	{
		StringBuilder result = new StringBuilder();

		maybeAdd(result, "name", suite.getName(), null);
		maybeAdd(result, "junit", suite.isJUnit(), XmlSuite.DEFAULT_JUNIT);
		maybeAdd(result, "verbose", suite.getVerbose(), XmlSuite.DEFAULT_VERBOSE);
		maybeAdd(result, "threadCount", suite.getThreadCount(), XmlSuite.DEFAULT_THREAD_COUNT);
		maybeAdd(result, "dataProviderThreadCount",
				suite.getDataProviderThreadCount(),
				XmlSuite.DEFAULT_DATA_PROVIDER_THREAD_COUNT);
		maybeAdd(result, "timeOut", suite.getTimeOut(), null);
		maybeAdd(result, "parallel", suite.getParallel(),
				XmlSuite.DEFAULT_PARALLEL);
		maybeAdd(result, "skipFailedInvocationCounts",
				suite.skipFailedInvocationCounts(),
				XmlSuite.DEFAULT_SKIP_FAILED_INVOCATION_COUNTS);

		toYaml(result, "parameters", "", suite.getParameters());
		toYaml(result, suite.getPackages());

		if (suite.getListeners().size() > 0)
		{
			result.append("listeners:\n");
			toYaml(result, "  ", suite.getListeners());
		}

		if (suite.getPackages().size() > 0)
		{
			result.append("packages:\n");
			toYaml(result, suite.getPackages());
		}
		toYaml(result, "listeners", suite.getListeners());
		if (suite.getTests().size() > 0)
		{
			result.append("tests:\n");
			for (XmlTest t : suite.getTests())
			{
				toYaml(result, "  ", t);
			}
		}

		if (suite.getChildSuites().size() > 0)
		{
			result.append("suite-files:\n");
			toYaml(result, "  ", suite.getSuiteFiles());
		}

		return result;
	}

	/**
	 * 
	 * @param sb
	 * @param key
	 * @param value
	 * @param def
	 */
	private static void maybeAdd( StringBuilder sb, String key, Object value, Object def )
	{
		maybeAdd(sb, "", key, value, def);
	}

	/**
	 * 
	 * @param sb
	 * @param sp
	 * @param key
	 * @param value
	 * @param def
	 */
	private static void maybeAdd( StringBuilder sb, String sp, String key,
								  Object value, Object def )
	{
		if (value != null && !value.equals(def))
		{
			sb.append(sp).append(key).append(": ").append(value.toString()).append("\n");
		}
	}

	/**
	 * 
	 * @param result
	 * @param sp
	 * @param t
	 */
	private static void toYaml( StringBuilder result, String sp, XmlTest t )
	{
		String sp2 = sp + "  ";
		result.append(sp).append("- name: ").append(t.getName()).append("\n");

		maybeAdd(result, sp2, "junit", t.isJUnit(), XmlSuite.DEFAULT_JUNIT);
		maybeAdd(result, sp2, "verbose", t.getVerbose(), XmlSuite.DEFAULT_VERBOSE);
		maybeAdd(result, sp2, "timeOut", t.getTimeOut(), null);
		maybeAdd(result, sp2, "parallel", t.getParallel(), XmlSuite.DEFAULT_PARALLEL);
		maybeAdd(result, sp2, "skipFailedInvocationCounts", t.skipFailedInvocationCounts(), XmlSuite.DEFAULT_SKIP_FAILED_INVOCATION_COUNTS);

		maybeAdd(result, "preserveOrder", sp2, t.getPreserveOrder(), "false"); // TBD: is it the default value?

		toYaml(result, "parameters", sp2, t.getParameters());

		if (t.getIncludedGroups().size() > 0)
		{
			result.append(sp2).append("includedGroups: [ ")
					.append(StringUtils.join(t.getIncludedGroups(), ","))
					.append(" ]\n");
		}

		if (t.getExcludedGroups().size() > 0)
		{
			result.append(sp2).append("excludedGroups: [ ")
					.append(StringUtils.join(t.getExcludedGroups(), ","))
					.append(" ]\n");
		}

		Map> mg = t.getMetaGroups();
		if (mg.size() > 0)
		{
			result.append(sp2).append("metaGroups: { ");
			boolean first = true;
			for (String group : mg.keySet())
			{
				if (!first)
				{
					result.append(", ");
				}
				result.append(group).append(": [ ")
						.append(StringUtils.join(mg.get(group), ",")).append(" ] ");
				first = false;
			}
			result.append(" }\n");
		}

		if (t.getXmlPackages().size() > 0)
		{
			result.append(sp2).append("xmlPackages:\n");
			for (XmlPackage xp : t.getXmlPackages())
			{
				toYaml(result, sp2 + "  - ", xp);
			}
		}

		if (t.getXmlClasses().size() > 0)
		{
			result.append(sp2).append("classes:\n");
			for (XmlClass xc : t.getXmlClasses())
			{
				toYaml(result, sp2 + "  ", xc);
			}
		}

		result.append("\n");
	}

	/**
	 * 
	 * @param result
	 * @param sp2
	 * @param xc
	 */
	private static void toYaml( StringBuilder result, String sp2, XmlClass xc )
	{
		List im = xc.getIncludedMethods();
		List em = xc.getExcludedMethods();
		String name = im.size() > 0 || em.size() > 0 ? "name: " : "";

		result.append(sp2).append("- " + name).append(xc.getName()).append("\n");
		if (im.size() > 0)
		{
			result.append(sp2 + "  includedMethods:\n");
			for (XmlInclude xi : im)
			{
				toYaml(result, sp2 + "    ", xi);
			}
		}

		if (em.size() > 0)
		{
			result.append(sp2 + "  excludedMethods:\n");
			toYaml(result, sp2 + "    ", em);
		}
	}

	/**
	 * 
	 * @param result
	 * @param sp2
	 * @param xi
	 */
	private static void toYaml( StringBuilder result, String sp2, XmlInclude xi )
	{
		result.append(sp2 + "- " + xi.getName()).append("\n");
	}

	/**
	 * 
	 * @param result
	 * @param sp
	 * @param strings
	 */
	private static void toYaml( StringBuilder result, String sp,
			List strings )
	{
		for (String l : strings)
		{
			result.append(sp).append("- ").append(l).append("\n");
		}
	}

	// private static final String SP = "  ";


	/**
	 * 
	 */
	private static void toYaml( StringBuilder sb, List packages )
	{
		if (packages.size() > 0)
		{
			sb.append("packages:\n");
			for (XmlPackage p : packages)
			{
				toYaml(sb, "  ", p);
			}
		}
		for (XmlPackage p : packages)
		{
			toYaml(sb, "  ", p);
		}
	}

	/**
	 * 
	 * @param sb
	 * @param sp
	 * @param p
	 */
	private static void toYaml( StringBuilder sb, String sp, XmlPackage p )
	{
		sb.append(sp).append("name: ").append(p.getName()).append("\n");

		generateIncludeExclude(sb, sp, "includes", p.getInclude());
		generateIncludeExclude(sb, sp, "excludes", p.getExclude());
	}

	/**
	 * 
	 * @param sb
	 * @param sp
	 * @param key
	 * @param includes
	 */
	private static void generateIncludeExclude( StringBuilder sb, String sp,
												String key, List includes )
	{
		if (includes.size() > 0)
		{
			sb.append(sp).append("  ").append(key).append("\n");
			for (String inc : includes)
			{
				sb.append(sp).append("    ").append(inc);
			}
		}
	}

	/**
	 * 
	 * @param map
	 * @param out
	 */
	private static void mapToYaml( Map map, StringBuilder out )
	{
		if (map.size() > 0)
		{
			out.append("{ ");
			boolean first = true;
			for (Map.Entry e : map.entrySet())
			{
				if (!first)
					out.append(", ");
				first = false;
				out.append(e.getKey() + ": " + e.getValue());
			}
			out.append(" }\n");
		}
	}

	/**
	 * 
	 * @param sb
	 * @param key
	 * @param sp
	 * @param parameters
	 */
	private static void toYaml( StringBuilder sb, String key, String sp,
								Map parameters )
	{
		if (parameters.size() > 0)
		{
			sb.append(sp).append(key).append(": ");
			mapToYaml(parameters, sb);
		}
	}

	/**
	 * 
	 * @param suite
	 * @param name
	 * @param target
	 */
	@SuppressWarnings({ "unused", "unchecked", "rawtypes" })
	private static void addToMap( Map suite, String name, Map target )
	{
		List> parameters = (List>) suite.get(name);
		if (parameters != null)
		{
			for (Map parameter : parameters)
			{
				for (Map.Entry p : parameter.entrySet())
				{
					target.put(p.getKey(), p.getValue().toString());
				}
			}
		}
	}

	/**
	 * 
	 * @param suite
	 * @param name
	 * @param target
	 */
	@SuppressWarnings({ "unused", "unchecked", "rawtypes" })
	private static void addToList( Map suite, String name, List target )
	{
		List> parameters = (List>) suite
				.get(name);
		if (parameters != null)
		{
			for (Map parameter : parameters)
			{
				for (Map.Entry p : parameter.entrySet())
				{
					target.add(p.getValue().toString());
				}
			}
		}
	}

	/**
	 * 
	 * @param filePath
	 * @param is
	 * @return XMLSuite
	 * @throws FileNotFoundException
	 */
	public static XmlSuite parse( String filePath, InputStream is )
	throws FileNotFoundException
	{
		JavaBeanLoader loader = new JavaBeanLoader(XmlSuite.class);
		if (is == null)
		{
			is = new FileInputStream(new File(filePath));
		}
		XmlSuite result = loader.load(new UnicodeReader(is));	// UnicodeReader
																// used to
																// respect BOM
		result.setFileName(filePath);
		// DEBUG
		// System.out.println("[Yaml] " + result.toXml());

		// Adjust XmlTest parents
		for (XmlTest t : result.getTests())
		{
			t.setSuite(result);
		}

		return result;
	}

//	private static void setField( Object xml, Map map, String key,
//			String methodName, Class parameter )
//	{
//		Object o = map.get(key);
//		if (o != null)
//		{
//			Method m;
//			try
//			{
//				m = xml.getClass().getMethod(methodName, parameter);
//				m.invoke(xml, o);
//			} catch (Exception e)
//			{
//				e.printStackTrace();
//			}
//		}
//	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy