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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy