rkaneko
5 years ago
9 changed files with 340 additions and 2 deletions
-
6.gitignore
-
15Pipfile
-
144Pipfile.lock
-
24README.md
-
25docker-compose.yml
-
6env/test/.env
-
0test/__init__.py
-
72test/dbtest.py
-
50test/test_example.py
@ -1 +1,5 @@ |
|||||
# ignore config |
|
||||
|
.venv/ |
||||
|
|
||||
|
__pycache__ |
||||
|
|
||||
|
.pytest_cache/ |
@ -0,0 +1,15 @@ |
|||||
|
[[source]] |
||||
|
name = "pypi" |
||||
|
url = "https://pypi.org/simple" |
||||
|
verify_ssl = true |
||||
|
|
||||
|
[dev-packages] |
||||
|
pytest = "*" |
||||
|
|
||||
|
[packages] |
||||
|
psycopg2-binary = "*" |
||||
|
|
||||
|
[requires] |
||||
|
python_version = "3.7" |
||||
|
|
||||
|
[scripts] |
@ -0,0 +1,144 @@ |
|||||
|
{ |
||||
|
"_meta": { |
||||
|
"hash": { |
||||
|
"sha256": "2732cd143c656d9b3256de0861c4df2eae10e59286513de09a99222ac596599d" |
||||
|
}, |
||||
|
"pipfile-spec": 6, |
||||
|
"requires": { |
||||
|
"python_version": "3.7" |
||||
|
}, |
||||
|
"sources": [ |
||||
|
{ |
||||
|
"name": "pypi", |
||||
|
"url": "https://pypi.org/simple", |
||||
|
"verify_ssl": true |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
"default": { |
||||
|
"psycopg2-binary": { |
||||
|
"hashes": [ |
||||
|
"sha256:040234f8a4a8dfd692662a8308d78f63f31a97e1c42d2480e5e6810c48966a29", |
||||
|
"sha256:086f7e89ec85a6704db51f68f0dcae432eff9300809723a6e8782c41c2f48e03", |
||||
|
"sha256:18ca813fdb17bc1db73fe61b196b05dd1ca2165b884dd5ec5568877cabf9b039", |
||||
|
"sha256:19dc39616850342a2a6db70559af55b22955f86667b5f652f40c0e99253d9881", |
||||
|
"sha256:2166e770cb98f02ed5ee2b0b569d40db26788e0bf2ec3ae1a0d864ea6f1d8309", |
||||
|
"sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed", |
||||
|
"sha256:3aa773580f85a28ffdf6f862e59cb5a3cc7ef6885121f2de3fca8d6ada4dbf3b", |
||||
|
"sha256:3b5deaa3ee7180585a296af33e14c9b18c218d148e735c7accf78130765a47e3", |
||||
|
"sha256:407af6d7e46593415f216c7f56ba087a9a42bd6dc2ecb86028760aa45b802bd7", |
||||
|
"sha256:4c3c09fb674401f630626310bcaf6cd6285daf0d5e4c26d6e55ca26a2734e39b", |
||||
|
"sha256:4c6717962247445b4f9e21c962ea61d2e884fc17df5ddf5e35863b016f8a1f03", |
||||
|
"sha256:50446fae5681fc99f87e505d4e77c9407e683ab60c555ec302f9ac9bffa61103", |
||||
|
"sha256:5057669b6a66aa9ca118a2a860159f0ee3acf837eda937bdd2a64f3431361a2d", |
||||
|
"sha256:5dd90c5438b4f935c9d01fcbad3620253da89d19c1f5fca9158646407ed7df35", |
||||
|
"sha256:659c815b5b8e2a55193ede2795c1e2349b8011497310bb936da7d4745652823b", |
||||
|
"sha256:69b13fdf12878b10dc6003acc8d0abf3ad93e79813fd5f3812497c1c9fb9be49", |
||||
|
"sha256:7a1cb80e35e1ccea3e11a48afe65d38744a0e0bde88795cc56a4d05b6e4f9d70", |
||||
|
"sha256:7e6e3c52e6732c219c07bd97fff6c088f8df4dae3b79752ee3a817e6f32e177e", |
||||
|
"sha256:7f42a8490c4fe854325504ce7a6e4796b207960dabb2cbafe3c3959cb00d1d7e", |
||||
|
"sha256:84156313f258eafff716b2961644a4483a9be44a5d43551d554844d15d4d224e", |
||||
|
"sha256:8578d6b8192e4c805e85f187bc530d0f52ba86c39172e61cd51f68fddd648103", |
||||
|
"sha256:890167d5091279a27e2505ff0e1fb273f8c48c41d35c5b92adbf4af80e6b2ed6", |
||||
|
"sha256:9aadff9032e967865f9778485571e93908d27dab21d0fdfdec0ca779bb6f8ad9", |
||||
|
"sha256:9f24f383a298a0c0f9b3113b982e21751a8ecde6615494a3f1470eb4a9d70e9e", |
||||
|
"sha256:a73021b44813b5c84eda4a3af5826dd72356a900bac9bd9dd1f0f81ee1c22c2f", |
||||
|
"sha256:afd96845e12638d2c44d213d4810a08f4dc4a563f9a98204b7428e567014b1cd", |
||||
|
"sha256:b73ddf033d8cd4cc9dfed6324b1ad2a89ba52c410ef6877998422fcb9c23e3a8", |
||||
|
"sha256:dbc5cd56fff1a6152ca59445178652756f4e509f672e49ccdf3d79c1043113a4", |
||||
|
"sha256:eac8a3499754790187bb00574ab980df13e754777d346f85e0ff6df929bcd964", |
||||
|
"sha256:eaed1c65f461a959284649e37b5051224f4db6ebdc84e40b5e65f2986f101a08" |
||||
|
], |
||||
|
"index": "pypi", |
||||
|
"version": "==2.8.4" |
||||
|
} |
||||
|
}, |
||||
|
"develop": { |
||||
|
"atomicwrites": { |
||||
|
"hashes": [ |
||||
|
"sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", |
||||
|
"sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" |
||||
|
], |
||||
|
"version": "==1.3.0" |
||||
|
}, |
||||
|
"attrs": { |
||||
|
"hashes": [ |
||||
|
"sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", |
||||
|
"sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" |
||||
|
], |
||||
|
"version": "==19.3.0" |
||||
|
}, |
||||
|
"importlib-metadata": { |
||||
|
"hashes": [ |
||||
|
"sha256:aa18d7378b00b40847790e7c27e11673d7fed219354109d0e7b9e5b25dc3ad26", |
||||
|
"sha256:d5f18a79777f3aa179c145737780282e27b508fc8fd688cb17c7a813e8bd39af" |
||||
|
], |
||||
|
"markers": "python_version < '3.8'", |
||||
|
"version": "==0.23" |
||||
|
}, |
||||
|
"more-itertools": { |
||||
|
"hashes": [ |
||||
|
"sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", |
||||
|
"sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" |
||||
|
], |
||||
|
"version": "==7.2.0" |
||||
|
}, |
||||
|
"packaging": { |
||||
|
"hashes": [ |
||||
|
"sha256:28b924174df7a2fa32c1953825ff29c61e2f5e082343165438812f00d3a7fc47", |
||||
|
"sha256:d9551545c6d761f3def1677baf08ab2a3ca17c56879e70fecba2fc4dde4ed108" |
||||
|
], |
||||
|
"version": "==19.2" |
||||
|
}, |
||||
|
"pluggy": { |
||||
|
"hashes": [ |
||||
|
"sha256:0db4b7601aae1d35b4a033282da476845aa19185c1e6964b25cf324b5e4ec3e6", |
||||
|
"sha256:fa5fa1622fa6dd5c030e9cad086fa19ef6a0cf6d7a2d12318e10cb49d6d68f34" |
||||
|
], |
||||
|
"version": "==0.13.0" |
||||
|
}, |
||||
|
"py": { |
||||
|
"hashes": [ |
||||
|
"sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", |
||||
|
"sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" |
||||
|
], |
||||
|
"version": "==1.8.0" |
||||
|
}, |
||||
|
"pyparsing": { |
||||
|
"hashes": [ |
||||
|
"sha256:4acadc9a2b96c19fe00932a38ca63e601180c39a189a696abce1eaab641447e1", |
||||
|
"sha256:61b5ed888beab19ddccab3478910e2076a6b5a0295dffc43021890e136edf764" |
||||
|
], |
||||
|
"version": "==2.4.4" |
||||
|
}, |
||||
|
"pytest": { |
||||
|
"hashes": [ |
||||
|
"sha256:27abc3fef618a01bebb1f0d6d303d2816a99aa87a5968ebc32fe971be91eb1e6", |
||||
|
"sha256:58cee9e09242937e136dbb3dab466116ba20d6b7828c7620f23947f37eb4dae4" |
||||
|
], |
||||
|
"index": "pypi", |
||||
|
"version": "==5.2.2" |
||||
|
}, |
||||
|
"six": { |
||||
|
"hashes": [ |
||||
|
"sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", |
||||
|
"sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" |
||||
|
], |
||||
|
"version": "==1.13.0" |
||||
|
}, |
||||
|
"wcwidth": { |
||||
|
"hashes": [ |
||||
|
"sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", |
||||
|
"sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" |
||||
|
], |
||||
|
"version": "==0.1.7" |
||||
|
}, |
||||
|
"zipp": { |
||||
|
"hashes": [ |
||||
|
"sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", |
||||
|
"sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335" |
||||
|
], |
||||
|
"version": "==0.6.0" |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
POSTGRES_USER=postgres |
||||
|
POSTGRES_PASSWORD=password |
||||
|
POSTGRES_DB=test |
||||
|
POSTGRES_HOST=postgres |
||||
|
POSTGRES_PORT=5432 |
||||
|
# POSTGIS_MAJOR=2.3 |
@ -0,0 +1,72 @@ |
|||||
|
import unittest |
||||
|
|
||||
|
import functools |
||||
|
import psycopg2 |
||||
|
import os |
||||
|
from typing import Any |
||||
|
|
||||
|
|
||||
|
def dbconnect(func): |
||||
|
@functools.wraps(func) |
||||
|
def inner(*args, **kwargs): |
||||
|
inner.__wrapped__ = func |
||||
|
params = { |
||||
|
"host": "testdb", |
||||
|
"port": 5432, |
||||
|
"dbname": "test", |
||||
|
"user": "postgres", |
||||
|
"password": "password", |
||||
|
} |
||||
|
print(f"Connecting for {params}") |
||||
|
# http://initd.org/psycopg/docs/usage.html#with-statement |
||||
|
conn = None |
||||
|
try: |
||||
|
with psycopg2.connect(**params) as conn: |
||||
|
func(*args, conn=conn, **kwargs) |
||||
|
finally: |
||||
|
if conn: |
||||
|
print(f"Close connection for {params}") |
||||
|
conn.close() |
||||
|
return inner |
||||
|
|
||||
|
|
||||
|
class DbTest(unittest.TestCase): |
||||
|
@dbconnect |
||||
|
def setUp(self, conn): |
||||
|
print("Invoking setUp") |
||||
|
print("Set up database schema") |
||||
|
path_to_schema = os.path.join( |
||||
|
os.path.dirname(__file__), |
||||
|
"..", |
||||
|
"sql", |
||||
|
"schema.sql" |
||||
|
) |
||||
|
with conn.cursor() as cur: |
||||
|
cur.execute("CREATE SCHEMA IF NOT EXISTS public;") |
||||
|
schema_sql = self.read_file(path_to_schema) |
||||
|
print(f"Loading {path_to_schema}") |
||||
|
cur.execute(schema_sql) |
||||
|
print(f"Loaded {path_to_schema}") |
||||
|
|
||||
|
@dbconnect |
||||
|
def tearDown(self, conn): |
||||
|
print("Invoking tearDown") |
||||
|
print("Tore down database schema") |
||||
|
with conn.cursor() as cur: |
||||
|
print("Droping schema") |
||||
|
cur.execute("DROP SCHEMA IF EXISTS public CASCADE;") |
||||
|
print("Dropped schema") |
||||
|
|
||||
|
|
||||
|
def load_fixtures(self, conn: Any, *path_to_sqls: str) -> None: |
||||
|
for path_to_sql in path_to_sqls: |
||||
|
sql = self.read_file(path_to_sql) |
||||
|
with conn.cursor() as cur: |
||||
|
print(f"Executing {path_to_sql}") |
||||
|
cur.execute(sql) |
||||
|
print(f"Executed {path_to_sql}") |
||||
|
|
||||
|
|
||||
|
def read_file(self, path_to_file: str) -> str: |
||||
|
with open(path_to_file, "r") as f: |
||||
|
return f.read() |
@ -0,0 +1,50 @@ |
|||||
|
from .dbtest import ( |
||||
|
DbTest, |
||||
|
dbconnect |
||||
|
) |
||||
|
|
||||
|
import os |
||||
|
from psycopg2.extras import RealDictCursor |
||||
|
|
||||
|
|
||||
|
PATH_TO_SQL_DIR = os.path.abspath( |
||||
|
os.path.join( |
||||
|
os.path.dirname(__file__), |
||||
|
"..", |
||||
|
"sql" |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
class TestExample(DbTest): |
||||
|
@dbconnect |
||||
|
def test_select_organizations(self, conn): |
||||
|
self.load_fixtures( |
||||
|
conn, |
||||
|
os.path.join(PATH_TO_SQL_DIR, "organizations.sql") |
||||
|
) |
||||
|
|
||||
|
sql = """ |
||||
|
SELECT * FROM organizations; |
||||
|
""" |
||||
|
with conn.cursor(cursor_factory=RealDictCursor) as cur: |
||||
|
cur.execute(sql) |
||||
|
organizations = cur.fetchall() |
||||
|
|
||||
|
assert len(organizations) == 7 |
||||
|
|
||||
|
|
||||
|
@dbconnect |
||||
|
def test_select_addresses(self, conn): |
||||
|
self.load_fixtures( |
||||
|
conn, |
||||
|
os.path.join(PATH_TO_SQL_DIR, "organizations.sql") |
||||
|
) |
||||
|
|
||||
|
sql = """ |
||||
|
SELECT * FROM addresses; |
||||
|
""" |
||||
|
with conn.cursor(cursor_factory=RealDictCursor) as cur: |
||||
|
cur.execute(sql) |
||||
|
addresses = cur.fetchall() |
||||
|
|
||||
|
assert len(addresses) == 7 |
Write
Preview
Loading…
Cancel
Save
Reference in new issue