Skip to content

Commit e01e0d1

Browse files
Add unit tests for async module (AsyncConnection, AsyncCursor)
The async module had zero test coverage. Add tests for state management, closed checks, context managers, iteration, and fetch behavior mirroring the sync test structure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 022ef15 commit e01e0d1

File tree

2 files changed

+153
-0
lines changed

2 files changed

+153
-0
lines changed

tests/test_async_connection.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""Tests for AsyncConnection class."""
2+
3+
import pytest
4+
5+
from dqlitedbapi.aio import connect
6+
from dqlitedbapi.aio.connection import AsyncConnection
7+
from dqlitedbapi.aio.cursor import AsyncCursor
8+
from dqlitedbapi.exceptions import InterfaceError
9+
10+
11+
class TestAsyncConnection:
12+
def test_connect_function_returns_async_connection(self) -> None:
13+
conn = connect("localhost:9001", database="test", timeout=5.0)
14+
assert isinstance(conn, AsyncConnection)
15+
16+
def test_cursor_returns_async_cursor(self) -> None:
17+
conn = AsyncConnection("localhost:9001")
18+
cursor = conn.cursor()
19+
assert isinstance(cursor, AsyncCursor)
20+
21+
@pytest.mark.asyncio
22+
async def test_close_marks_connection_closed(self) -> None:
23+
conn = AsyncConnection("localhost:9001")
24+
await conn.close()
25+
assert conn._closed
26+
27+
@pytest.mark.asyncio
28+
async def test_cursor_on_closed_connection_raises(self) -> None:
29+
conn = AsyncConnection("localhost:9001")
30+
await conn.close()
31+
32+
with pytest.raises(InterfaceError, match="Connection is closed"):
33+
conn.cursor()
34+
35+
@pytest.mark.asyncio
36+
async def test_commit_on_closed_connection_raises(self) -> None:
37+
conn = AsyncConnection("localhost:9001")
38+
await conn.close()
39+
40+
with pytest.raises(InterfaceError, match="Connection is closed"):
41+
await conn.commit()
42+
43+
@pytest.mark.asyncio
44+
async def test_rollback_on_closed_connection_raises(self) -> None:
45+
conn = AsyncConnection("localhost:9001")
46+
await conn.close()
47+
48+
with pytest.raises(InterfaceError, match="Connection is closed"):
49+
await conn.rollback()
50+
51+
def test_cursor_is_sync(self) -> None:
52+
"""cursor() is intentionally sync for SQLAlchemy compatibility."""
53+
conn = AsyncConnection("localhost:9001")
54+
cursor = conn.cursor()
55+
# Verify it returns directly, not a coroutine
56+
assert isinstance(cursor, AsyncCursor)

tests/test_async_cursor.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
"""Tests for AsyncCursor class."""
2+
3+
import pytest
4+
5+
from dqlitedbapi.aio.connection import AsyncConnection
6+
from dqlitedbapi.aio.cursor import AsyncCursor
7+
from dqlitedbapi.exceptions import InterfaceError
8+
9+
10+
class TestAsyncCursor:
11+
def test_description_initially_none(self) -> None:
12+
conn = AsyncConnection("localhost:9001")
13+
cursor = AsyncCursor(conn)
14+
assert cursor.description is None
15+
16+
def test_rowcount_initially_minus_one(self) -> None:
17+
conn = AsyncConnection("localhost:9001")
18+
cursor = AsyncCursor(conn)
19+
assert cursor.rowcount == -1
20+
21+
def test_arraysize_default(self) -> None:
22+
conn = AsyncConnection("localhost:9001")
23+
cursor = AsyncCursor(conn)
24+
assert cursor.arraysize == 1
25+
26+
def test_arraysize_setter(self) -> None:
27+
conn = AsyncConnection("localhost:9001")
28+
cursor = AsyncCursor(conn)
29+
cursor.arraysize = 10
30+
assert cursor.arraysize == 10
31+
32+
def test_lastrowid_initially_none(self) -> None:
33+
conn = AsyncConnection("localhost:9001")
34+
cursor = AsyncCursor(conn)
35+
assert cursor.lastrowid is None
36+
37+
@pytest.mark.asyncio
38+
async def test_close_marks_cursor_closed(self) -> None:
39+
conn = AsyncConnection("localhost:9001")
40+
cursor = AsyncCursor(conn)
41+
await cursor.close()
42+
assert cursor._closed
43+
44+
@pytest.mark.asyncio
45+
async def test_fetchone_on_closed_cursor_raises(self) -> None:
46+
conn = AsyncConnection("localhost:9001")
47+
cursor = AsyncCursor(conn)
48+
await cursor.close()
49+
50+
with pytest.raises(InterfaceError, match="Cursor is closed"):
51+
await cursor.fetchone()
52+
53+
@pytest.mark.asyncio
54+
async def test_fetchone_no_rows_returns_none(self) -> None:
55+
conn = AsyncConnection("localhost:9001")
56+
cursor = AsyncCursor(conn)
57+
# Simulate a query that returned zero rows
58+
cursor._description = [("id", None, None, None, None, None, None)]
59+
cursor._rows = []
60+
result = await cursor.fetchone()
61+
assert result is None
62+
63+
@pytest.mark.asyncio
64+
async def test_fetchall_no_rows_returns_empty(self) -> None:
65+
conn = AsyncConnection("localhost:9001")
66+
cursor = AsyncCursor(conn)
67+
cursor._description = [("id", None, None, None, None, None, None)]
68+
cursor._rows = []
69+
result = await cursor.fetchall()
70+
assert result == []
71+
72+
@pytest.mark.asyncio
73+
async def test_context_manager(self) -> None:
74+
conn = AsyncConnection("localhost:9001")
75+
async with AsyncCursor(conn) as cursor:
76+
assert not cursor._closed
77+
assert cursor._closed
78+
79+
@pytest.mark.asyncio
80+
async def test_async_iterator(self) -> None:
81+
conn = AsyncConnection("localhost:9001")
82+
cursor = AsyncCursor(conn)
83+
cursor._rows = [(1, "a"), (2, "b"), (3, "c")]
84+
cursor._description = [("id", None, None, None, None, None, None)]
85+
86+
results = [row async for row in cursor]
87+
assert results == [(1, "a"), (2, "b"), (3, "c")]
88+
89+
def test_setinputsizes_noop(self) -> None:
90+
conn = AsyncConnection("localhost:9001")
91+
cursor = AsyncCursor(conn)
92+
cursor.setinputsizes([None, None])
93+
94+
def test_setoutputsize_noop(self) -> None:
95+
conn = AsyncConnection("localhost:9001")
96+
cursor = AsyncCursor(conn)
97+
cursor.setoutputsize(100, 0)

0 commit comments

Comments
 (0)