-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_db.py
164 lines (121 loc) · 6.39 KB
/
test_db.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
from pathlib import Path
from subprocess import CalledProcessError
from unittest.mock import MagicMock
import psycopg
import pytest
from psycopg import ProgrammingError
from psycopg.sql import SQL
from pytest_mock import MockFixture
from ops_data_store.db import DBClient
from ops_data_store.db import Path as DBClientPath
class TestDBClient:
"""Tests for app DB client."""
def test_init(self, caplog: pytest.LogCaptureFixture) -> None:
"""Can be initialised."""
client = DBClient()
assert "Creating DB client." in caplog.text
assert isinstance(client, DBClient)
def test_check_ok(self, caplog: pytest.LogCaptureFixture, mocker: MockFixture) -> None:
"""Check succeeds."""
mock_cursor = MagicMock()
mock_cursor.__enter__.return_value.execute.return_value = (1,)
mock_conn = MagicMock()
mock_conn.__enter__.return_value.cursor.return_value = mock_cursor
mocker.patch("psycopg.connect", return_value=mock_conn)
client = DBClient()
client.check()
assert "Creating DB client." in caplog.text
assert "DB connection ok." in caplog.text
def test_check_fail(self, caplog: pytest.LogCaptureFixture, mocker: MockFixture) -> None:
"""Failed raises error."""
mock_cursor = MagicMock()
mock_cursor.__enter__.return_value.execute.side_effect = ProgrammingError
mock_conn = MagicMock()
mock_conn.__enter__.return_value.cursor.return_value = mock_cursor
mocker.patch("psycopg.connect", return_value=mock_conn)
client = DBClient()
assert "Creating DB client." in caplog.text
with pytest.raises(RuntimeError, match="DB connection failed."):
client.check()
def test_setup_ok(self, caplog: pytest.LogCaptureFixture, mocker: MockFixture) -> None:
"""Setup succeeds."""
mock_cursor = MagicMock()
mock_cursor.__enter__.return_value.fetchone.return_value = (1,)
mock_conn = MagicMock()
mock_conn.__enter__.return_value.cursor.return_value = mock_cursor
mocker.patch("psycopg.connect", return_value=mock_conn)
client = DBClient()
client.setup()
assert "Setting up required database objects." in caplog.text
assert "Setting up required DB extension 'postgis'." in caplog.text
assert "Setting up required DB data type 'ddm_point'." in caplog.text
assert "Setting up required DB function 'generate_ulid'." in caplog.text
def test_setup_extensions_fails(self, caplog: pytest.LogCaptureFixture, mocker: MockFixture) -> None:
"""Failed extensions setup raises error."""
mock_cursor = MagicMock()
mock_cursor.__enter__.return_value.fetchone.return_value = (0,)
mock_conn = MagicMock()
mock_conn.__enter__.return_value.cursor.return_value = mock_cursor
mocker.patch("psycopg.connect", return_value=mock_conn)
client = DBClient()
with pytest.raises(RuntimeError, match="No. Required extension 'postgis' not found."): # noqa: SIM117
with psycopg.connect("") as conn, conn.cursor() as cur:
client._setup_extensions(cur=cur)
def test_setup_data_types_fails(self, caplog: pytest.LogCaptureFixture, mocker: MockFixture) -> None:
"""Failed data types setup raises error."""
mock_cursor = MagicMock()
mock_cursor.__enter__.return_value.fetchone.return_value = (0,)
mock_conn = MagicMock()
mock_conn.__enter__.return_value.cursor.return_value = mock_cursor
mocker.patch("psycopg.connect", return_value=mock_conn)
client = DBClient()
with pytest.raises(RuntimeError, match="No. Required data type 'ddm_point' not found."): # noqa: SIM117
with psycopg.connect("") as conn, conn.cursor() as cur:
client._setup_types(cur=cur)
def test_setup_functions_fails(self, caplog: pytest.LogCaptureFixture, mocker: MockFixture) -> None:
"""Failed functions setup raises error."""
mock_cursor = MagicMock()
mock_cursor.__enter__.return_value.fetchone.return_value = (0,)
mock_conn = MagicMock()
mock_conn.__enter__.return_value.cursor.return_value = mock_cursor
mocker.patch("psycopg.connect", return_value=mock_conn)
client = DBClient()
with pytest.raises(RuntimeError, match="No. Required function 'generate_ulid' not found."): # noqa: SIM117
with psycopg.connect("") as conn, conn.cursor() as cur:
client._setup_functions(cur=cur)
def test_execute(self, mocker: MockFixture):
"""Execute succeeds."""
mock_cursor = MagicMock()
mock_cursor.__enter__.return_value.execute.return_value = None
mock_conn = MagicMock()
mock_conn.__enter__.return_value.cursor.return_value = mock_cursor
mocker.patch("psycopg.connect", return_value=mock_conn)
client = DBClient()
client.execute(query="SELECT 1;")
def test_dump_ok(self, mocker: MockFixture, caplog: pytest.LogCaptureFixture):
"""Dump succeeds."""
mocker.patch("subprocess.run")
mocker.patch.object(DBClientPath, "open", mocker.mock_open())
client = DBClient()
# mock needs to be localised to prevent issues loading config from `.env` files
client.dump(path=Path("/x.sql"))
assert "Dumping controlled datasets via `pg_dump`." in caplog.text
assert "DB dump ok." in caplog.text
def test_dump_fail(self, mocker: MockFixture, caplog: pytest.LogCaptureFixture):
"""Failed dump raises error."""
mocker.patch("subprocess.run", side_effect=CalledProcessError(returncode=1, cmd="x"))
client = DBClient()
with pytest.raises(RuntimeError, match="DB dump failed."):
client.dump(path=Path("/x.sql"))
assert "Dumping controlled datasets via `pg_dump`." in caplog.text
def test_fetch_ok(self, mocker: MockFixture, caplog: pytest.LogCaptureFixture) -> None:
"""Fetch succeeds."""
mock_cursor = MagicMock()
mock_cursor.__enter__.return_value.execute.return_value = (1,)
mock_conn = MagicMock()
mock_conn.__enter__.return_value.cursor.return_value = mock_cursor
mocker.patch("psycopg.connect", return_value=mock_conn)
client = DBClient()
# noinspection PyTypeChecker
client.fetch(query=SQL("SELECT 1;"))
assert "Fetching from database." in caplog.text