org.paxml.testng.AbstractPaxmlTestResult.java Source code

Java tutorial

Introduction

Here is the source code for org.paxml.testng.AbstractPaxmlTestResult.java

Source

/**
 * This file is part of PaxmlTestNG.
 *
 * PaxmlTestNG is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PaxmlTestNG is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with PaxmlTestNG.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.paxml.testng;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.paxml.core.Context;
import org.paxml.core.Context.Stack.IStackTraverser;
import org.paxml.core.IEntity;
import org.paxml.selenium.rc.SeleniumTag;
import org.paxml.selenium.rc.SeleniumHelper;
import org.paxml.selenium.rc.SeleniumHelper.SnapshotInfo;
import org.paxml.tag.ITag;
import org.paxml.testng.PaxmlTestCaseFactory.ILockedOperation;
import org.paxml.util.XmlUtils;
import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;

/**
 * paxml test case impl for testNG.
 * 
 * @author Xuetao Niu
 * 
 */
public abstract class AbstractPaxmlTestResult {

    public static enum ResultType {
        JSON("js"), XML("xml");

        private final String ext;

        private ResultType(String ext) {
            this.ext = ext;
        }

        public String getExt() {
            return ext;
        }

    }

    private static final Log log = LogFactory.getLog(AbstractPaxmlTestResult.class);

    private final long processId;
    private final File outputDir;
    private final ResultType resultType;
    private final String entityName;
    private final String group;
    private boolean success = false;
    private final Map<?, ?> initialProps;

    /**
     * Construct from factors.
     * 
     * @param point
     *            the launch point
     * 
     */
    public AbstractPaxmlTestResult(String group, String entityName, long processId, File outputDir,
            ResultType resultType, Map<?, ?> initialProps) {

        if (resultType == null) {
            resultType = ResultType.JSON;
        }
        this.group = group;
        this.initialProps = initialProps;
        this.entityName = entityName;
        this.resultType = resultType;
        this.outputDir = outputDir;
        this.processId = processId;

    }

    @Override
    public String toString() {
        return getClass().getName() + ":" + getProcessId();
    }

    protected void addMap(Map<?, ?> map, List<Const> consts) {
        for (Map.Entry<?, ?> entry : map.entrySet()) {
            Const c = new Const();
            c.setName(String.valueOf(entry.getKey()));
            Object value = entry.getValue();
            c.setValue(String.valueOf(value));
            if (value != null) {
                c.setType(value.getClass().getName());
            }
            consts.add(c);
        }
        Collections.sort(consts, new Comparator<Const>() {

            @Override
            public int compare(Const o1, Const o2) {
                return o1.getName().compareTo(o2.getName());
            }

        });
    }

    protected abstract Context getContext();

    protected abstract void onSummary(TestResultSummary s);

    protected abstract void doTest() throws Throwable;

    protected abstract String getThreadName();

    protected abstract long getStartMs();

    protected abstract long getStopMs();

    @Test
    public void executeTest() throws Throwable {
        doTest();
        success = true;
    }

    @AfterMethod
    public void populateReport(final ITestResult result) throws Exception {
        try {
            PaxmlTestCaseFactory.performLocked(new ILockedOperation<Object>() {

                @Override
                public Object perform() {
                    try {
                        doPopulateReport(result);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    return null;
                }

            });
        } catch (Throwable t) {
            log.error("Cannot generate test result", t);
        }
    }

    private void doPopulateReport(ITestResult result) throws Exception {

        final Context context = getContext();
        final Context exceptionContext = context == null ? null : context.getExceptionContext();

        final TestResultSummary s = new TestResultSummary();

        try {
            final TestResult r = new TestResult();

            r.setProcessId(processId);
            r.setEntityName(entityName);
            r.setGroup(group);
            r.setThreadName(getThreadName());
            r.setSuccessful(success);
            r.setStart(getStartMs());
            r.setStop(getStopMs());

            s.setProcessId(r.getProcessId());
            s.setGroup(r.getGroup());
            s.setEntityName(r.getEntityName());
            s.setThreadName(r.getThreadName());
            s.setSuccessful(r.isSuccessful());
            s.setStart(r.getStart());
            s.setStop(r.getStop());

            ContextDump dump = new ContextDump();
            r.setContextDump(dump);

            for (SnapshotInfo si : SeleniumHelper.getSnapshots(context)) {
                ScreenshotInfo info = new ScreenshotInfo();
                r.getScreenshots().add(info);
                info.setFileName(si.getFile().getName());

                for (SeleniumHelper.CallStack cs : si.getCallStack()) {
                    CallStack _cs = new CallStack();
                    _cs.setEntityName(cs.getEntity().getResource().getName());
                    _cs.setTagName(cs.getTag().getTagName());
                    _cs.setLine(cs.getTag().getLineNumber());
                    info.getCallStack().add(_cs);
                }

            }

            addMap(System.getProperties(), r.getSystemProperties());

            if (initialProps != null) {
                addMap(initialProps, r.getInitialProperties());
                s.getInitialProperties().addAll(r.getInitialProperties());
            }

            if (success) {
                if (context != null) {
                    addMap(context.getIdMap(true, false), dump.getContextValue());
                }
            } else {
                r.setErrorMessage(result.getThrowable().getMessage());
                s.setErrorMessage(r.getErrorMessage());
                if (exceptionContext != null) {
                    addMap(exceptionContext.getIdMap(true, false), dump.getContextValue());

                    final File file = SeleniumTag.getErrorSnapshot(exceptionContext);
                    if (file != null) {
                        r.setErrorScreenshotName(file.getName());
                    } else {
                        if (log.isWarnEnabled()) {
                            log.warn(getTitle()
                                    + " failed but has no selenium snapshots attached. It may have failed before opening the browser.");
                        }
                    }

                    // compose error stack
                    exceptionContext.getStack().traverse(new IStackTraverser() {

                        @Override
                        public boolean onItem(IEntity entity, ITag tag) {
                            CallStack c = new CallStack();
                            r.getErrorStack().add(c);
                            c.setLine(tag.getLineNumber());
                            c.setEntityName(entity.getResource().getName());
                            c.setTagName(tag.getTagName());
                            return true;
                        }
                    });
                }
            }

            // write the log detached to from the current test case.
            Context.cleanCurrentThreadContext();

            writeReportFile(r, false);
        } finally {
            onSummary(s);
        }
    }

    public long getProcessId() {
        return processId;
    }

    public File getOutputDir() {
        return outputDir;
    }

    public ResultType getResultType() {
        return resultType;
    }

    public String getEntityName() {
        return entityName;
    }

    public String getTitle() {
        return processId + ":" + entityName + "@" + getThreadName();
    }

    public File writeReportFile(Object tr, boolean index) {
        String str = null;
        if (resultType == ResultType.JSON) {
            str = XmlUtils.toJson(tr);
        } else if (resultType == ResultType.XML) {
            str = serializeXml(tr);
        } else {
            throw new RuntimeException("Unknown result type: " + resultType);
        }
        if (null != outputDir) {
            final String fn = index ? "index" : new Long(processId).toString();
            final File file = new File(outputDir, fn + "." + resultType.getExt());
            if (log.isInfoEnabled()) {
                if (index) {
                    log.info("Outputting test result index to: " + file.getAbsolutePath());
                } else {
                    log.info("Outputting test result to: " + file.getAbsolutePath());

                }

            }

            outputDir.mkdirs();
            try {
                FileUtils.writeStringToFile(file, str, "UTF-8");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            return file;
        } else {
            if (log.isWarnEnabled()) {
                if (index) {
                    log.warn("No output dir specified, therefore no test result index file will be saved.");
                } else {
                    log.warn(
                            "No output dir specified, therefore no test result file will be saved after each test case.");

                }

            }
            return null;
        }

    }

    public static String serializeXml(Object obj) {
        final String encoding = "UTF-8";
        try {
            JAXBContext c = JAXBContext.newInstance(obj.getClass());
            Marshaller m = c.createMarshaller();
            m.setProperty(Marshaller.JAXB_ENCODING, encoding);
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

            ByteArrayOutputStream out = new ByteArrayOutputStream();
            m.marshal(obj, out);
            return out.toString(encoding);
        } catch (Exception e) {
            throw new RuntimeException("Cannot serialize jaxb object of class: " + obj.getClass(), e);
        }
    }

}