@@ -37,80 +37,34 @@ python my_tests.py
37
37
```
38
38
39
39
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
-
66
40
###Examples
67
41
68
42
Here is an example of what you can do with` testgres ` :
69
43
70
44
``` 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:
89
47
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()
93
50
94
- ``` python
95
- node.init()
96
- ```
51
+ # start PostgreSQL
52
+ node.start()
97
53
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' ))
101
56
102
- ``` python
103
- node.start()
57
+ # ... node stops and its files are about to be removed
104
58
```
105
59
106
- Finally, our temporary cluster is able to process queries. There are fourways to run them :
60
+ There are fourAPI methods for runnig queries :
107
61
108
62
| Command| Description|
109
63
| ----------------------------------| -----------------------------------------------------------------------------------------------------------------------------------------------------|
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.|
114
68
115
69
The last one is the most powerful: you can use` begin(isolation_level) ` ,` commit() ` and` rollback() ` :
116
70
``` python
@@ -120,12 +74,39 @@ with node.connect() as con:
120
74
con.rollback()
121
75
```
122
76
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:
124
87
125
88
``` 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 )
127
105
```
128
106
107
+ Look at` tests/test_simple.py ` file for a complete example of the logging
108
+ configuration.
109
+
129
110
130
111
###Backup & replication
131
112
@@ -134,7 +115,10 @@ It's quite easy to create a backup and start a new replica:
134
115
``` python
135
116
with testgres.get_new_node(' master' )as master:
136
117
master.init().start()
118
+
119
+ # create a backup
137
120
with master.backup()as backup:
121
+
138
122
# create and start a new replica
139
123
replica= backup.spawn_replica(' replica' ).start()
140
124
@@ -147,7 +131,7 @@ with testgres.get_new_node('master') as master:
147
131
148
132
###Benchmarks
149
133
150
- ` testgres ` alsocan help you to make benchmarks using` pgbench ` from postgres installation :
134
+ ` testgres ` is alsocapable of running benchmarks using` pgbench ` :
151
135
152
136
``` python
153
137
with testgres.get_new_node(' master' )as master:
@@ -160,9 +144,37 @@ with testgres.get_new_node('master') as master:
160
144
```
161
145
162
146
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
+
163
175
##Authors
164
176
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
168
180
[ Yury Zhuravlev] ( https://github.com/stalkerg ) <stalkerg(at)gmail.com>