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

patterntesting.runtime.junit.internal.ProfiledStatement Maven / Gradle / Ivy

Go to download

PatternTesting Runtime (patterntesting-rt) is the runtime component for the PatternTesting framework. It provides the annotations and base classes for the PatternTesting testing framework (e.g. patterntesting-check, patterntesting-concurrent or patterntesting-exception) but can be also used standalone for classpath monitoring or profiling. It uses AOP and AspectJ to perform this feat.

There is a newer version: 2.4.0
Show newest version
/*
 * $Id: ProfiledStatement.java,v 1.8 2014/04/28 14:56:48 oboehm Exp $
 *
 * Copyright (c) 2010 by Oliver Boehm
 *
 * 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 orimplied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * (c)reated 29.03.2010 by oliver ([email protected])
 */

package patterntesting.runtime.junit.internal;

import java.lang.reflect.*;
import java.util.List;

import junit.framework.TestCase;

import org.junit.*;
import org.junit.Test.None;
import org.junit.runners.model.*;
import org.slf4j.*;

import patterntesting.annotation.check.runtime.MayReturnNull;

/**
 * The ProfiledStatement measures also the time the different setUp() and
 * tearDown() methods need. In contradiction to the original JUnit statement
 * this statement is not only a wrapper around the test method but contains
 * also the setUp and tearDown methods. And it is able to handle JUnit4
 * and JUnit3 methods.
 *
 * @author oliver
 * @since 1.0 (29.03.2010)
 */
public class ProfiledStatement extends Statement {

    private static final Logger log = LoggerFactory.getLogger(ProfiledStatement.class);
    private final TestClass testClass;
    private final FrameworkMethod frameworkMethod;
    private long startTime;
    private long startTimeTest;
    private long startTimeAfters;
    private long endTime;

    /**
     * The default constructor for this class if the call of the
     * frameworkMethod is ok.
     *
     * @param testClass the test class
     * @param frameworkMethod the FrameworkMethod
     */
    public ProfiledStatement(final TestClass testClass, final FrameworkMethod frameworkMethod) {
        this.testClass = testClass;
        this.frameworkMethod = frameworkMethod;
    }

    /**
     * May be needed by some subclasses.
     * @return the method name
     */
    protected final String getMethodName() {
        return this.frameworkMethod.getName();
    }

    /**
     * Invokes the test method.
     *
     * @throws Throwable the throwable
     * @see org.junit.runners.model.Statement#evaluate()
     */
    @Override
    public void evaluate() throws Throwable {
        Object target = testClass.getOnlyConstructor().newInstance();
        try {
            this.startTimer();
            invokeBefores(target);
            this.startTestTimer();
            invokeTest(target);
            this.startAftersTimer();
            invokeAfters(target);
        } catch (InvocationTargetException ite) {
            Throwable targetException = ite.getTargetException();
            if (targetException == null) {
                throw ite;
            }
            throw targetException;
        } finally {
            if (this.startTimeTest == 0) {
                this.startTestTimer();
            }
            if (this.startTimeAfters == 0) {
                this.startAftersTimer();
            }
            this.endTimer();
        }
    }

    /**
     * We do not only call the test here but check if an excpected exception
     * appears or not.
     *
     * @param target the test target
     * @throws Throwable thrown by the test method
     */
    private void invokeTest(final Object target) throws Throwable {
        Class expected = getExpectedException();
        try {
            frameworkMethod.invokeExplosively(target);
            if ((expected != null) && (expected != None.class)) {
                throw new AssertionError("Expected exception: "
                        + expected.getName());
            }
        } catch (Throwable t) {         //NOSONAR
            if ((expected != null) && (expected != None.class)
                    && (expected.isAssignableFrom(t.getClass()))) {
                log.debug("expected exception appears", t);
                return;
            }
            throw t;
        }
    }

    @MayReturnNull
    private Class getExpectedException() {
        Test test = frameworkMethod.getAnnotation(Test.class);
        if (test == null) {
            return None.class;
        }
        return test.expected();
    }

    /**
     * Here we invoke all setUp() methods.
     * @param target the instantiated JUnit test
     * @throws Throwable if setUp method has a problem
     */
    private void invokeBefores(final Object target) throws Throwable {
        if (ProfiledStatement.isTestCaseClass(testClass)) {
            invoke("setUp", target);
        } else {
            List befores = testClass.getAnnotatedMethods(Before.class);
            invoke(befores, target);
        }
    }

    /**
     * Here we invoke all tearDown() methods.
     * @param stmt the recorded statement
     * @throws Throwable if tearDown method has a problem
     */
    private void invokeAfters(final Object target) throws Throwable {
        if (ProfiledStatement.isTestCaseClass(testClass)) {
            invoke("tearDown", target);
        } else {
            List afters = testClass.getAnnotatedMethods(After.class);
            invoke(afters, target);
        }
    }

    private void invoke(final String methodName, final Object target)
            throws Throwable {
        FrameworkMethod method = JUnitHelper.getFrameworkMethod(testClass.getJavaClass(), methodName);
        if (method != null) {
            invoke(method, target);
        }
    }

    private void invoke(final FrameworkMethod fwkMethod, final Object target)
            throws Throwable {
        try {
            fwkMethod.invokeExplosively(target);
        } catch (IllegalAccessException e) {
            invokeProtected(fwkMethod, target);
        } catch (InvocationTargetException e) {
            throw getThrowableFor(fwkMethod, e);
        }
    }

    private void invokeProtected(final FrameworkMethod fwkMethod,
            final Object target) throws Throwable {
        Method method = fwkMethod.getMethod();
        method.setAccessible(true);
        try {
            method.invoke(target);
        } catch (IllegalAccessException e) {
            throw getAssertionErrorFor(fwkMethod, e);
        } catch (InvocationTargetException e) {
            throw getThrowableFor(fwkMethod, e);
        }
    }

    private void invoke(final List fwkMethods,
            final Object target) throws Throwable {
        for (FrameworkMethod fwkMethod : fwkMethods) {
            invoke(fwkMethod, target);
        }
    }

    private AssertionError getAssertionErrorFor(final FrameworkMethod method, final Throwable t) {
        String detailedMessage = "invoke of " + method.getName()
                + "() failed\n" + t;
        return new AssertionError(detailedMessage);
    }

    private Throwable getThrowableFor(final FrameworkMethod fwkMethod,
            final InvocationTargetException e) throws AssertionError {
        Throwable t = e.getTargetException();
        if (t == null) {
            throw getAssertionErrorFor(fwkMethod, e);
        }
        return t;
    }

    /**
     * Here we start the timer when the first setUp() method was called.
     */
    public final void startTimer() {
        this.startTime = System.currentTimeMillis();
    }

    /**
     * Here we start the timer when the test method was called.
     */
    public final void startTestTimer() {
        this.startTimeTest = System.currentTimeMillis();
    }

    /**
     * Here we start the timer when the first tearDown() method was called.
     */
    public final void startAftersTimer() {
        this.startTimeAfters = System.currentTimeMillis();
    }

    /**
     * The timer should end after the last tearDown() method was called.
     */
    public final void endTimer() {
        this.endTime = System.currentTimeMillis();
    }

    /**
     * Returns the name of the method with the measured times.
     *
     * @return the framework method with the measured times
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return this.testClass.getName() + "." + this.frameworkMethod.getName()
                + " (" + (this.startTimeTest - this.startTime) + "+"
                + (this.startTimeAfters - this.startTimeTest) + "+"
                + (this.endTime - this.startTimeAfters) + " ms)";
    }

    /**
     * @param testClass the test class
     * @return true if testClass is derived from TestCase
     */
    public static boolean isTestCaseClass(final TestClass testClass) {
        return TestCase.class.isAssignableFrom(testClass.getJavaClass());
    }

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy