Answering these by mail, not Jira comment, as it is not the best way to answer a lot of specific questions. Maybe I'll condense the discussion and add a Jira comment later. Just to be clear, I do not primarily work on this issue. I just wanted to bring out comments to get things started, and it does seem people have some.

David Van Couvering (JIRA) wrote:
[ http://issues.apache.org/jira/browse/DERBY-919?page=comments#action_12370400 ]
David Van Couvering commented on DERBY-919:
-------------------------------------------

I think it is great to have base unit test like this, although I agree with 
Andreas that this should be renamed.  This class is almost solely about 
obtaining connections using different frameworks, and is very JDBC-specific.  
There are plenty of unit tests that have no need for this functionality.

Yes, indeed. But then we are *almost* back to simply extending TestCase. What tests not related to frameworks (and thus JDBC) need some kind of common functionality? Including JDBC in the name seems like a solution. Do we agree that non-JDBC tests should extend TestCase directly?

I am not sure how this work integrates with/coincides with the work Andreas did 
to create a junit test type which allows you to run 'raw' JUnit tests under the 
harness.  Can you explain?

Andreas' work for running a "raw" JUnit test under the harness is not affected. This is all about getting a connection and some other basic functionality. It was written because the existing DerbyJUnitTest need additional methods calls before getConnection() returns a valid connection, and because TestUtil does not have a getConnection() (but several other getConnection(arguments) methods). We have several choices:
* Use TestUtil, maybe do some additional work on it.
* Adapt/change DerbyJUnitTest (dependencies restrict what we can change of existing API/behavior)
* Write a new common class from scratch

So far most of the comments I have received have been regarding implementation, which was not my primary goal. Do we all agree what we need, but we want to do it in different ways? Or are there still someone out there that have more fundamental issues to comment on?

Here are my general comments...

Javadoc:
- getConnection() - it would be great to say it connects to the default database, instead 
of "some database", which is a little disconcerting as it sounds somewhat 
non-deterministic.

   /**
    * Get a connection to some database.
    * If the database does not exist, it will be created.
    * As long as the state of this class is not changed, this method will
* return a connection to the same database. Most suites will require that
    * this condition is true.
    */

My "as long as state of this class is not changed" was supposed to indicate that a connection to the same database was returned. "some" was chosen because a test should not generally care what the database it uses is named - as long as it is the same database for a given time (typically while running a single test method or a suite). This is a matter of wording.

- You should document what the defaults are, such as "wombat" for the database name and 
"APP" for username and password.

I did not do this, because most tests should not care.

- why can't setup() or teardown() automaticlly call resetState() rather than 
asking the user to do it?  This seems dangerous and highly error-prone.

When I wrote the class, I was looking at the JDBC4 test suite. It is configured to always run under DerbyNetClient, but it "internally" runs tests for embedded as well. BasicDerbyJUnitTest was written with the following paradigm in mind: do setup (basically set framework, maybe change default name and force use of datasource), then use getConnection() for all tests in suite. The setup would be done in a TestSetup decorator. With this approach, the test code can be exactly the same for multiple frameworks and/or setups, where as the test decorator would do different things for each suite. Calling resetState in TestCase.setUp() would delete the state setup by TestDecorator.setUp(). If this way to run tests are not needed, things can be rewritten (in many ways...).

- when I try to click on a method name, I get a "404" error, although I can 
scroll directly down to view the method details.  I suspect this is probably just a JIRA 
bug.

This is because I just copied a single Javadoc file and attached it. Jira is not to blame here. I did not find it necessary to upload all results generated when running javadoc.

BaseDerbyJUnitTest:

- I don't understand why you set a property for the database name before 
calling obtainConnection() rather than just passing in the database name to 
obtainConnection().  It would be good to at least explain the motivation behind 
this, as at first read it seems a bit odd.  Scanning at the code, it looks like 
you use db(P_DBNAME) in createBaseDatabaseUrl() where you could just as easily 
pass the database name in as a parameter

All properties can be hardcoded and represented by constants instead of using a Properties object. I just wanted to signal that results are based on the state of the class, and that P_* are not set by environment properties, but that S_* are (passed on from the test harness). Andreas' TestConfiguration would separate this information from the class, which is good. I do think it is a bit too rigid as it is to give the required flexibility (not possible to change anything), but this is of course easily changed. It also give me the impression that every configurable aspect is passed on from the test harness, which is not yet true.

Also, it seems the harness uses all of "hostName", "derbyTesting.serverhost" and "derbyTesting.clienthost". Can anyone shed some light on this?

- There are a lot of defaults being setup in a hardcoded fashion in 
resetState().  It would be better to have a section of static finals at the top 
with all the default values so that someone looking at this code can tell right 
away what they are.  Actually, looking at Andreas' TestConfiguration, that is a 
nice way of doing it . Having it as a separate class also seems to be useful 
and more coherent.

One note here, is that it would not be possible to change the framework with the current TestConfiguration. This would cause trouble for exceptional cases (as the current JDBC4 testsuite) and if we want to run useprocess=false and switch framework. Is this switching of framework something we don't need?

- You have a lot of useful debug statements, but your javadoc doesn't really explain how 
to turn debug on and off, nor is it clear from the class (e.g. there is not 
"debug(boolean)" method).

Would mentioning this in the public class documentation do the trick?

   /**
    * Set property used to determine debug mode.
    * Set property to <code>true</code> to enable debug mode.
    * Debug mode can only be enabled/disabled on JVM startup.
    */
   private static final String  DEBUG_PROPERTY     = "derby.tests.debug";
   private static final boolean DEBUG              = new Boolean(
                   PropertyUtil.getSystemProperty(DEBUG_PROPERTY,
                                                  "false")).booleanValue();


- Your javadoc should be a little more explicit about how the default framework 
gets set

Noted. For the record, it reads system property "framework".

- It would be nice to have a helper method that allows subclasses to quickly 
obtain other properties set by the harness (e.g. so they don't have to do a 
privileged block every time they want to get a system property)

Are you thinking of a getSystemProperty(key) with a privileged block, or a method accessing a "cached" system properties object?

- I like Andreas' typesafe JDBCClient class, it seems a better approach.

Yes. It should be extended to have information about DataSource classes also, or else it would not be sufficent in a JSR 169 (like) environment. Some complications here if we want to allow for more than one type of DataSource for a given framework (XA, Pooled, Simple, "normal").



--
Kristian

Thanks,

David

improve pattern for setting up junit tests
------------------------------------------

         Key: DERBY-919
         URL: http://issues.apache.org/jira/browse/DERBY-919
     Project: Derby
        Type: Sub-task
  Components: Test
 Environment: All
    Reporter: Andreas Korneliussen
 Attachments: BasicDerbyJUnitTest.html, BasicDerbyJUnitTest.java, 
BasicDerbyJUnitTestTest.java, JDBCClient.java, TestConfiguration.java

The current junit tests cannot be run directly from the java.ui.textrunner by 
i.e using:
java junit.textui.TestRunner 
org.apache.derbyTesting.functionTests.tests.junitTests.lang.BooleanTest
.E
Time: 0.008
There was 1 error:
1) 
testBoolean(org.apache.derbyTesting.functionTests.tests.junitTests.lang.BooleanTest)java.lang.NullPointerException
        at 
org.apache.derbyTesting.functionTests.util.DerbyJUnitTest.faultInDriver(DerbyJUnitTest.java:317)
        at 
org.apache.derbyTesting.functionTests.util.DerbyJUnitTest.getConnection(DerbyJUnitTest.java:345)
        at 
org.apache.derbyTesting.functionTests.util.DerbyJUnitTest.getConnection(DerbyJUnitTest.java:335)
        at 
org.apache.derbyTesting.functionTests.tests.junitTests.lang.BooleanTest.testBoolean(BooleanTest.java:136)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
FAILURES!!!
Tests run: 1,  Failures: 0,  Errors: 1
The reason is that the tests needs to have some fixture being set up before the 
test can run, and that this is currently supported by calling a bunch of static 
methods in the correct order to initialize some static members of 
DerbyJUnitTest.
The proposed alternative is that the added fixture is set up in the suite() 
method, which is used by JUnit to get the Test object to be run.


Reply via email to