From: David S. <sa...@mi...> - 2006-10-31 17:07:19
|
Thomas, Thank you for teaching me more about APT. After asking the more specific questions, I should probably move back to the big question. What is the primary goal of this patch? Will Eclipse, for example, flag errors at compile time if this is included? Otherwise, it would seem that whether APT or the runtime finds problems is going to be fairly transparent to users. One reason for a little inertia here is that Kent and Erich have tried to maintain a position as a "leaf in the technology tree", that is, having dependency on nothing but Java. I want to see this discussion through, but right now, I'm thinking that the best path may be to have this released separately into the JUnit ecosystem, and see if it gathers a following as an add-on to JUnit. What do you think? David Saff worodin wrote: > David, > > for 1.) > Short answer: The patch actually does this. > Long answer: > The patch places the APT processor into the same junit.jar as the > runtime, so users may drop the jar simply into the classpath of apt, > which is shared with javac, if you order apt to trigger the > compile too, (e.g by *not* using the option '-nocompile'). > > In fact, it is problematic to separate the required classes into > different jars, as in any case, you are likely to need access to the > compiled annotation classes, which would end up in both jars then. > > On a similar track, since the processor isn't generating anything, but > only doing checks, its currently not strictly a prerequisite to > compiling & running the tests. So prudence requires, that the runtime > checks remain in place; but we might want to share the resulting messages. > > For 2.) > APT caters for having several processors in the same build. > The processor needs to implement an information method, telling apt > which annotations to process. Apt detects process factorys, by peeking > into META-INF/services/com.sun.mirror.apt.AnnotationProcessorFactory of > every jar found in the -classpath or -factorypath of apt. > > This means: in the current state of the patch, a supplier of another > annotation (junit related or not) would have to implement its own > processor, and register it as mentioned above. > > Of course, we could start thinking about sort of an extension framework > for integrating junit specific extensions into our processor, but this > would require us to forsee all the needs of those, which proves > difficult. In our case: we would have to define an interface, that > abstracts the handling for treating any runner, and a way to look up > an implementation of that interface for any given runner. > > While this could be done, I'm still wondering if we really do need to to > specify runners via @RunWith. As far as I can see we currently have: > > - The default runner, which is used if non is specified. > - The Suite Runner, which *needs* to be used for a suite, > iff a @Suite.Classes() annotation is present, that is. > - The Parameterized Runner, which only makes sense, if there is also > an @Parametesr annotation. > > Are there more? > My impression is, we might be better off, dropping the @RunWith > annotations, and infering the proper runner from other annotations. > > Dreaming on, this could result in having a resolver, that starts nesting > runners, if there are several annotations that require different runners > - ordering might become a problem here. > > Thomas > > David Saff schrieb: > >> Thomas, >> >> It's certainly an interesting approach, and is a candidate for division >> of responsibilities. I've been meaning to learn more about APT. I >> wonder about the following challenges: >> >> 1) Can we avoid creating two runtimes, one for APT, and the other for >> the test execution? >> 2) If third parties create custom runners with custom annotations, how >> do they plug into the APT checks? >> >> David Saff >> >> worodin wrote: >> >>> Hey ho list! >>> >>> As a reference for this thread, pls take a look at >>> https://sourceforge.net/tracker/?func=detail&atid=315278&aid=1581916&group_id=15278 >>> >>> and try the jar. >>> >>> E. g. executing a task like >>> >>> <exec executable="C:/dev/tool/sun/j2sdk/1.5.0_07/bin/apt.exe"> >>> <arg line='-classpath ".;./junit4.1/junit-4.1.jar" -nocompile -d "." >>> org/junit/tests/apt/*.java'/> >>> </exec> >>> >>> against the test classes supplied in the patch would yield: >>> >>> [exec] org/junit/tests/apt/AllTests.java:41: The abstract test >>> class org.junit.tests.apt.TestAfter can not be instanced by suite runner >>> [exec] public class AllTests { >>> [exec] ^ >>> [exec] org/junit/tests/apt/AllTests.java:41: The abstract test >>> class org.junit.tests.apt.TestAfterClass can not be instanced by suite >>> runner >>> [exec] public class AllTests { >>> [exec] ^ >>> [exec] org/junit/tests/apt/AllTests.java:41: The abstract test >>> class org.junit.tests.apt.TestBefore can not be instanced by suite runner >>> [exec] public class AllTests { >>> [exec] ^ >>> [exec] org/junit/tests/apt/AllTests.java:41: The abstract test >>> class org.junit.tests.apt.TestBeforeClass can not be instanced by suite >>> runner >>> [exec] public class AllTests { >>> [exec] ^ >>> [exec] org/junit/tests/apt/AllTests.java:41: The abstract test >>> class org.junit.tests.apt.Quiet can not be instanced by suite runner >>> [exec] public class AllTests { >>> [exec] ^ >>> [exec] org/junit/tests/apt/EmptySuiteClasses.java:11: warning: >>> Annotation @SuiteClasses was empty - nothing to test. >>> [exec] public class EmptySuiteClasses {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/NoSuiteClasses.java:8: warning: Classes >>> annotated with @RunWith(Suite.class) should also be annotated with a non >>> empty @SuiteClasses({}). The resulting test suite is empty. >>> [exec] public class NoSuiteClasses {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/NotThrowing.java:7: Checked Exception >>> org.junit.tests.apt.NotThrowing.MyException will never be thrown, >>> because it isn't declared for method notThrowing. This test will allways >>> fail. >>> [exec] @Test(expected=MyException.class) public void >>> notThrowing() {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/OrphanedSuite.java:7: warning: The >>> annotation @SuiteClasses({...}) is only of use for classes also >>> annotated with @RunWith(Suite.class). >>> [exec] public class OrphanedSuite {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/StaticTest.java:7: Methods annotated >>> with org.junit.Test must not be static. >>> [exec] @Test public static void staticTest() {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestAfter.java:7: Methods annotated with >>> org.junit.After need to return void. >>> [exec] @After public int notVoid(Object o) {return 0;} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestAfter.java:7: Methods annotated with >>> org.junit.After shouldn't have parameters. >>> [exec] @After public int notVoid(Object o) {return 0;} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestAfterClass.java:7: Methods annotated >>> with org.junit.AfterClass need to be public. >>> [exec] @AfterClass void notPublic(Object o) {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestAfterClass.java:7: Methods annotated >>> with org.junit.AfterClass shouldn't have parameters. >>> [exec] @AfterClass void notPublic(Object o) {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestAfterClass.java:7: Methods annotated >>> with org.junit.AfterClass need to be static. >>> [exec] @AfterClass void notPublic(Object o) {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestBefore.java:7: Methods annotated >>> with org.junit.Before need to be public. >>> [exec] @Before int notPublicNotVoid() {return 0;} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestBefore.java:7: Methods annotated >>> with org.junit.Before need to return void. >>> [exec] @Before int notPublicNotVoid() {return 0;} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestBeforeClass.java:7: Methods >>> annotated with org.junit.BeforeClass need to be public. >>> [exec] @BeforeClass int notPublicNotVoid(Object o) {return 0;} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestBeforeClass.java:7: Methods >>> annotated with org.junit.BeforeClass need to return void. >>> [exec] @BeforeClass int notPublicNotVoid(Object o) {return 0;} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestBeforeClass.java:7: Methods >>> annotated with org.junit.BeforeClass shouldn't have parameters. >>> [exec] @BeforeClass int notPublicNotVoid(Object o) {return 0;} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestBeforeClass.java:7: Methods >>> annotated with org.junit.BeforeClass need to be static. >>> [exec] @BeforeClass int notPublicNotVoid(Object o) {return 0;} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestHasParameters.java:7: Methods >>> annotated with org.junit.Test shouldn't have parameters. >>> [exec] @Test public void hasParameters(Object o) {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestInheritedParameters.java:11: Methods >>> annotated with org.junit.runners.Parameterized.Parameters are required >>> to return java.util.Collection<java.lang.Object[]>. >>> [exec] @Parameters public static Object data2() {return new >>> Object();} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestNotPublic.java:7: Methods annotated >>> with org.junit.Test need to be public. >>> [exec] @Test void notPublic() {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestNotVoid.java:7: Methods annotated >>> with org.junit.Test need to return void. >>> [exec] @Test public int notVoid() {return 0;} >>> [exec] ^ >>> [exec] >>> org/junit/tests/apt/TestParameterizedWith2Constructors.java:15: >>> Constructor competes with one allready seen at >>> org/junit/tests/apt/TestParameterizedWith2Constructors.java:14 - classes >>> annotated with @RunWith(Parameterized.class) require exactly one public >>> constructor taking the parameters. >>> [exec] public TestParameterizedWith2Constructors() {} >>> [exec] ^ >>> [exec] >>> org/junit/tests/apt/TestParameterizedWith2Constructors.java:12: >>> org.junit.tests.apt.TestParameterizedWith2Constructors contains 2 public >>> constructors - classes annotated with @RunWith(Parameterized.class) >>> require exactly one public constructor taking the parameters. >>> [exec] public class TestParameterizedWith2Constructors { >>> [exec] ^ >>> [exec] >>> org/junit/tests/apt/TestParameterizedWith2ParameterMethods.java:26: >>> warning: Method annotated with @Parameters competes with one allready >>> seen at >>> org/junit/tests/apt/TestParameterizedWith2ParameterMethods.java:20 - as >>> of Junit 4.1, only one of them will be used to retrieve test parameters. >>> [exec] @Parameters public static Collection<Object[]> data2() { >>> [exec] ^ >>> [exec] >>> org/junit/tests/apt/TestParameterizedWith2ParameterMethods.java:11: >>> warning: There are 2 competing methods all annotated with @Parameters - >>> as of Junit 4.1, only one of them will be used to retrieve test >>> parameters. >>> [exec] public class TestParameterizedWith2ParameterMethods { >>> [exec] ^ >>> [exec] >>> org/junit/tests/apt/TestParameterizedWithNoParameterMethods.java:9: >>> Class org.junit.tests.apt.TestParameterizedWithNoParameterMethods is not >>> abstract, annotated as @RunWith(Parameterized.class), but there is no >>> instance method annotated with @Parameters within the type hierarchy: >>> There will be nothing to test. >>> [exec] public class TestParameterizedWithNoParameterMethods { >>> [exec] ^ >>> [exec] org/junit/tests/apt/TestParameters.java:11: Methods >>> annotated with org.junit.runners.Parameterized.Parameters are required >>> to return java.util.Collection<java.lang.Object[]>. >>> [exec] @Parameters public static Object data2() {return new >>> Object();} >>> [exec] ^ >>> [exec] org/junit/tests/apt/SuiteCycle.java:25: The following >>> classes annotated with @RunWith(Suite.class) form a loop: >>> org.junit.tests.apt.SuiteCycle.ASuite -> >>> org.junit.tests.apt.SuiteCycle.AnotherSuite - invoking any of them will >>> result in a stack overflow at runtime. >>> [exec] public static class ASuite {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/SuiteCycle.java:25: Referenced suite >>> org.junit.tests.apt.SuiteCycle.AnotherSuite is part of or references a >>> loop of suits - invokation will cause a stack overflow at runtime. >>> [exec] public static class ASuite {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/SuiteCycle.java:21: Referenced suite >>> org.junit.tests.apt.SuiteCycle.ASuite is part of or references a loop of >>> suits - invokation will cause a stack overflow at runtime. >>> [exec] public class SuiteCycle { >>> [exec] ^ >>> [exec] org/junit/tests/apt/AllTests.java:41: Referenced suite >>> org.junit.tests.apt.SuiteCycle is part of or references a loop of suits >>> - invokation will cause a stack overflow at runtime. >>> [exec] public class AllTests { >>> [exec] ^ >>> [exec] org/junit/tests/apt/NoTestInSuiteClass.java:11: warning: >>> Test case org.junit.tests.apt.NoTestInSuiteClass doesn't contain any >>> test methods. >>> [exec] public class NoTestInSuiteClass {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/NoSuiteClasses.java:8: warning: Test >>> case org.junit.tests.apt.NoSuiteClasses doesn't contain any test methods. >>> [exec] public class NoSuiteClasses {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/EmptySuiteClasses.java:11: warning: Test >>> case org.junit.tests.apt.EmptySuiteClasses doesn't contain any test >>> methods. >>> [exec] public class EmptySuiteClasses {} >>> [exec] ^ >>> [exec] org/junit/tests/apt/ClassNotPublic.java:9: Class >>> org.junit.tests.apt.ClassNotPublic has to be public in order to be >>> instanced. >>> [exec] class ClassNotPublic { >>> [exec] ^ >>> [exec] org/junit/tests/apt/NoValidConstructors.java:6: This test >>> class requires a public no argument constructor. >>> [exec] public class NoValidConstructors { >>> [exec] ^ >>> [exec] 32 errors >>> [exec] 8 warnings >>> [exec] Result: 1 >>> >>> >>> As far as I can tell, the checks are pretty complete, but I'm open to >>> suggestions. The processor might do with some refactoring, but hey, it's >>> my first try at apt. >>> >>> I see several spin offs: >>> >>> - the apt processor uses 20+ messages (Errors and warnings), some of >>> them intersecting with runtime messages. It might be viable, to start >>> pooling all messages used in org.junit in a jdk 1.5 enumeration. >>> >>> - as an afterthought, I wonder if we really need @RunWith. AFAICT, the >>> proper runner can mostly infered from an other annotation, e. g. >>> @SuiteClasses or @Parameters, leaving the rest to the default runner. >>> >>> - the patch contains a test, that runs apt on a isolated file, checking >>> for results. This could be evolved into a pattern for testing apt >>> processors. >>> >>> Hope this is of interest. >>> >>> Thomas >>> >>> ------------------------------------------------------------------------- >>> Using Tomcat but need to do more? Need to support web services, security? >>> Get stuff done quickly with pre-integrated technology to make your job >>> easier >>> Download IBM WebSphere Application Server v.1.0.1 based on Apache >>> Geronimo >>> http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 >>> _______________________________________________ >>> Junit-devel mailing list >>> Jun...@li... >>> https://lists.sourceforge.net/lists/listinfo/junit-devel >>> >>> > > |