1Test::Database::TutoriaUls(e3r)Contributed Perl DocumentTaetsito:n:Database::Tutorial(3)
2
3
4
6 Test::Database::Tutorial - How to use Test::Database
7
9 The goal of the Test::Database module is to provide easy to use test
10 databases for test scripts that need them.
11
12 The problem
13 Until now, when a test script needed a database, it either used SQLite
14 (or some other easy to setup database), or required some environment
15 variables to be present, or used default credentials, or even set up
16 the database by itself.
17
18 Most of those methods have pros and cons:
19
20 · using SQLite
21
22 No setup needed, but the test script can only use SQLite's dialect
23 of SQL. So much for portability across database engines.
24
25 · using environment variables
26
27 The environment variables are different for every module to test,
28 and usually only the main developers/testers know about them. Since
29 most of the CPAN testers probably don't bother setting them up,
30 these modules are most certainly undertested.
31
32 · using default credentials
33
34 Typically using 'root' and '' to connect to the "test" MySQL
35 database, these test script assume a default installation on the
36 host system. These credentials often provide full access to the
37 database engine, which is a security risk in itself (see below).
38
39 · setting up the database by itself
40
41 This method usually uses the default credentials to access an
42 account with enough privileges to create a database. The host
43 system data may be at risk!
44
45 A solution: Test::Database
46 Many modules use a database to store their data, and often support
47 several database engines.
48
49 Wouldn't it be nice to be able to test on all the supported databases
50 that are available on the test system? Without breaking (into)
51 anything?
52
53 This is the goal of the Test::Database module. It supports:
54
55 · getting DSN information from a list of pre-configured database and
56 engines
57
58 · automatic detection of "file-based" database engines (typically,
59 SQLite).
60
61 The rest of this document describes various use cases for
62 Test::Database.
63
65 Test::Database has a single interface for test authors:
66
67 my @handles = Test::Database->handles( @requests );
68
69 @request is a list of "requests" for databases handles. Requests must
70 declare the DBD they expect, and can optionaly add version-based
71 limitations (only available for drivers supported by Test::Database).
72
73 The handles returned are objects of the Test::Database::Handle class.
74
75 The data contained in the database is never destroyed or cleaned up by
76 Test::Database, so it's perfectly fine to have a startup script that
77 will setup the necessary tables and test data, several tests scripts
78 that will build and update the data, and a eventually a teardown script
79 that will drop all created tables.
80
81 Test::Database can return two types of databases handles:
82
83 · either a handle to a newly created database (created especially at
84 the test script's request)
85
86 · or a handle to an already existing database
87
88 There is no way for the test script to tell the difference.
89
90 In any case, the database is assumed to provide "DROP TABLE" and
91 "CREATE TABLE" rights, and the test script is by definition allowed to
92 do whatever it pleases with the tables that exist in the database.
93
94 Note that Test::Database supports any DSN, not just those for which it
95 has a driver. If your module supports Oracle, you can add 'Oracle' to
96 your list of requests, and if the host owner configured a "dsn"
97 pointing at an Oracle database, then it will be available for your
98 tests.
99
100 Specific database support
101 It is possible to request specific versions of a database engine.
102
103 use Test::Database;
104
105 # request database handles for all available databases
106 my @handles = Test::Database->handles();
107
108 # or for only the databases we support
109 my @handles = Test::Database->handles(
110 { dbd => 'SQLite' },
111 { dbd => 'SQLite2' },
112 { dbd => 'mysql', min_version => '4.0' },
113 );
114
115 See Test::Database documentation for details about how to write a
116 request.
117
118 Testing on a development box
119 The first systems on which you are going to test your module are the
120 ones you own. On these system, it's up to you to configure the
121 databases you want to make available.
122
123 A typical ~/.test-database configuration file would look like this:
124
125 dsn = dbi:mysql:database=test
126 username = root
127
128 dsn = dbi:Pg:database=test
129 username = postgres
130
131 dsn = dbi:Oracle:test
132
133 There is no need to add "dsn" sections for file-based drivers (at least
134 the ones that have a corresponding Test::Database::Driver), since the
135 module will automatically detect the available ones and create
136 databases as needed.
137
138 To find out which of the DBD that Test::Database supports are
139 installed, use the following one-liner:
140
141 $ perl -MTest::Database -le 'print for Test::Database->list_drivers("available")'
142 DBM
143 SQLite
144 mysql
145
146 With no parameter, it will return the list of configured ones:
147
148 $ perl -MTest::Database -le 'print for Test::Database->list_drivers()'
149 DBM
150 SQLite
151
153 The main goal of Test::Database from the point of view of a tester is:
154 "configure once, test everything".
155
156 As a CPAN tester, once you have installed Test::Database, you should
157 edit the local equivalent of ~/.test-database for the user that will be
158 running the CPAN test suites.
159
160 "dsn" versus "driver_dsn"
161 "dsn" sections define the information needed to connect to a single
162 database. Any database listed here can be used by any test script that
163 requests it.
164
165 "driver_dsn" sections define the information needed to connect to a
166 database engine (a "driver") with sufficient rights to run a "CREATE
167 DATABASE" command. This allows Test::Database to create the databases
168 on demand, thus ensuring every test suite will get a specific database.
169
170 If you have file-based database engine, there is nothing to setup, as
171 Test::Database is able to detect available file-based engines and use
172 them as needed.
173
174 Other database engines like "mysql" and "Pg" require a little more
175 configuration. For example, here's the content of my ~/.test-database
176 configuration file:
177
178 driver_dsn = dbi:mysql:
179 username = root
180
181 driver_dsn = dbi:Pg:
182 username = postgres
183
184 For "Pg", I had to edit the pg_hba.cong file in /etc to make sure
185 anyone would be able to connect as the "postgres" user, for example.
186
187 Several test hosts accessing the same database engine
188 If you have a large scale testing setup, you may want to setup a single
189 MySQL or Postgres instance for all your test hosts, rather than one per
190 test host.
191
192 Databases created by Test::Database::Driver (using a configured
193 "driver_dsn" have a name built after the following template:
194 "tdd_driver_login_n", where driver is the DBD name, login is the login
195 of the user running Test::Database and n a number that
196
197 If the same database server is used by several host running
198 Test::Database from the same user account, there is a race condition
199 during with two different host may try to create the a database with
200 the same name. A simple trick to avoid this is to add a "key" section
201 to the ~/.test-database configuration file.
202
203 If the "key" entry exists, the template used by Test::Database::Driver
204 to create new databases is "tdd_driver_login_key_n".
205
206 Cleaning the test drivers
207 When given a "driver_dsn", Test::Database will use it to create a
208 database for each test suite that requests one. Some mapping
209 information is created to ensure the same test suite always receives a
210 handle to the same database. (The mapping of test suite to database is
211 based on the current working directory when Test::Database is loaded).
212
213 After a while, your database engine may fill up with unused test
214 databases.
215
216 All drivers store their mapping information in the system's temporary
217 directory, so the mapping information is relatively volatile, which
218 implies more unused test databases (at least for non file-based
219 drivers, since the file-based drivers store their database files in the
220 system's temporary directory too).
221
222 The following one-liner will list all the existing databases that were
223 created by Test::Database in your configured drivers:
224
225 perl -MTest::Database -le 'print join "\n ", $_->name, $_->databases for Test::Database->drivers'
226
227 Example output:
228
229 CSV
230 tdd_csv_book_0
231 tdd_csv_book_1
232 DBM
233 SQLite
234 tdd_sqlite_book_0
235 tdd_sqlite_book_1
236 SQLite2
237 tdd_sqlite2_book_0
238 mysql
239 tdd_mysql_book_0
240 tdd_mysql_book_1
241
242 The following one-liner will drop them all:
243
244 perl -MTest::Database -le 'for$d(Test::Database->drivers){$d->drop_database($_)for$d->databases}'
245
246 If a "key" has been defined in the configuration, only the databases
247 corresponding to that key will be dropped.
248
250 Test::Database currently supports the following DBD drivers: "CSV",
251 "DBM", "mysql", "Pg", "SQLite2", "SQLite".
252
253 Adding a new driver requires writing a corresponding
254 Test::Database::Driver subclass, having the same name as the original
255 "DBD" driver.
256
257 An example module is provided in eg/MyDriver.pm, and the other drivers
258 can also be used as an example. See also the WRITING A DRIVER FOR YOUR
259 DATABASE OF CHOICE section in the documentation for
260 Test::Database::Driver.
261
263 The following ASCII-art graph shows where the Test::Database::Handle
264 objects returned by the "handles()" method come from:
265
266 ,-------------, ,-------------, ,--------------,
267 | DSN from | | File-based | | Drivers from |
268 | config file | | drivers | | config file |
269 '-------------' '-------------' '--------------'
270 | | |
271 | | ,-----------, |
272 | '--->| Available |<----'
273 | | drivers |
274 | '-----------'
275 | |
276 | ,-----------, |
277 '------------->| Available |<--'
278 | DSN |
279 '-----------'
280
281 Here are a few details about the "handles()" method works:
282
283 · Test::Database maintains a list of Test::Database::Handle objects
284 computed from the DSN listed in the configuration.
285
286 The handles matching the request are selected.
287
288 · Test::Database also maintains a list of Test::Database::Driver
289 objects computed from the list of supported file-based drivers that
290 are locally available and from the list in the configuration file.
291
292 The list of matching drivers is computed from the requests. Each
293 driver is then requested to provide an existing database (using its
294 existing mapping information) or to create one if needed, and
295 returns the corresponding Test::Database::Handle objects.
296
297 · Finally, all the collected Test::Database::Handle objects are
298 returned.
299
300 So, without any configuration, Test::Database will only be able to
301 provide file-based databases. It is also recommended to not put DSN or
302 driver information for the file-based database engines that have a
303 corresponding Test::Database::Driver class, since it will cause
304 "handles()" to return several handles for the same database engine.
305
307 Philippe Bruhat (BooK), "<book@cpan.org>"
308
310 Copyright 2009-2010 Philippe Bruhat (BooK), all rights reserved.
311
313 You can redistribute this tutorial and/or modify it under the same
314 terms as Perl itself.
315
316
317
318perl v5.32.0 2020-07-28 Test::Database::Tutorial(3)