@@ -37,80 +37,34 @@ python my_tests.py
3737```
3838
3939
40- ###Logging
41-
42- By default,` cleanup() ` removes all temporary files (DB files, logs etc) that were created by testgres' API methods.
43- If you'd like to keep logs, execute` configure_testgres(node_cleanup_full=False) ` before running any tests.
44-
45- > Note: context managers (aka` with ` ) call` stop() ` and` cleanup() ` automatically.
46-
47- testgres supports[ python logging] ( https://docs.python.org/3.6/library/logging.html ) ,
48- which means that you can aggregate logs from several nodes into one file:
49-
50- ``` python
51- import logging
52-
53- # write everything to /tmp/testgres.log
54- logging.basicConfig(filename = ' /tmp/testgres.log' )
55-
56- # create two different nodes with logging
57- node1= testgres.get_new_node(use_logging = True ).init().start()
58- node2= testgres.get_new_node(use_logging = True ).init().start()
59-
60- # execute a few queries
61- node1.execute(' postgres' ,' select 1' )
62- node2.execute(' postgres' ,' select 2' )
63- ```
64-
65-
6640###Examples
6741
6842Here is an example of what you can do with` testgres ` :
6943
7044``` python
71- with testgres.get_new_node(' test' )as node:
72- node.init()# run initdb
73- node.start()# start PostgreSQL
74- print (node.execute(' postgres' ,' select 1' ))
75- node.stop()# stop PostgreSQL
76- ```
77-
78- Let's walk through the code. First, you create a new node using:
79-
80- ``` python
81- with testgres.get_new_node(' master' )as node:
82- ```
83-
84- or
85-
86- ``` python
87- with testgres.get_new_node(' master' ,' /path/to/DB' )as node:
88- ```
45+ # create a node with random name, port, etc
46+ with testgres.get_new_node()as node:
8947
90- where` master ` is a node's application name. Name matters if you're testing something like replication.
91- Function` get_new_node() ` only creates directory structure in specified directory (or somewhere in '/tmp' if
92- we did not specify base directory) for cluster. After that, we have to initialize the PostgreSQL cluster:
48+ # run inidb
49+ node.init()
9350
94- ``` python
95- node.init()
96- ```
51+ # start PostgreSQL
52+ node.start()
9753
98- This function runs` initdb ` command and adds some basic configuration to` postgresql.conf ` and` pg_hba.conf ` files.
99- Function` init() ` accepts optional parameter` allows_streaming ` which configures cluster for streaming replication (default is` False ` ).
100- Now we are ready to start:
54+ # execute a query in a default DB
55+ print (node.execute(' select 1' ))
10156
102- ``` python
103- node.start()
57+ # ... node stops and its files are about to be removed
10458```
10559
106- Finally, our temporary cluster is able to process queries. There are fourways to run them :
60+ There are fourAPI methods for runnig queries :
10761
10862| Command| Description|
10963| ----------------------------------| -----------------------------------------------------------------------------------------------------------------------------------------------------|
110- | ` node.psql(dbname, query ) ` | Runs query via` psql ` command and returns tuple` (error code, stdout, stderr) ` .|
111- | ` node.safe_psql(dbname, query ) ` | Same as` psql() ` except that it returns only` stdout ` . If an error occures during the execution, an exception will be thrown.|
112- | ` node.execute(dbname, query ) ` | Connects to PostgreSQL using` psycopg2 ` or` pg8000 ` (depends on which one is installed in your system) and returns two-dimensional array with data.|
113- | ` node.connect(dbname,username ) ` | Returns connection wrapper (` NodeConnection ` ) capable of running several queries within a single transaction.|
64+ | ` node.psql(query, ... ) ` | Runs query via` psql ` command and returns tuple` (error code, stdout, stderr) ` .|
65+ | ` node.safe_psql(query, ... ) ` | Same as` psql() ` except that it returns only` stdout ` . If an error occures during the execution, an exception will be thrown.|
66+ | ` node.execute(query, ... ) ` | Connects to PostgreSQL using` psycopg2 ` or` pg8000 ` (depends on which one is installed in your system) and returns two-dimensional array with data.|
67+ | ` node.connect(dbname,... ) ` | Returns connection wrapper (` NodeConnection ` ) capable of running several queries within a single transaction.|
11468
11569The last one is the most powerful: you can use` begin(isolation_level) ` ,` commit() ` and` rollback() ` :
11670``` python
@@ -120,12 +74,39 @@ with node.connect() as con:
12074 con.rollback()
12175```
12276
123- To stop the server, run:
77+
78+ ###Logging
79+
80+ By default,` cleanup() ` removes all temporary files (DB files, logs etc) that were created by testgres' API methods.
81+ If you'd like to keep logs, execute` configure_testgres(node_cleanup_full=False) ` before running any tests.
82+
83+ > Note: context managers (aka` with ` ) call` stop() ` and` cleanup() ` automatically.
84+
85+ ` testgres ` supports[ python logging] ( https://docs.python.org/3.6/library/logging.html ) ,
86+ which means that you can aggregate logs from several nodes into one file:
12487
12588``` python
126- node.stop()
89+ import logging
90+
91+ # write everything to /tmp/testgres.log
92+ logging.basicConfig(filename = ' /tmp/testgres.log' )
93+
94+ # enable logging, and create two different nodes
95+ testgres.configure_testgres(enable_python_logging = True )
96+ node1= testgres.get_new_node().init().start()
97+ node2= testgres.get_new_node().init().start()
98+
99+ # execute a few queries
100+ node1.execute(' select 1' )
101+ node2.execute(' select 2' )
102+
103+ # disable logging
104+ testgres.configure_testgres(enable_python_logging = False )
127105```
128106
107+ Look at` tests/test_simple.py ` file for a complete example of the logging
108+ configuration.
109+
129110
130111###Backup & replication
131112
@@ -134,7 +115,10 @@ It's quite easy to create a backup and start a new replica:
134115``` python
135116with testgres.get_new_node(' master' )as master:
136117 master.init().start()
118+
119+ # create a backup
137120with master.backup()as backup:
121+
138122# create and start a new replica
139123 replica= backup.spawn_replica(' replica' ).start()
140124
@@ -147,7 +131,7 @@ with testgres.get_new_node('master') as master:
147131
148132###Benchmarks
149133
150- ` testgres ` alsocan help you to make benchmarks using` pgbench ` from postgres installation :
134+ ` testgres ` is alsocapable of running benchmarks using` pgbench ` :
151135
152136``` python
153137with testgres.get_new_node(' master' )as master:
@@ -160,9 +144,37 @@ with testgres.get_new_node('master') as master:
160144```
161145
162146
147+ ###Custom configuration
148+
149+ It's often useful to extend default configuration provided by` testgres ` .
150+
151+ ` testgres ` has` default_conf() ` function that helps control some basic
152+ options. The` append_conf() ` function can be used to add custom
153+ lines to configuration lines:
154+
155+ ``` python
156+ ext_conf= " shared_preload_libraries = 'postgres_fdw'"
157+
158+ # initialize a new node
159+ with testgres.get_new_node().init()as master:
160+
161+ # ... do something ...
162+
163+ # reset main config file
164+ master.default_conf(fsync = True ,
165+ allow_streaming = True )
166+
167+ # add a new config line
168+ master.append_conf(' postgresql.conf' , ext_conf)
169+ ```
170+
171+ Note that` default_conf() ` is called by` init() ` function; both of them overwrite
172+ the configuration file, which means that they should be called before` append_conf() ` .
173+
174+
163175##Authors
164176
165- [ Ildar Musin] ( https://github.com/zilder ) <i.musin(at)postgrespro.ru> Postgres Professional Ltd., Russia
166- [ Dmitry Ivanov] ( https://github.com/funbringer ) <d.ivanov(at)postgrespro.ru> Postgres Professional Ltd., Russia
167- [ Ildus Kurbangaliev] ( https://github.com/ildus ) <i.kurbangaliev(at)postgrespro.ru> Postgres Professional Ltd., Russia
177+ [ Ildar Musin] ( https://github.com/zilder ) <i.musin(at)postgrespro.ru> Postgres Professional Ltd., Russia
178+ [ Dmitry Ivanov] ( https://github.com/funbringer ) <d.ivanov(at)postgrespro.ru> Postgres Professional Ltd., Russia
179+ [ Ildus Kurbangaliev] ( https://github.com/ildus ) <i.kurbangaliev(at)postgrespro.ru> Postgres Professional Ltd., Russia
168180[ Yury Zhuravlev] ( https://github.com/stalkerg ) <stalkerg(at)gmail.com>