org.grails.ide.eclipse.test.Grails20JUnitIntegrationTests.java Source code

Java tutorial

Introduction

Here is the source code for org.grails.ide.eclipse.test.Grails20JUnitIntegrationTests.java

Source

/*******************************************************************************
 * Copyright (c) 2012 VMWare, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     VMWare, Inc. - initial API and implementation
 *******************************************************************************/
package org.grails.ide.eclipse.test;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URLClassLoader;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.junit.launcher.ITestFinder;
import org.eclipse.jdt.internal.junit.model.TestRunSession;
import org.eclipse.jdt.launching.JavaRuntime;
import org.grails.ide.eclipse.commands.GrailsCommand;
import org.grails.ide.eclipse.commands.GrailsCommandFactory;
import org.grails.ide.eclipse.core.junit.Grails20AwareTestFinder;
import org.grails.ide.eclipse.core.launch.SynchLaunch.ILaunchResult;
import org.grails.ide.eclipse.core.model.GrailsVersion;
import org.osgi.framework.Bundle;
import org.springsource.ide.eclipse.commons.tests.util.StsTestUtil;
import org.grails.ide.eclipse.test.util.AbstractGrailsJUnitIntegrationsTest;
import org.grails.ide.eclipse.test.util.GrailsTest;

/**
 * Tests for the 'run as >> Junit test' functionality provided by JDT. We are testing here whether
 * our hackery intended to make it work with Grails 2.0 actually does what it is intended to do,
 * while not breaking JUnit 3 style test finding and running.
 * 
 * @author Kris De Volder
 *
 * @since 2.9
 */
public class Grails20JUnitIntegrationTests extends AbstractGrailsJUnitIntegrationsTest {

    public final String TEST_PROJECT_NAME = this.getClass().getSimpleName();
    private IProject project;
    private IJavaProject javaProject;

    private String packageName; // name of the package most classes are in
    private String domainClassName; // name of the single domain class present in the 'base-line' test application.
    private String testDomainClassName; // name of the test class containing tests for the domain class.
    private String domainClassBaseName;
    private String generatedTestMethodName;

    private static boolean domainClassCreated = false;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        assertTrue("This test assumes Grails 20 but most recent Grails version is " + GrailsVersion.MOST_RECENT,
                GrailsVersion.MOST_RECENT.compareTo(GrailsVersion.V_2_0_0) >= 0);
        ensureDefaultGrailsVersion(GrailsVersion.MOST_RECENT);
        setJava17Compliance();

        project = ensureProject(TEST_PROJECT_NAME);
        javaProject = JavaCore.create(project);

        //Add a generated domain class to make the base-line test project a bit more interesting.
        packageName = TEST_PROJECT_NAME.toLowerCase();
        domainClassBaseName = "Song";
        domainClassName = packageName + "." + domainClassBaseName;
        if (!domainClassCreated) {
            GrailsCommand cmd = GrailsCommandFactory.createDomainClass(project, domainClassName);
            ILaunchResult result = cmd.synchExec();
            System.out.println(result.getOutput());
            project.refreshLocal(IResource.DEPTH_INFINITE, null);
            domainClassCreated = true;
        }

        if (GrailsVersion.MOST_RECENT.compareTo(GrailsVersion.V_2_3_) >= 0) {
            testDomainClassName = domainClassName + "Spec";
            generatedTestMethodName = "test something";
            //Replace generated 2.3.0 spock test with a test that actually has some test code in it.
            createResource(project, "test/unit/grails20junitintegrationtests/SongSpec.groovy",
                    "package grails20junitintegrationtests\n" + "\n" + "import grails.test.mixin.TestFor\n"
                            + "import spock.lang.Specification\n" + "\n" + "/**\n"
                            + " * See the API for {@link grails.test.mixin.domain.DomainClassUnitTestMixin} for usage instructions\n"
                            + " */\n" + "@TestFor(Song)\n" + "class SongSpec extends Specification {\n" + "\n"
                            + "    def setup() {\n" + "    }\n" + "\n" + "    def cleanup() {\n" + "    }\n" + "\n"
                            + "    void \"test something\"() {\n"
                            + "      expect: \"Implement me\"==\"not implemented\"\n" + "    }\n" + "}\n");
            //Ensure project gets built with new SongSpec class.
            StsTestUtil.assertNoErrors(project);
        } else {
            testDomainClassName = domainClassName + "Tests";
            generatedTestMethodName = "testSomething";
        }
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
    }

    public void testScaffolding() throws Exception {
        StsTestUtil.assertNoErrors(project);
    }

    public void testOurTestFinderIsInstalled() {
        ITestFinder finder = getJUnit4TestFinder();
        assertTrue(finder instanceof Grails20AwareTestFinder);
    }

    //   /**
    //    * For some unkown reason, JUnit 4 classpath container isn't resolving on the build server.
    //    * This test is trying to determine why. It does so by using a local copy of the P2Utils class
    //    * that is used by the JUnit support in jdt to find the junit 4 bundle and extract a jar file location from it.
    //    */
    //   public void testJUnit4BundlesAndStuff() throws Exception {
    //      IClasspathEntry junit4lib = BuildPathSupport.getJUnit4LibraryEntry();
    //      System.out.println("Junit 4 library entry = "+junit4lib);
    //      
    //      BundleInfo bundleInfo = P2Utils.findBundle("org.junit", new VersionRange("[4.7.0,5.0.0)"), false);
    //      System.out.println("bundleInfo = "+bundleInfo); //Example of what we expect: BundleInfo(org.junit, 4.8.2.v4_8_2_v20110321-1705, location=file:/home/kdvolder/Applications/springsource-2.9.0.M1/sts-2.9.0.M1/plugins/org.junit_4.8.2.v4_8_2_v20110321-1705/, startLevel=4, toBeStarted=false, resolved=false, id=-1,no manifest)
    //      
    //      IPath bundleLocation = P2Utils.getBundleLocationPath(bundleInfo);
    //      System.out.println("bundle location = "+bundleLocation);
    //      
    //      assertNotNull(bundleLocation);
    //      
    //      //What this test is printing on my machine (where the JUnit tests are passing ok)
    //      /*
    //       Junit 4 library entry = /home/kdvolder/Applications/springsource-2.9.0.M1/sts-2.9.0.M1/plugins/org.junit_4.8.2.v4_8_2_v20110321-1705/junit.jar[CPE_LIBRARY][K_BINARY][sourcePath:/home/kdvolder/Applications/springsource-2.9.0.M1/sts-2.9.0.M1/plugins/org.junit.source_4.8.2.v4_8_2_v20110321-1705.jar][isExported:false][attributes:javadoc_location=https://www.junit.org/junit/javadoc/4.5]
    //       bundleInfo = BundleInfo(org.junit, 4.8.2.v4_8_2_v20110321-1705, location=file:/home/kdvolder/Applications/springsource-2.9.0.M1/sts-2.9.0.M1/plugins/org.junit_4.8.2.v4_8_2_v20110321-1705/, startLevel=4, toBeStarted=false, resolved=false, id=-1,no manifest)
    //         /home/kdvolder/Applications/springsource-2.9.0.M1/sts-2.9.0.M1/plugins/org.junit_4.8.2.v4_8_2_v20110321-1705/
    //       */
    //   }

    /**
     * Test whether test finder still works for a pretty standard JDT Java project.
     */
    public void testDontBreakJDT() throws Exception {
        ITestFinder testFinder = getJUnit4TestFinder();

        IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("sts2312");
        project.create(new NullProgressMonitor());
        project.open(new NullProgressMonitor());

        IProjectDescription desc = project.getDescription();
        String[] natures = desc.getNatureIds();
        String[] newNatures = new String[natures.length + 1];
        System.arraycopy(natures, 0, newNatures, 0, natures.length);
        newNatures[natures.length] = JavaCore.NATURE_ID;
        desc.setNatureIds(newNatures);
        project.setDescription(desc, new NullProgressMonitor());

        javaProject = JavaCore.create(project);

        IPath outputLocation = new Path("/" + project.getName() + "/bin");
        IClasspathEntry[] entries = new IClasspathEntry[] {
                JavaCore.newContainerEntry(JavaRuntime.newDefaultJREContainerPath()), getJUnit4JarEntry(),
                JavaCore.newSourceEntry(new Path("/" + project.getName() + "/src")),
                JavaCore.newSourceEntry(new Path("/" + project.getName() + "/test")), };
        javaProject.setRawClasspath(entries, outputLocation, new NullProgressMonitor());

        createResource(project, "src/foo/Main.java",
                "package foo;\n" + "public class Main {\n" + "  public static void main(String[] args) {\n"
                        + "    System.out.println(\"Hello\");\n" + "  }" + "}");

        createResource(project, "test/foo/Test1.java",
                "package foo;\n" + "\n" + "import junit.framework.TestCase;\n" + "\n"
                        + "public class Test1 extends TestCase {\n"
                        + "  public void testSomething(String[] args) {\n" + "    System.out.println(\"Hello\");\n"
                        + "  }" + "}");

        createResource(project, "src/foo/Test2.java",
                "package foo;\n" + "\n" + "import junit.framework.TestCase;\n" + "\n"
                        + "public class Test2 extends TestCase {\n"
                        + "  public void testSomething(String[] args) {\n" + "    System.out.println(\"Hello\");\n"
                        + "  }" + "}");

        StsTestUtil.dumpClasspathInfo(javaProject);

        StsTestUtil.assertNoErrors(project);
        IType test1 = javaProject.findType("foo.Test1");
        IType test2 = javaProject.findType("foo.Test2");

        assertNotNull(test1);
        assertNotNull(test2);
        assertTrue(testFinder.isTest(test1));
        assertTrue(testFinder.isTest(test2));
        { // find in project
            HashSet result = new HashSet();
            testFinder.findTestsInContainer(javaProject, result, new NullProgressMonitor());
            assertElements(result, test1, test2);
        }
        { //find in type
            HashSet result = new HashSet();
            testFinder.findTestsInContainer(test1, result, new NullProgressMonitor());
            assertElements(result, test1);
        }
        { //find in type
            HashSet result = new HashSet();
            testFinder.findTestsInContainer(test2, result, new NullProgressMonitor());
            assertElements(result, test2);
        }
    }

    private IClasspathEntry getJUnit4JarEntry() throws IOException {
        Bundle[] bundles = Platform.getBundles("org.junit", "4.7.0");
        File bundleFile = FileLocator.getBundleFile(bundles[0]);
        assertTrue("bundleFile doesn't exist: " + bundleFile, bundleFile.exists());
        assertTrue("bundleFile isn't a directory: " + bundleFile, bundleFile.isDirectory());
        for (File file : bundleFile.listFiles()) {
            if (file.getName().equals("junit.jar")) {
                return JavaCore.newLibraryEntry(new Path(file.toString()), null, null, true);
            }
        }
        fail("Couldn't find Junit jar file");
        return null; //unreachable code
    }

    /**
     * Test basic function of the 'isTest' method in the test finder:
     *   - a domain class isn't a test
     *   - a class in the test/unit source folder is a test
     *    
     * @throws Exception
     */
    public void testTestFinderIsTest() throws Exception {
        ITestFinder testFinder = getJUnit4TestFinder();

        IType domainClass = javaProject.findType(domainClassName);
        assertNotNull(domainClass);
        assertFalse(testFinder.isTest(domainClass));

        IType testClass = javaProject.findType(testDomainClassName);
        assertNotNull(testClass);
        assertTrue(testFinder.isTest(testClass));

        createTmpResource(project, "test/integration/" + packageName + "/FoobarTests.groovy",
                "package grails20junitintegrationtests\n" + "\n" + "import grails.test.mixin.*\n" + "\n"
                        + "@TestFor(" + domainClassBaseName + ")\n" + "class FoobarTests {\n" + "\n"
                        + "   void testThisAndThat() {\n" + "      assertEquals 4, 4\n" + "   }\n" + "   \n" + "}");
        StsTestUtil.waitForAutoBuild();

        IType integTests = javaProject.findType(packageName + ".FoobarTests");
        assertNotNull(integTests);
        assertTrue(testFinder.isTest(integTests));
    }

    /**
     * Test slightly more 'advanced' cases. 
     *  - a helper class present in the unit testing source folder shouldn't be
     *    recognized as a test class.
     *  
     * @throws Exception
     */
    public void testTestFinderIsTest2() throws Exception {
        ITestFinder testFinder = getJUnit4TestFinder();

        createTmpResource(project, "test/unit/" + packageName + "/Helper.groovy",
                "package " + packageName + "\n" + "\n" + "class Helper {\n" + "\n" + "   void help() {\n"
                        + "      println 'help!'\n" + "   }\n" + "}");
        StsTestUtil.waitForAutoBuild();
        IType clazz = javaProject.findType(packageName + ".Helper");
        assertNotNull(clazz);
        assertFalse(testFinder.isTest(clazz));
    }

    public void testTestFinderFindTest() throws Exception {
        ITestFinder testFinder = getJUnit4TestFinder();

        createTmpResource(project, "test/unit/" + packageName + "/Helper.groovy",
                "package " + packageName + "\n" + "\n" + "class Helper {\n" + "\n" + "   void help() {\n"
                        + "      println 'help!'\n" + "   }\n" + "}");
        StsTestUtil.waitForAutoBuild();
        IType clazz = javaProject.findType(packageName + ".Helper");
        assertNotNull(clazz);

        //1) Search in a cu that doesn't have a test class inside.
        Set<Object> result = new HashSet<Object>();
        testFinder.findTestsInContainer(clazz.getCompilationUnit(), result, new NullProgressMonitor());
        assertEquals(0, result.size());

        //2) Search in a cu that does have a test class inside
        result = new HashSet<Object>();
        clazz = javaProject.findType(testDomainClassName);
        testFinder.findTestsInContainer(clazz.getCompilationUnit(), result, new NullProgressMonitor());
        GrailsTest.assertElements(result, clazz);

        //3) Search in test/unit package fragment root
        result = new HashSet<Object>();
        IJavaElement pfr = clazz.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
        testFinder.findTestsInContainer(pfr, result, new NullProgressMonitor());
        GrailsTest.assertElements(result, clazz);

        //4) Same as above, but add an extra test class to see if that's also found.
        createTmpResource(project, "test/unit/" + packageName + "/FoobarTests.groovy",
                "package grails20junitintegrationtests\n" + "\n" + "import grails.test.mixin.*\n" + "\n"
                        + "@TestFor(" + domainClassBaseName + ")\n" + "class FoobarTests {\n" + "\n"
                        + "   void testThisAndThat() {\n" + "      assertEquals 4, 4\n" + "   }\n" + "   \n" + "}");
        StsTestUtil.waitForAutoBuild();
        IType extraTestClass = javaProject.findType(packageName + ".FoobarTests");
        testFinder.findTestsInContainer(pfr, result, new NullProgressMonitor());
        GrailsTest.assertElements(result, clazz, extraTestClass);

        //5) One more time, now search the whole project
        result = new HashSet<Object>();
        testFinder.findTestsInContainer(javaProject, result, new NullProgressMonitor());
        GrailsTest.assertElements(result, clazz, extraTestClass);
    }

    public void testTestFinderFindTestInSourceFileWithoutATestClass() throws Exception {
        ITestFinder testFinder = getJUnit4TestFinder();

        createTmpResource(project, "test/unit/" + packageName + "/Helper.groovy",
                "package " + packageName + "\n" + "\n" + "class Helper {\n" + "\n" + "   void help() {\n"
                        + "      println 'help!'\n" + "   }\n" + "}");
        StsTestUtil.waitForAutoBuild();
        IType clazz = javaProject.findType(packageName + ".Helper");
        assertNotNull(clazz);

        Set<Object> result = new HashSet<Object>();
        testFinder.findTestsInContainer(clazz.getCompilationUnit(), result, new NullProgressMonitor());
        assertEquals(0, result.size());
    }

    @SuppressWarnings("rawtypes")
    public void testThatASTTransformGotExecuted() throws Exception {
        //We check this indirectly, by checking whether the TestFor annotation exists on the testMethod, as expected, in the
        //byte code... We do this by creating a URLClassLoader from the projects resolved runtime classpath and then loading
        //up the test class.

        //This test only applies to 'regular' tests with the @TestFor annotation on the class. 
        // It doesn't apply to the spock test generated in Grails 2.3 so we create a old style test
        // here to verify this still works.

        createTmpResource(project, "test/unit/" + packageName + "/FoobarTests.groovy",
                "package grails20junitintegrationtests\n" + "\n" + "import grails.test.mixin.*\n" + "\n"
                        + "@TestFor(" + domainClassBaseName + ")\n" + "class FoobarTests {\n" + "\n"
                        + "   void testThisAndThat() {\n" + "      assertEquals 4, 4\n" + "   }\n" + "   \n" + "}");
        //Build project is required for the new code to be compiled by Eclipse:
        StsTestUtil.assertNoErrors(project);

        URLClassLoader classLoader = getRuntimeClassLoader(javaProject);
        Class testClass = Class.forName(packageName + ".FoobarTests", false, classLoader);
        Method m = getMethod(testClass, "testThisAndThat");
        assertAnnotation(m, "org.junit.Test");
    }

    /** 
     * Test a simple JUnit test run, while registering a test listener to capture the results.
     * 
     * @throws Exception
     */
    public void testSimpleRun() throws Exception {
        TestRunSession session = runAsJUnit(javaProject);
        assertTestFailure(session, "Implement me", testDomainClassName, generatedTestMethodName);

        //Also check the numbers of test run, failed etc.
        assertEquals(1, session.getStartedCount());
        assertEquals(0, session.getErrorCount());
        assertEquals(1, session.getFailureCount());
        assertEquals(1, session.getTotalCount());
    }

    /**
     * Verify whether test finder and runner is still capable of identifying, finding and running 
     * JUnit 3 style test types.
     */
    public void testFinderJUnit3Compatibility() throws Exception {
        createTmpResource(project, "test/unit/" + packageName + "/ExtraTests.groovy",
                "package " + packageName + "\n" + "\n" + "import grails.test.GrailsUnitTestCase;\n" + "\n"
                        + "class ExtraTests extends GrailsUnitTestCase {\n" + "   \n"
                        + "   void testSomething() {\n" + "      fail('Testing JUnit3 compatibility')\n" + "   }\n"
                        + "\n" + "}");

        StsTestUtil.waitForAutoBuild();

        //Is it a test?
        IType type = javaProject.findType(packageName + ".ExtraTests");
        ITestFinder testFinder = getJUnit4TestFinder();
        assertTrue(testFinder.isTest(type));

        //Can we find the test?
        HashSet<Object> result = new HashSet<Object>();
        testFinder.findTestsInContainer(javaProject, result, new NullProgressMonitor());
        assertElements(result, type, javaProject.findType(testDomainClassName));

        //Can we run the test and get expected result?
        TestRunSession session = runAsJUnit(type);
        assertTestFailure(session, "Testing JUnit3 compatibility", type.getFullyQualifiedName(), "testSomething");

    }

    public void testDoIncludeIntegrationTestsIfJUnit3() throws Exception {
        createTmpResource(project, "test/integration/" + packageName + "/ExtraTests.groovy",
                "package " + packageName + "\n" + "\n" + "import grails.test.GrailsUnitTestCase;\n" + "\n"
                        + "class ExtraTests extends GrailsUnitTestCase {\n" + "   \n"
                        + "   void testSomething() {\n" + "      fail('Testing JUnit3 compatibility')\n" + "   }\n"
                        + "\n" + "}");

        StsTestUtil.waitForAutoBuild();

        //Is it a test? (Should say YES) see https://issuetracker.springsource.com/browse/STS-2481
        IType type = javaProject.findType(packageName + ".ExtraTests");
        ITestFinder testFinder = getJUnit4TestFinder();
        assertTrue(testFinder.isTest(type));

        //Can we find the test? (SHOULD) see https://issuetracker.springsource.com/browse/STS-2481
        HashSet<Object> result = new HashSet<Object>();
        testFinder.findTestsInContainer(javaProject, result, new NullProgressMonitor());
        assertElements(result, javaProject.findType(testDomainClassName), type);
    }

    public void testDoIncludeGrailsIntegrationTests() throws Exception {
        String className = "SongITests";
        createTmpResource(project, "test/integration/" + packageName + "/" + className + ".groovy",
                "package " + packageName + "\n" + "\n" + "import static org.junit.Assert.*\n"
                        + "import grails.test.mixin.TestFor\n" + "\n" + "import org.junit.*\n" + "\n"
                        + "@TestFor(Song)\n" + "class " + className + " {\n" + "\n" + "    void testSomething() {\n"
                        + "        fail \"Implement me\"\n" + "    }\n" + "}\n");
        StsTestUtil.waitForAutoBuild();

        //Is it a test? (Should say YES) see: https://issuetracker.springsource.com/browse/STS-2481
        IType type = javaProject.findType(packageName + "." + className);
        ITestFinder testFinder = getJUnit4TestFinder();
        assertTrue(testFinder.isTest(type));

        //Can we find the test? (SHOULD) see: https://issuetracker.springsource.com/browse/STS-2481
        HashSet<Object> result = new HashSet<Object>();
        testFinder.findTestsInContainer(javaProject, result, new NullProgressMonitor());
        assertElements(result, javaProject.findType(testDomainClassName), type);

        //Run test with expected result?
        TestRunSession session = runAsJUnit(javaProject);
        assertTestFailure(session, "Implement me", type.getFullyQualifiedName(), "testSomething");

    }

    public void testDoIncludeIntegrationTestsIfJUnit4() throws Exception {
        String className = "SampleIntegrationTest";
        createTmpResource(project, "test/integration/" + packageName + "/" + className + ".groovy",
                "package " + packageName + "\n" + "\n" + "import org.junit.Test\n"
                        + "import static org.junit.Assert.*\n" + "\n" + "class " + className + " {\n" + "   \n"
                        + "   @Test\n" + "   void hello() {\n" + "      assertTrue(true)\n" + "   }\n" + "\n"
                        + "}\n");

        StsTestUtil.waitForAutoBuild();

        //Is it a test? (Should say YES) see: https://issuetracker.springsource.com/browse/STS-2481
        IType type = javaProject.findType(packageName + "." + className);
        ITestFinder testFinder = getJUnit4TestFinder();
        assertTrue(testFinder.isTest(type));

        //Can we find the test? (SHOULD) see: https://issuetracker.springsource.com/browse/STS-2481
        HashSet<Object> result = new HashSet<Object>();
        testFinder.findTestsInContainer(javaProject, result, new NullProgressMonitor());
        assertElements(result, javaProject.findType(testDomainClassName), type);
    }

    public void testOrdinaryJUNit4TestsInGrailsProject() throws Exception {
        String className = "FooTest";
        createTmpResource(project, "src/java/" + packageName + "/" + className + ".java",
                "package " + packageName + ";\n" + "\n" + "import static org.junit.Assert.*;\n" + "\n"
                        + "import org.junit.Test;\n" + "\n" + "public class " + className + " {\n" + "\n"
                        + "   @Test\n" + "   public void oneThatFails() {\n" + "      fail(\"not implemented\");\n"
                        + "   }\n" + "\n" + "}\n");

        StsTestUtil.waitForAutoBuild();

        //Is it a test? (Should say YES) see: https://issuetracker.springsource.com/browse/STS-2481
        IType type = javaProject.findType(packageName + "." + className);
        ITestFinder testFinder = getJUnit4TestFinder();
        assertTrue(testFinder.isTest(type));

        //Can we find the test? (SHOULD) see: https://issuetracker.springsource.com/browse/STS-2481
        HashSet<Object> result = new HashSet<Object>();
        testFinder.findTestsInContainer(javaProject, result, new NullProgressMonitor());
        assertElements(result, javaProject.findType(testDomainClassName), type);

        //Can we run the test and get expected result?
        TestRunSession session = runAsJUnit(javaProject);
        assertTestFailure(session, "not implemented", type.getFullyQualifiedName(), "oneThatFails");
    }

    public void testOrdinaryJUNit3TestsInGrailsProject() throws Exception {
        String className = "FooTest";
        createTmpResource(project, "src/java/" + packageName + "/" + className + ".java",
                "package grails20junitintegrationtests;\n" + "\n" + "import static org.junit.Assert.*;\n"
                        + "import junit.framework.TestCase;\n" + "\n" + "import org.junit.Test;\n" + "\n"
                        + "public class " + className + " extends TestCase {\n" + "   \n"
                        + "   public void testThatFails() {\n" + "      fail(\"not implemented\");\n" + "   }\n"
                        + "   \n" + "}\n" + "");

        StsTestUtil.waitForAutoBuild();

        //Is it a test? (Should say YES) see: https://issuetracker.springsource.com/browse/STS-2481
        IType type = javaProject.findType(packageName + "." + className);
        ITestFinder testFinder = getJUnit4TestFinder();
        assertTrue(testFinder.isTest(type));

        //Can we find the test? (SHOULD) see: https://issuetracker.springsource.com/browse/STS-2481
        HashSet<Object> result = new HashSet<Object>();
        testFinder.findTestsInContainer(javaProject, result, new NullProgressMonitor());
        assertElements(result, javaProject.findType(testDomainClassName), type);

        //Can we run the test and get expected result?
        TestRunSession session = runAsJUnit(javaProject);
        assertTestFailure(session, "not implemented", type.getFullyQualifiedName(), "testThatFails");
    }

    /**
     * When a Grails unit test class doesn't have the @TestFor annotation, but it has 
     * a name SomeDomainTests and there's a corresponding SomeDomain class, then
     * it should be treated the same as if the @TestFor(SomeDomain) annotation was present.
     */
    public void testNoAnnotationButCorrespondingDomainClassExists() throws Exception {
        //      Grails20TestSupport.DEBUG = true; //Compile will fail until Greclipse update site has newer version.
        try {
            tmpReplaceResource(project, "test/unit/" + packageName + "/" + domainClassBaseName + "Tests.groovy",
                    "package " + packageName + "\n" + "\n" +
                    //@TestFor !!!!ANNOTATION REMOVED!!!!
                            "class " + domainClassBaseName + "Tests {\n" + "   \n" + "   void testSomething() {\n"
                            + "      fail('Testing JUnit3 compatibility')\n" + "   }\n" + "}");
            StsTestUtil.waitForAutoBuild();
            StsTestUtil.assertNoErrors(project);

            //Using the locally created one instead of the generated one (which is a Spock test for Grails 2.3).
            String testDomainClassName = packageName + "." + domainClassBaseName + "Tests";

            //Is it a test?
            IType type = javaProject.findType(testDomainClassName);
            ITestFinder testFinder = getJUnit4TestFinder();
            assertTrue(testFinder.isTest(type));

            //Can we find the test?
            HashSet<Object> result = new HashSet<Object>();
            testFinder.findTestsInContainer(javaProject, result, new NullProgressMonitor());
            int numTests;
            if (GrailsVersion.MOST_RECENT.compareTo(GrailsVersion.V_2_3_) >= 0) {
                assertElements(result, javaProject.findType(testDomainClassName),
                        javaProject.findType(this.testDomainClassName) //generated 'Spec' test in 2.3
                );
                numTests = 2;
            } else {
                numTests = 1;
                assertElements(result, javaProject.findType(testDomainClassName));
            }

            //Did the transform run?
            URLClassLoader classLoader = getRuntimeClassLoader(javaProject);

            Class testClass = Class.forName(testDomainClassName, false, classLoader);
            Method m = getMethod(testClass, "testSomething");
            assertAnnotation(m, "org.junit.Test"); //should have been added by the transform.

            //Can we run the test
            TestRunSession session = runAsJUnit(javaProject);
            assertTestFailure(session, "Testing JUnit3 compatibility", testDomainClassName, "testSomething");

            //Also check the numbers of test run, failed etc.
            assertEquals(numTests, session.getStartedCount());
            assertEquals(numTests, session.getFailureCount() + session.getErrorCount());
            assertEquals(numTests, session.getTotalCount());
        } finally {
            //         Grails20TestSupport.DEBUG = false;
        }
    }

    private void assertAnnotation(Method m, String qName) {
        for (Annotation a : m.getAnnotations()) {
            String foundName = a.annotationType().getName();
            if (foundName.equals(qName)) {
                return;
            }
        }
        fail("Annotation " + qName + " not found on " + m);
    }

    private Method getMethod(Class<?> clazz, String name) {
        for (Method m : clazz.getMethods()) {
            if (m.getName().equals(name)) {
                return m;
            }
        }
        return null;
    }

}