Reputation: 309
I would like to run some tests for code that uses a MySQL database. Right now, the code consists of multiple modules that all import a common module mainlib
. This module does the
db = MySQLdb.connect(host='localhost', user='admin', password='admin', db='MyDatabase').
I would like to do tests using a test database instead of the real database.
I was thinking I could close the connection (mainlib.db.close()
) and create a new connection in the test script:
db = MySQLdb.connect(host='localhost', user='admin', password='admin', db='TestDatabase')
and name the new cursor with the same global variable. But I am unsure of how the imports in the other modules work. In any case, this method doesn't seem to work, as I get InterfaceError: (0, '')
as well as no data back from my test database cursor
.
Does anyone know how to switch to a test database without modifying the source code?
Upvotes: 0
Views: 605
Reputation: 279255
Python's "global" variables don't have global scope. They are module-scope variables. So the same-named global in different modules isn't the same variable.
I think you might be closing mainlib.db
and then setting mytestcode.db
to a new database. All the rest of your code of course continues to use mainlib.db
, which is now closed.
Try mainlib.db = MySQLdb.connect(...)
, and the same for the cursor. Directly modifying another module's variables is ugly, but it works as you'd expect.
The alternative would be to introduce a way of configuring how mainlib
opens the DB. For example, you could have a function like this in mainlib
:
db = None
dbname = None
cursor = None
def connectdb(name = None):
"""
Set up the global database connection and cursor, if it isn't already.
Omit 'name' when the caller doesn't care what database is used,
and is happy to accept whatever database is already connected or
connect to a default database.
Since there cannot be multiple global databases, an exception is thrown
if 'name' is specified, the global connection already exists, and the
names don't match.
"""
global db, dbname, cursor
if db is None:
if name is None:
name = 'MyDatabase'
db = MySQLdb.connect(host='localhost', user='admin', password='admin', db=name)
dbname = name
cursor = db.cursor()
elif name not in (None, dbname):
raise Exception('cannot connect to the specified db: the global connection already exists and connects to a different db')
Now, in your normal program (not in every module, just the top level) you call mainlib.connectdb()
right after importing mainlib
. In your test code you call mainlib.connectdb('TestDatabase')
.
Optionally, you could have connectdb
return the cursor and/or the connection object, That way, everything that uses the global db can go through this function.
Personally, I prefer not to use globals for this at all -- I would have a function to create a database connection and I would pass that database as a parameter into anything that needs it. However, I realise that tastes vary in this respect.
Upvotes: 1
Reputation: 4051
A quick fix would be to use the same cursor, but to be explicit with the database when selecting a table. for instance if you have a table T in both databases.
you could do
select * from myDatabase.T #if you want to use the real table
or
select * from TestDatabase.T #if you want to use the test table
Upvotes: 0