Skip to content

Commit 7103506

Browse files
Add tests for pyodbc (#796)
* Add tests for pyodbc * Move imports into tests to get import coverage * Fixup: remove time import * Trigger tests --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent 363122a commit 7103506

File tree

4 files changed

+164
-0
lines changed

4 files changed

+164
-0
lines changed

.github/workflows/tests.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,14 @@ jobs:
255255
- uses: actions/checkout@v3
256256
- uses: ./.github/actions/setup-python-matrix
257257

258+
- name: Install odbc driver for postgresql
259+
run: |
260+
sudo apt-get update
261+
sudo sudo apt-get install odbc-postgresql
262+
sudo sed -i 's/Driver=psqlodbca.so/Driver=\/usr\/lib\/x86_64-linux-gnu\/odbc\/psqlodbca.so/g' /etc/odbcinst.ini
263+
sudo sed -i 's/Driver=psqlodbcw.so/Driver=\/usr\/lib\/x86_64-linux-gnu\/odbc\/psqlodbcw.so/g' /etc/odbcinst.ini
264+
sudo sed -i 's/Setup=libodbcpsqlS.so/Setup=\/usr\/lib\/x86_64-linux-gnu\/odbc\/libodbcpsqlS.so/g' /etc/odbcinst.ini
265+
258266
- name: Get Environments
259267
id: get-envs
260268
run: |

tests/datastore_pyodbc/conftest.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Copyright 2010 New Relic, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from testing_support.fixtures import ( # noqa: F401; pylint: disable=W0611
16+
collector_agent_registration_fixture,
17+
collector_available_fixture,
18+
)
19+
20+
_default_settings = {
21+
"transaction_tracer.explain_threshold": 0.0,
22+
"transaction_tracer.transaction_threshold": 0.0,
23+
"transaction_tracer.stack_trace_threshold": 0.0,
24+
"debug.log_data_collector_payloads": True,
25+
"debug.record_transaction_failure": True,
26+
"debug.log_explain_plan_queries": True,
27+
}
28+
29+
collector_agent_registration = collector_agent_registration_fixture(
30+
app_name="Python Agent Test (datastore_pyodbc)",
31+
default_settings=_default_settings,
32+
linked_applications=["Python Agent Test (datastore)"],
33+
)

tests/datastore_pyodbc/test_pyodbc.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Copyright 2010 New Relic, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import pytest
15+
from testing_support.db_settings import postgresql_settings
16+
from testing_support.validators.validate_database_trace_inputs import (
17+
validate_database_trace_inputs,
18+
)
19+
from testing_support.validators.validate_transaction_metrics import (
20+
validate_transaction_metrics,
21+
)
22+
23+
from newrelic.api.background_task import background_task
24+
25+
DB_SETTINGS = postgresql_settings()[0]
26+
27+
28+
@validate_transaction_metrics(
29+
"test_pyodbc:test_execute_via_cursor",
30+
scoped_metrics=[
31+
("Function/pyodbc:connect", 1),
32+
],
33+
rollup_metrics=[
34+
("Datastore/all", 1),
35+
("Datastore/allOther", 1),
36+
("Datastore/ODBC/all", 1),
37+
("Datastore/ODBC/allOther", 1),
38+
],
39+
background_task=True,
40+
)
41+
@validate_database_trace_inputs(sql_parameters_type=tuple)
42+
@background_task()
43+
def test_execute_via_cursor(pyodbc_driver):
44+
import pyodbc
45+
46+
with pyodbc.connect(
47+
"DRIVER={%s};SERVER=%s;PORT=%s;DATABASE=%s;UID=%s;PWD=%s"
48+
% (
49+
pyodbc_driver,
50+
DB_SETTINGS["host"],
51+
DB_SETTINGS["port"],
52+
DB_SETTINGS["name"],
53+
DB_SETTINGS["user"],
54+
DB_SETTINGS["password"],
55+
)
56+
) as connection:
57+
cursor = connection.cursor()
58+
cursor.execute("""drop table if exists %s""" % DB_SETTINGS["table_name"])
59+
cursor.execute("""create table %s """ % DB_SETTINGS["table_name"] + """(a integer, b real, c text)""")
60+
cursor.executemany(
61+
"""insert into %s """ % DB_SETTINGS["table_name"] + """values (?, ?, ?)""",
62+
[(1, 1.0, "1.0"), (2, 2.2, "2.2"), (3, 3.3, "3.3")],
63+
)
64+
cursor.execute("""select * from %s""" % DB_SETTINGS["table_name"])
65+
for row in cursor:
66+
pass
67+
cursor.execute(
68+
"""update %s """ % DB_SETTINGS["table_name"] + """set a=?, b=?, c=? where a=?""",
69+
(4, 4.0, "4.0", 1),
70+
)
71+
cursor.execute("""delete from %s where a=2""" % DB_SETTINGS["table_name"])
72+
connection.commit()
73+
74+
cursor.execute("SELECT now()")
75+
cursor.execute("SELECT pg_sleep(0.25)")
76+
77+
connection.rollback()
78+
connection.commit()
79+
80+
81+
@validate_transaction_metrics(
82+
"test_pyodbc:test_rollback_on_exception",
83+
scoped_metrics=[
84+
("Function/pyodbc:connect", 1),
85+
],
86+
rollup_metrics=[
87+
("Datastore/all", 1),
88+
("Datastore/allOther", 1),
89+
("Datastore/ODBC/all", 1),
90+
("Datastore/ODBC/allOther", 1),
91+
],
92+
background_task=True,
93+
)
94+
@validate_database_trace_inputs(sql_parameters_type=tuple)
95+
@background_task()
96+
def test_rollback_on_exception(pyodbc_driver):
97+
import pyodbc
98+
99+
with pytest.raises(RuntimeError):
100+
with pyodbc.connect(
101+
"DRIVER={%s};SERVER=%s;PORT=%s;DATABASE=%s;UID=%s;PWD=%s"
102+
% (
103+
pyodbc_driver,
104+
DB_SETTINGS["host"],
105+
DB_SETTINGS["port"],
106+
DB_SETTINGS["name"],
107+
DB_SETTINGS["user"],
108+
DB_SETTINGS["password"],
109+
)
110+
) as connection:
111+
raise RuntimeError("error")
112+
113+
114+
@pytest.fixture
115+
def pyodbc_driver():
116+
import pyodbc
117+
118+
driver_name = "PostgreSQL Unicode"
119+
assert driver_name in pyodbc.drivers()
120+
return driver_name

tox.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ envlist =
8080
postgres-datastore_postgresql-{py37,py38,py39},
8181
postgres-datastore_psycopg2-{py27,py37,py38,py39,py310,py311}-psycopg2latest
8282
postgres-datastore_psycopg2cffi-{py27,pypy,py37,py38,py39,py310,py311}-psycopg2cffilatest,
83+
postgres-datastore_pyodbc-{py27,py37,py311}-pyodbclatest
8384
memcached-datastore_pylibmc-{py27,py37},
8485
memcached-datastore_pymemcache-{py27,py37,py38,py39,py310,py311,pypy,pypy37},
8586
mongodb-datastore_pymongo-{py27,py37,py38,py39,py310,py311,pypy}-pymongo{03},
@@ -231,6 +232,7 @@ deps =
231232
datastore_postgresql: py-postgresql<1.3
232233
datastore_psycopg2-psycopg2latest: psycopg2-binary
233234
datastore_psycopg2cffi-psycopg2cffilatest: psycopg2cffi
235+
datastore_pyodbc-pyodbclatest: pyodbc
234236
datastore_pylibmc: pylibmc
235237
datastore_pymemcache: pymemcache
236238
datastore_pymongo-pymongo03: pymongo<4.0
@@ -434,6 +436,7 @@ changedir =
434436
datastore_mysql: tests/datastore_mysql
435437
datastore_postgresql: tests/datastore_postgresql
436438
datastore_psycopg2: tests/datastore_psycopg2
439+
datastore_pyodbc: tests/datastore_pyodbc
437440
datastore_psycopg2cffi: tests/datastore_psycopg2cffi
438441
datastore_pylibmc: tests/datastore_pylibmc
439442
datastore_pymemcache: tests/datastore_pymemcache

0 commit comments

Comments
 (0)