alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Groovy example source code file (GroovyTestCase.java)

This example Groovy source code file (GroovyTestCase.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Groovy tags/keywords

class, closure, closure, exception, groovyruntimeexception, log, logging, max_nested_exceptions, method, object, object, reflection, string, string, stringbuffer, throwable, throwable

The Groovy GroovyTestCase.java source code

/*
 * Copyright 2003-2007 the original author or authors.
 *
 * 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 or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package groovy.util;

import groovy.lang.Closure;
import groovy.lang.GroovyRuntimeException;
import groovy.lang.GroovyShell;
import junit.framework.TestCase;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.logging.Logger;

/**
 * A default JUnit TestCase in Groovy. This provides a number of helper methods
 * plus avoids the JUnit restriction of requiring all test* methods to be void
 * return type.
 *
 * @author <a href="mailto:bob@werken.com">bob mcwhirter
 * @author <a href="mailto:james@coredevelopers.net">James Strachan
 * @author Dierk Koenig (the notYetImplemented feature, changes to shouldFail)
 * @version $Revision: 20583 $
 */
public class GroovyTestCase extends TestCase {

    protected static Logger log = Logger.getLogger(GroovyTestCase.class.getName());
    private static int counter;
    private static final int MAX_NESTED_EXCEPTIONS = 10;
    public static final String TEST_SCRIPT_NAME_PREFIX = "TestScript";

    private boolean useAgileDoxNaming = false;

    public GroovyTestCase() {
    }

    /**
     * Overload the getName() method to make the test cases look more like AgileDox
     * (thanks to Joe Walnes for this tip!)
     */
    public String getName() {
        if (useAgileDoxNaming) {
            return super.getName().substring(4).replaceAll("([A-Z])", " $1").toLowerCase();
        } else {
            return super.getName();
        }
    }

    public String getMethodName() {
        return super.getName();
    }

    /**
     * Asserts that the arrays are equivalent and contain the same values
     *
     * @param expected
     * @param value
     */
    protected void assertArrayEquals(Object[] expected, Object[] value) {
        String message =
                "expected array: " + InvokerHelper.toString(expected) + " value array: " + InvokerHelper.toString(value);
        assertNotNull(message + ": expected should not be null", expected);
        assertNotNull(message + ": value should not be null", value);
        assertEquals(message, expected.length, value.length);
        for (int i = 0, size = expected.length; i < size; i++) {
            assertEquals("value[" + i + "] when " + message, expected[i], value[i]);
        }
    }

    /**
     * Asserts that the array of characters has a given length
     *
     * @param length expected length
     * @param array  the array
     */
    protected void assertLength(int length, char[] array) {
        assertEquals(length, array.length);
    }

    /**
     * Asserts that the array of ints has a given length
     *
     * @param length expected length
     * @param array  the array
     */
    protected void assertLength(int length, int[] array) {
        assertEquals(length, array.length);
    }

    /**
     * Asserts that the array of objects has a given length
     *
     * @param length expected length
     * @param array  the array
     */
    protected void assertLength(int length, Object[] array) {
        assertEquals(length, array.length);
    }

    /**
     * Asserts that the array of characters contains a given char
     *
     * @param expected expected character to be found
     * @param array    the array
     */
    protected void assertContains(char expected, char[] array) {
        for (int i = 0; i < array.length; ++i) {
            if (array[i] == expected) {
                return;
            }
        }

        StringBuffer message = new StringBuffer();

        message.append(expected).append(" not in {");

        for (int i = 0; i < array.length; ++i) {
            message.append("'").append(array[i]).append("'");

            if (i < (array.length - 1)) {
                message.append(", ");
            }
        }

        message.append(" }");

        fail(message.toString());
    }

    /**
     * Asserts that the array of ints contains a given int
     *
     * @param expected expected int
     * @param array    the array
     */
    protected void assertContains(int expected, int[] array) {
        for (int anInt : array) {
            if (anInt == expected) {
                return;
            }
        }

        StringBuffer message = new StringBuffer();

        message.append(expected).append(" not in {");

        for (int i = 0; i < array.length; ++i) {
            message.append("'").append(array[i]).append("'");

            if (i < (array.length - 1)) {
                message.append(", ");
            }
        }

        message.append(" }");

        fail(message.toString());
    }

    /**
     * Asserts that the value of toString() on the given object matches the
     * given text string
     *
     * @param value    the object to be output to the console
     * @param expected the expected String representation
     */
    protected void assertToString(Object value, String expected) {
        Object console = InvokerHelper.invokeMethod(value, "toString", null);
        assertEquals("toString() on value: " + value, expected, console);
    }

    /**
     * Asserts that the value of inspect() on the given object matches the
     * given text string
     *
     * @param value    the object to be output to the console
     * @param expected the expected String representation
     */
    protected void assertInspect(Object value, String expected) {
        Object console = InvokerHelper.invokeMethod(value, "inspect", null);
        assertEquals("inspect() on value: " + value, expected, console);
    }

    /**
     * Asserts that the script runs without any exceptions
     *
     * @param script the script that should pass without any exception thrown
     */
    protected void assertScript(final String script) throws Exception {
        GroovyShell shell = new GroovyShell();
        shell.evaluate(script, getTestClassName());
    }

    protected String getTestClassName() {
        return TEST_SCRIPT_NAME_PREFIX + getMethodName() + (counter++) + ".groovy";
    }

    /**
     * Asserts that the given code closure fails when it is evaluated
     *
     * @param code
     * @return the message of the thrown Throwable
     */
    protected String shouldFail(Closure code) {
        boolean failed = false;
        String result = null;
        try {
            code.call();
        }
        catch (GroovyRuntimeException gre) {
            failed = true;
            result = ScriptBytecodeAdapter.unwrap(gre).getMessage();
        }
        catch (Throwable e) {
            failed = true;
            result = e.getMessage();
        }
        assertTrue("Closure " + code + " should have failed", failed);
        return result;
    }

    /**
     * Asserts that the given code closure fails when it is evaluated
     * and that a particular exception is thrown.
     *
     * @param clazz the class of the expected exception
     * @param code  the closure that should fail
     * @return the message of the expected Throwable
     */
    protected String shouldFail(Class clazz, Closure code) {
        Throwable th = null;
        try {
            code.call();
        } catch (GroovyRuntimeException gre) {
            th = ScriptBytecodeAdapter.unwrap(gre);
        } catch (Throwable e) {
            th = e;
        }

        if (th == null) {
            fail("Closure " + code + " should have failed with an exception of type " + clazz.getName());
        } else if (!clazz.isInstance(th)) {
            fail("Closure " + code + " should have failed with an exception of type " + clazz.getName() + ", instead got Exception " + th);
        }
        return th.getMessage();
    }

    /**
     * Asserts that the given code closure fails when it is evaluated
     * and that a particular exception can be attributed to the cause.
     * The expected exception class is compared recursively with any nested
     * exceptions using getCause() until either a match is found or no more
     * nested exceptions exist.
     * <p/>
     * If a match is found the error message associated with the matching
     * exception is returned. If no match was found the method will fail.
     *
     * @param clazz the class of the expected exception
     * @param code  the closure that should fail
     * @return the message of the expected Throwable
     */
    protected String shouldFailWithCause(Class clazz, Closure code) {
        Throwable th = null;
        Throwable orig = null;
        int level = 0;
        try {
            code.call();
        } catch (GroovyRuntimeException gre) {
            orig = ScriptBytecodeAdapter.unwrap(gre);
            th = orig.getCause();
        } catch (Throwable e) {
            orig = e;
            th = orig.getCause();
        }

        while (th != null && !clazz.isInstance(th) && th != th.getCause() && level < MAX_NESTED_EXCEPTIONS) {
            th = th.getCause();
            level++;
        }

        if (orig == null) {
            fail("Closure " + code + " should have failed with an exception caused by type " + clazz.getName());
        } else if (th == null || !clazz.isInstance(th)) {
            fail("Closure " + code + " should have failed with an exception caused by type " + clazz.getName() + ", instead found these Exceptions:\n" + buildExceptionList(orig));
        }
        return th.getMessage();
    }

    private String buildExceptionList(Throwable th) {
        StringBuilder sb = new StringBuilder();
        int level = 0;
        while (th != null) {
            if (level > 1) {
                for (int i = 0; i < level - 1; i++) sb.append("   ");
            }
            if (level > 0) sb.append("-> ");
            if (level > MAX_NESTED_EXCEPTIONS) {
                sb.append("...");
                break;
            }
            sb.append(th.getClass().getName()).append(": ").append(th.getMessage()).append("\n");
            if (th == th.getCause()) {
                break;
            }
            th = th.getCause();
            level++;
        }
        return sb.toString();
    }

    /**
     * Returns a copy of a string in which all EOLs are \n.
     */
    protected String fixEOLs(String value) {
        return value.replaceAll("(\\r\\n?)|\n", "\n");
    }

    /**
     * Runs the calling JUnit test again and fails only if it unexpectedly runs.<br/>
     * This is helpful for tests that don't currently work but should work one day,
     * when the tested functionality has been implemented.<br/>
     * The right way to use it is:
     * <pre>
     * public void testXXX() {
     *   if (GroovyTestCase.notYetImplemented(this)) return;
     *   ... the real (now failing) unit test
     * }
     * </pre>
     * Idea copied from HtmlUnit (many thanks to Marc Guillemot).
     * Future versions maybe available in the JUnit distro.
     * The purpose of providing a 'static' version is such that you can use the
     * feature even if not subclassing GroovyTestCase.
     *
     * @return <false> when not itself already in the call stack
     */
    public static boolean notYetImplemented(TestCase caller) {
        if (notYetImplementedFlag.get() != null) {
            return false;
        }
        notYetImplementedFlag.set(Boolean.TRUE);

        final Method testMethod = findRunningJUnitTestMethod(caller.getClass());
        try {
            log.info("Running " + testMethod.getName() + " as not yet implemented");
            testMethod.invoke(caller, (Object[]) new Class[]{});
            fail(testMethod.getName() + " is marked as not yet implemented but passes unexpectedly");
        }
        catch (final Exception e) {
            log.info(testMethod.getName() + " fails which is expected as it is not yet implemented");
            // method execution failed, it is really "not yet implemented"
        }
        finally {
            notYetImplementedFlag.set(null);
        }
        return true;
    }

    /**
     * Convenience method for subclasses of GroovyTestCase, identical to
     * <pre> GroovyTestCase.notYetImplemented(this); 
. * * @return <false> when not itself already in the call stack * @see #notYetImplemented(junit.framework.TestCase) */ public boolean notYetImplemented() { return notYetImplemented(this); } /** * From JUnit. Finds from the call stack the active running JUnit test case * * @return the test case method * @throws RuntimeException if no method could be found. */ private static Method findRunningJUnitTestMethod(Class caller) { final Class[] args = new Class[]{}; // search the initial junit test final Throwable t = new Exception(); for (int i = t.getStackTrace().length - 1; i >= 0; --i) { final StackTraceElement element = t.getStackTrace()[i]; if (element.getClassName().equals(caller.getName())) { try { final Method m = caller.getMethod(element.getMethodName(), args); if (isPublicTestMethod(m)) { return m; } } catch (final Exception e) { // can't access, ignore it } } } throw new RuntimeException("No JUnit test case method found in call stack"); } /** * From Junit. Test if the method is a junit test. * * @param method the method * @return <code>true if this is a junit test. */ private static boolean isPublicTestMethod(final Method method) { final String name = method.getName(); final Class[] parameters = method.getParameterTypes(); final Class returnType = method.getReturnType(); return parameters.length == 0 && name.startsWith("test") && returnType.equals(Void.TYPE) && Modifier.isPublic(method.getModifiers()); } public static void assertEquals(String message, Object expected, Object actual) { if (expected == null && actual == null) return; if (expected != null && DefaultTypeTransformation.compareEqual(expected, actual)) return; failNotEquals(message, expected, actual); } public static void assertEquals(Object expected, Object actual) { assertEquals(null, expected, actual); } public static void assertEquals(String expected, String actual) { assertEquals(null, expected, actual); } private static final ThreadLocal notYetImplementedFlag = new ThreadLocal(); }

Other Groovy examples (source code examples)

Here is a short list of links related to this Groovy GroovyTestCase.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.