6 Replies Latest reply on Nov 16, 2006 10:39 PM by starksm64

    Logging with JBossTestCase

    rachmato

      There have been some changes to the class hierarchy involving JBossTestCase. It used to subclass from junit.framework.TestCase. It now subclasses from org.jboss.test.BaseTestCase which in turn subclasses from org.jboss.test.AbstractTestCase.

      BaseTestCase provides a getLog() method, something which JBossTestCase used to do. But in order for logging to be set up correctly, a subclass X of JBossTestCase must ensure that setUp() is called in BaseTestCase. If X does not override setUp() or tearDown(), it need take no action, as the method will be inherited; if it does override setUp() or tearDown(), it needs to call super.setUp() and super.tearDown() in the overriding methods.

      But I believe there are still problems here:
      1. JBossTestCase uses logging provided by BaseTestCase, but it does not call setUp() or tearDown(). Also, test class constructors seem to get called by JUnit before setUp() methods. Thus, I believe that any use of logging in JBossTestCase (for example, when handling exceptions in initDelegate()) will not be properly initialised by that time, as setUp() will not yet have been called.

      2. The setUp() and tearDown() methods are called each time a testcase is run. So it appears that logging will be set up and torn down for every test case, as opposed to once every test suite. It may be more appropriate to arrange things so that either this setup was done in a one time setup/teardown wrapper, as in AbstractTestCaseWithSetup, or arrange for logging setup outside of the methods setUp() and tearDown(). But AbstractTestCaseWithSetup would probably need some alteration as it is currently tuned to run with Joram tests. See related: http://www.jboss.com/index.html?module=bb&op=viewtopic&t=91386&postdays=0&postorder=asc&start=0

      3. If setUp() and tearDown() are used as the means for initialising logging, would it help programmers if those methods were overridden in JBossTestCase to call super.setUp() and super.tearDown(), to make it more obvious that there was important work being done in superclasses with these methods?

        • 1. Re: Logging with JBossTestCase
          starksm64

           

          "rachmatowicz@jboss.com" wrote:

          But I believe there are still problems here:
          1. JBossTestCase uses logging provided by BaseTestCase, but it does not call setUp() or tearDown(). Also, test class constructors seem to get called by JUnit before setUp() methods. Thus, I believe that any use of logging in JBossTestCase (for example, when handling exceptions in initDelegate()) will not be properly initialised by that time, as setUp() will not yet have been called.

          Doing initialization from the ctor is bad. This should be moved to a setUp/tearDown.

          "rachmatowicz@jboss.com" wrote:

          2. The setUp() and tearDown() methods are called each time a testcase is run. So it appears that logging will be set up and torn down for every test case, as opposed to once every test suite. It may be more appropriate to arrange things so that either this setup was done in a one time setup/teardown wrapper, as in AbstractTestCaseWithSetup, or arrange for logging setup outside of the methods setUp() and tearDown(). But AbstractTestCaseWithSetup would probably need some alteration as it is currently tuned to run with Joram tests. See related: http://www.jboss.com/index.html?module=bb&op=viewtopic&t=91386&postdays=0&postorder=asc&start=0

          This is a function of how you run the test. If we are running multiple tests there should be a TestSuite wrapper. If your running a single tests from within an ide you want a per test setUp/tearDown.

          "rachmatowicz@jboss.com" wrote:

          3. If setUp() and tearDown() are used as the means for initialising logging, would it help programmers if those methods were overridden in JBossTestCase to call super.setUp() and super.tearDown(), to make it more obvious that there was important work being done in superclasses with these methods?

          The JBossTest* classes in the jbossas suite need to be brought in synch with the base test project classes. If there are changes needed to do that in the test project, that is fine as long as they are discussed.


          • 2. Re: Logging with JBossTestCase
            rachmato

            An example of the problem is if you want to write to the log from a test case constructor for some reason. The class below subclasses from JBossTestCase:

            public MessageBodyUnitTestCase(String name) throws Exception
            {
            super(name);
            // this should return null
            log = getLog();
            if (log == null)
            System.out.println("MessageBodyUnitTestCase: null returned") ;
            }

            protected void setUp() throws Exception
            {
            // call setUp() in the superclass
            super.setUp() ;
            connect();
            }

            protected void tearDown() throws Exception
            {
            disconnect();
            // call tearDown() in the superclass to cleanup
            super.tearDown() ;
            }

            The test execution shows that the log is not correctly initialsed by the time the construtor gets executed:

            java.lang.NullPointerException
            at org.jboss.test.jbossmessaging.test.MessageBodyUnitTestCase.connect(MessageBodyUnitTestCase.java:95)
            at org.jboss.test.jbossmessaging.test.MessageBodyUnitTestCase.setUp(MessageBodyUnitTestCase.java:82)
            at junit.extensions.TestDecorator.basicRun(TestDecorator.java:22)
            at junit.extensions.TestSetup$1.protect(TestSetup.java:19)
            at junit.extensions.TestSetup.run(TestSetup.java:23)


            <system-out><![CDATA[MessageBodyUnitTestCase: null returned
            MessageBodyUnitTestCase: null returned

            This state of affairs also holds for JBossTestCase's constructor as well - so the exception handling code won't work in initDelegate.

            But i'll change the logging arrange,ent to call getLog() when a log reference is needed, and put any once-per-test-suite stuff in a JBossTestSetup wrapper.

            • 3. Re: Logging with JBossTestCase
              starksm64

              ctors cannot be calling non-private methods as you cannot guarantee that they will behave correctly. All of the initialization and logging in test class ctors is fragile and subject to being broken like has happened with this refactoring, and needs to be revised.

              • 4. Re: Logging with JBossTestCase
                starksm64

                We need to do a release of the test project so I'll look at the MessageBodyUnitTestCase to see how the JBossTestCase can be refactored to better work with the test base classes.

                • 5. Re: Logging with JBossTestCase
                  starksm64

                  The correct integration is to have JBossTestCase extend AbstractTestCaseWithSetup and have JBossTestServices be an extension of AbstractTestDelegate. JBossTestServices would "override" the static getDelegate method to return a JBossTestServices as the delegate.

                  • 6. Re: Logging with JBossTestCase
                    starksm64

                    With the current test project changes the MessageBodyUnitTestCase is running and passing 4/5 tests.