The Great Re-write of 2010: CGI::Session/Test::Database/DBIx::NamedDSN
Hi Folks
I have just finished a re-write of CGI::Session, called Data::Session, and started wondering how best to test it.
I've always disliked setting all the env vars to make its tests work for MySQL, PG, etc, so I hit CPAN looking for A Better Way.
I found Test::Database, which seemed to be a good idea. But examining the code was discouraging, so I decided to re-write that too.
I soon realized that one thing (among many - see below) which bugged me about Test::Database was its handing of DSNs.
So I decided to split that out into a separate distro, using an INI-style file, so I could add extra attributes to the DSN, such as active and use_for_testing. I might add use_for_production too.
That's why I've just released to CPAN DBIx::Admin::DSNManager V 1.00.
Now I'll use that in the re-write of Test::Database, which I'm going to call Test::Admin::Database.
I don't want to reuse the namespace Test::Database, since the aims of the modules are a bit different.
Then finally the latter can be used to help test Data::Session which I'll release as V 0.90 at first.
Pain with Test::Database:
1) Test::Database does not install with cpanm. First you have to install DBD::CSV V 0.31 twice. Then it installs.
2) Also, the docs for Test::Database are very hard to fillow. For instance, under Description,
it talks about install leading you through configuration, and writing ~/.test-database. That does not happen. Perhaps it did once upon a time.
3) Also, in Test::Database::Tutorial, there is a talk about the difference between a dsn and a driver_dsn, but the code does not follow the docs.
For example, when I used a dsn (in ~/.test-database) for Postgres, with a user who has createdb rights, that dsn is ignored. But if I use dsn_driver, it is used.
4) Also, if I put a dsn for SQLite in ~/.test-databas, to see what happens, I get 2 handles to SQLite. Perhaps that's a good idea, but it should be documented.
5) Also, Test::Database does not use File::HomeDir - it should.
6) Also, when I remove dsns from ~/.test-database, the module does not rewrite /tmp/Test-Database-ron//Pg/mapping.yml, which is then left with dsns I don't want to use.
Now I have not seen your new code yes, but the old one in my experience was rather unfortunate in the sense that it did not cater for the case that two instances were accessing the session concurrently and updated different values in the session ...
A - open session
B - open session
A - write prop A
B - write prop B
A - close session
B - close session
would result in prop A being lost ...
All of those problems in Test::Database sound like bugs, not fundamental design problems. Can’t they just be fixed?
The main value of something like Test::Database is if (close to) every distribution uses it, because that lets users configure their test database credentials once and have all their module installation attempts use that configuration. If there are 15 different modules for supplying database credentials to tests, then the situation is no better for users than if every distribution were looking for some kind of environment variable.
So please consider whether you can somehow fix T::D instead of going off in an entirely new direction.
Have you talked with BooK about any of this?
Before replying to your points, I must say Test::Database has been looking for users for a long time, and I'm sad to say that I have had very little return on the topic. I have tried very hard to make the module pass all tests on a number of platforms/databases, and have talked a lot with a number of people to try and provide something useful to most.
The design goal of Test::Database is to allow people who try to write code that is portable across database drivers to use the power of CPAN Testers. It is not a DSN configuration manager.
Now, quick replies to your points:
Yes, there have been issues with DBD::CSV, which I tried to fix. I don't think I found time to fix all the issues, even thought DBD::CSV's author fixed a few things because of Test::Database.
Yeah, that is actually a quote, back from early discussions on the topic. A bit of name-dropping too. Anyway, even though I planned to have some way to automatically create the file, this will probably never happen. I should fix the Description to match reality, indeed.
Actually, the doc is incorrect. What it meant, is that Test::Database will only create databases with a driver_dsn.
In Test::Database, a dsn is a place where you're implicitly allowed to do anything up to CREATE TABLE and DROP TABLE. A dsn_driver assumes you can also CREATE DATABASE and DROP DATABASE.
File-based handles are automatically provided if the DBD is available.
Actually, it does. Since March 2009.
This looks partly as a bug. Of course, rm -rf /tmp/Test-Database-ron/ won't hurt.
After re-reading the Tutorial, I think the documentation explains exactly what the code does.
Basically, Test::Database is meant to provide database handles, not configured in any way, to let your test scripts do their thing.
It will return the same dbh to several successive test scripts running in the same cwd, thus allowing a test script to setup the database that the following tests scripts will use. The ability to create a database is only needed because Test::Database would prefer to create a database per distribution being tested.
Providing a dsn in the configuration is allowing any test script to do anything there, but has the drawback that several test script (possibly running in parallel) will access the same database handle. Not really recommended for a CPAN Tester setup.
That behaviour is actually documented in Test::Database::Tutorial:
Hi Folks
$many x $thanx for the replies. I'll respond to each, but first an apology. I should have posted the link to the docs on my web site, rather than waiting for CPAN. So:
http://savage.net.au/Perl-modules/html/DBIx/Admin/DSNManager.html
Hi Tobi:
Your problem doesn't surprise me. Each process would write its own session data, without checking if the session had been updated behind-its-back.
My code (Data::Session) - at the moment - does not do any such check either. I've made a note and will consider changing the code before release.
I hate complexity, but perhaps we need another option to new() allowing you to warn that processes can share sessions. That way, most time we don't need to check the update time of a session before re-writing it.
Hi Aristotle:
I considered asking the author of Test::Database for co-maint, but decided to start from scratch.
One thing I didn't make clear (hence the link above) is that (with DBIx::Admin::DSNManager) I'm dealing just with DSNs, not live db handles. This affects how I think about the problem.
As for who uses Test::Database - I have no idea. I should warn you that this is still a bit of a sensitive topic, since download stats for modules were ruthlessly suppressed for so long, but let's skip another discussion of that. BooK's comment suggest he too is not clear on usage of Test::Database, which is a pity. I'd very much like to know who I'm affecting.
There are many situations where we have too many similar modules - I'm intensely aware of that. Nevertheless, I thought this approach was appropriate. That means simply that I chose not to use Test::Database for my own work, and that I'm going to write a replacement with enough effort put into it that other people can reasonably rely on the code (but can just ignore it, too).
And, no, I did not talk to BooK.
Hi BooK
Glad to see you've spent some time considering my comments. I tried hard to make them code-oriented and not personal....
I too want to write portable code, without having to spend too much time testing other (non-Debian) OSes, and using only 1 Perl.
(As an aside, my laptop only has 756 Mb RAM, so I'm reluctant to do too much, but I've just sold my house (settlement - as it's called in Australia [i.e. full payment] on Dec-17) so I'll upgrade after that).
I hoped you'd be able to use my comments as guides to patching Test::Database, but it's OK if you don't want to do that.
As for parallel testing - I haven't designed anything to deal specifically with that. It sounds like a solution is a tiny client-server setup, with the server handing out DSNs which it knows are free. Hmmm, interesting...
Hi Folks
Perhaps someone with experience of parallel testing will write up a Google Summer of Code proposal for managing DSNs:
http://perlbuzz.com/2010/11/google-code-in-brings-fresh-blood-to-the-perl-and-parrot-communities.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+PerlBuzz+(PerlBuzz)