Provide a platform neutral way to run Postgres in integration tests. More info at: http://www.simulmedia.com/resources/blog/pyembedpg-simple-way-use-postgres-python-integration-tests/
- Running tests in parallel on different instances of Postgres
- Testing on different versions can be useful (e.g., prod has another version of Postgres installed)
- Easier to install a particular version than manually
- Dropping databases and users all the time is painful (and cleanup might not be done properly everytime)
It downloads the specified version of Postgres automatically from https://ftp.postgresql.org/pub/source/,
build it and cache it in .pyembedpg so subsequent uses won't download it.
You can start the Postgres server on any port in a context (using with) that will be shutdown when you exit the context.
You can install pyembedpg with pip:
pip install pyembedpg
You can start a new postgres server as follows:
pg=PyEmbedPg('9.4.0')
# Start the database and download it and build it if it hasn't been done so alreadywithpg.start(15432) asdb:
# do your thingor:
pg=PyEmbedPg('9.4.0')
# Start the database and download it and build it if it hasn't been done so alreadydb=pg.start(15432)
try:
# do your thingfinally:
db.shutdown()If you don't specify the version (e.g., PyEmbedPg()), it will use the latest version found in .pyembedpg or on the FTP server if .pyembedpg is empty.
If you want to use the current Postgres version installed on the server you can do PyEmbedPg('local').
You can use it as follows:
pg=PyEmbedPg('9.4.0')
withpg.start(15432) aspostgres:
postgres.create_user('scott', 'tiger')
postgres.create_database('testdb', 'scott')
# Postgres is initialized, now run some querieswithpsycopg2.connect(database='postgres', user='scott', password='tiger', port=postgres.running_port) asconn:
withconn.cursor() ascursor:
cursor.execute('CREATE TABLE employee(name VARCHAR(32), age INT)')
cursor.execute("INSERT INTO employee VALUES ('John', 32)")
cursor.execute("INSERT INTO employee VALUES ('Mary', 22)")
cursor.execute('SELECT * FROM employee ORDER BY age')
assertcursor.fetchall() == [('Mary', 22), ('John', 32)]or in unit tests:
importunittestimportpsycopg2frompyembedpgimportPyEmbedPgclassTestPyEmbedPgWithContext(unittest.TestCase):
defsetUp(self):
self.postgres=PyEmbedPg('9.4.0').start(15432)
deftest_simple_run(self):
self.postgres.create_user('scott', 'tiger')
self.postgres.create_database('testdb', 'scott')
# Postgres is initialized, now run some querieswithpsycopg2.connect(database='postgres', user='scott', password='tiger', port=self.postgres.running_port) asconn:
withconn.cursor() ascursor:
cursor.execute('CREATE TABLE employee(name VARCHAR(32), age INT)')
cursor.execute("INSERT INTO employee VALUES ('John', 32)")
cursor.execute("INSERT INTO employee VALUES ('Mary', 22)")
cursor.execute('SELECT * FROM employee ORDER BY age')
assertcursor.fetchall() == [('Mary', 22), ('John', 32)]
deftearDown(self):
self.postgres.shutdown()You can also specify a list of ports to use (e.g., PyEmbedPg('9.4.0').start(range(15432, 15440))). The first available port will be used. This can be useful when you run multiple tests in parallel.
Check that gcc and readline (e.g., libreadline-dev on Debian, readline on MacOS) are installed.
Alternatively, there is another project testing.postgres that allows to use the current Postgres application installed on the server and initialize a new instance.
- Lukmanul Hakim @kimkimkeren

