Hi,

During the last Perl QA Hackathon, I've been talking with TIMB, REHSACK,
HMBRAND and RIBASUSHI about Test::Database.

Going back to the needs that people have, it seems to me that:
- the main need is to obtain DSN to databases that match a certain
  set of prerequisites
- the prerequisites can vary wildly, and much more than what
  Test::Database currently supports (the most obvious example being any
  type of database that is behind a DBD::ODBC DSN)
- with enough support from CPAN Testers, there is no real need to
  *automatically* create databases (unless explicitely asked to, most
  likely for the file-based databases)

Test::Database suffers from bad naming: Test::Database::Handle,
Test::Database::Driver, driver_dsn are overloading names already used
with slightly different meanings in DBI. These can probably be fixed,
as the main interface for Test::Database is its handle / handles method.

It is also used by a number of modules on CPAN, so we have to be careful
with backwards compatibility.

Here are some of my conclusions:
- Test::Database should only return workspaces / databases that have
  already been configured, and assume that the necessary persmissions for
  testing are granted (create table, drop table, etc)
- Test::Database must support a much larger set of configuration files,
  located in various places: system (/etc), global ($HOME), local (cwd).
  That last bit would allow some projects to provide their own config file
  (as RIBASUSHI wants to do with DBIx::Class)
- the configuration files would support a much more fine-grained
  description for each DSN, and the characteristics would be described,
  and not discovered (well, apart from the DBD version, which is probably
  the only runtime attrbute). For example, the details of a database
  engine to which one connect through an ODBC DSN probably can't easily
  be discovered. These DSN would be Test::DSN objects, which have a larger
  set of attributes than the current Test::Database::Handle objects,
  but could share the same basic methods (dns, connection_info, etc)

With this in mind, Test::DSN would replace the legacy
Test::Database::Handle, and provide the dsn itself (pointing to a database
where the test script can create and drop its tables), the connection
information, and a set of attributes describing the workspace. Test::Database
would read its config files to get the list of available Test::DSN objects
and their attributes, and provide a method to request them based on their
attributes (e.g. give me a dsn for MySQL version 5.6 minimum, with such and
such options configured).

Backwards compatibility is assured by using a new method to return the
new Test::DSN objects. Over time, the old methods will be limited in
scope, until they are faded out (first by doing nothing, and later being
dropped entirely).

There are other issues that come to mind, like how to deal with parallel
testing, or even multiple different test suites using the same database
dsn at the same time. Maybe Test::Database could provide some sort of
optional locking mechanism, but I've have a hard time coming up with a
good one. Modules like DBIT already take that into account, by creating
tables with names explicitely designed to avoid clashes.

If some locking is provided, I think it probably must be at the table
level, i.e. a script will declare that it wants exclusive access to tables
X, Y, Z when requesting a dsn. The function will block (there's probably
a need for a timeout, to avoid having test scripts hanging forever)
until it can return a dsn with exclusive access to those tables. If
no tables are declared, Test::Database will assume that the script is
taking care of the issue.

Another option is that Test::Database could provide a function that
returns a unique prefix for a given script, so that the test script
can use that when creating the tables. That would provide isolated
"namespaces", and then we don't have to deal with locking directly.
With that namespace, we can even let Test::Database do things like
"drop all tables in that namespace".

As for file-based DBD, they should be handled specifically:
- Test::Database can already create a unique Test::DSN for any of those
- Test::Database would only have "drivers" for file-based DSN, as these
  would be the only case where database creation needs to be delegated
  to Test::Database.
- if a test wants specific options, they could be part of the request,
  and influence the database creation proceass

I've said above that all DSN should come from configuration files, but
there are still a few that can be discovered automatically, like the
test databases for MySQL and Pg. Should these be automatically included
in the list of DSN if they are found?

-- 
 Philippe Bruhat (BooK)

 None suffer so much in a war as those who strive to end it.
                                    (Moral from Groo The Wanderer #51 (Epic))

Reply via email to