From: worodin <wo...@fr...> - 2006-10-21 23:41:30
|
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 |
From: worodin <wo...@fr...> - 2006-10-28 09:59:16
|
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 >> > |
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 >>> >>> > > |
From: David S. <sa...@mi...> - 2006-11-07 16:28:19
|
On 11/3/06, Jun...@li... < Jun...@li...> wrote: > This is certainly true for smaller projects and test suits. Might be > nice though, to find some of the problems *before* proceding into an > half hour build and test cycle, if you are just using ANT. I can understand that. > 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. > > Nothing to add there. Sure enough, the patch currently doesn't add any > other dependency outside of the JDK 1.5 tools.jar. tools.jar already contains APT? I wasn't aware of that (as I said, I'm new here. :-) - While writing the processor, some of the design choices for junit > annotations proved critical. This is especially the case, if the > presence of certain annotations at one declaration is in subtle ways > depending on the presence/absence of others. > E. g.: what should be the behavior of junit for class having > @RunWith(Suite.class), no @Suite.Classes() but a @Parameters method? > What about having several methods annotated with @Parameters in the same > hierarchie of classes? You had mentioned earlier the idea that there are several runners that are somewhat redundant with their "characteristic" further-information annotations. I think that this can lead to some interesting new design choices, but I'm still ruminating about that. For now, the next thing for me to do is probably look at the code and run it, and that will help us think further. I can't promise I'll get to it in less than a week. Thanks, David Saff |