Skip to content

Remove test dependency coupling for testing UUID retrieval #1474

Description

@bkline

Expected

A unit test should succeed when run separately from the rest of the test suite in which it is contained.

Observed

The test_sql_variant test in tests/sqlserver_test.py fails when run independently.

% pytest tests/sqlserver_test.py
============================================= test session starts ==============================================
platform darwin -- Python 3.14.0, pytest-9.0.2, pluggy-1.6.0
rootdir: /Users/bkline/repos/pyodbc
configfile: pyproject.toml
collected 98 items

tests/sqlserver_test.py ................................................................................ [ 81%]
..................                                                                                       [100%]

============================================== 98 passed in 3.41s ==============================================
% pytest tests/sqlserver_test.py::test_sql_variant
============================================= test session starts ==============================================
platform darwin -- Python 3.14.0, pytest-9.0.2, pluggy-1.6.0
rootdir: /Users/bkline/repos/pyodbc
configfile: pyproject.toml
collected 1 item

tests/sqlserver_test.py F

=================================================== FAILURES ===================================================
_______________________________________________ test_sql_variant _______________________________________________

cursor = <pyodbc.Cursor object at 0x1075e7830>

    @pytest.mark.skipif(SQLSERVER_YEAR < 2000, reason='sql_variant not supported until 2000')
    def test_sql_variant(cursor: pyodbc.Cursor):
        """
        Tests decoding of the sql_variant data type as performed by the GetData_SqlVariant() method.
        """

        cursor.execute("create table t1 (a sql_variant)")

        # insert a number of values of disparate types. this is not exhaustive as not all
        # types that can be contained within a sql_variant field are supported by pyodbc
        cursor.execute("insert into t1 values (456.7)")
        cursor.execute("insert into t1 values ('a string')")
        cursor.execute("insert into t1 values (CAST('2024-06-03' AS DATE))")
        cursor.execute("insert into t1 values (CAST('2024-06-03 23:46:03.000' AS DATETIME))")
        cursor.execute("insert into t1 values (CAST('binary data' AS VARBINARY(200)))")
        cursor.execute(
            "insert into t1 values (CAST('0592b437-745f-4b2c-a997-97022c624cf6' AS UNIQUEIDENTIFIER))"
        )

        # select all of the values we inserted and ensure they have the correct types
        results = [record[0] for record in cursor.execute("select a from t1").fetchall()]
        for index, assertion_tuple in enumerate(
            [
                (Decimal, Decimal("456.7")),
                (str, "a string"),
                (date, date(2024, 6, 3)),
                (datetime, datetime(2024, 6, 3, 23, 46, 3)),
                (bytes, b'binary data'),
                (uuid.UUID, uuid.UUID("0592b437-745f-4b2c-a997-97022c624cf6"))
            ]
        ):
            # pylint: disable=unidiomatic-typecheck
            expected_type, expected_value = assertion_tuple

>           assert type(results[index]) is expected_type
E           AssertionError: assert <class 'str'> is <class 'uuid.UUID'>
E            +  where <class 'str'> = type('0592B437-745F-4B2C-A997-97022C624CF6')

tests/sqlserver_test.py:1682: AssertionError
=========================================== short test summary info ============================================
FAILED tests/sqlserver_test.py::test_sql_variant - AssertionError: assert <class 'str'> is <class 'uuid.UUID'>
============================================== 1 failed in 0.27s ===============================================

Environment

Component Version
pyodbc 5.3.0
Database Microsoft SQL Server 2022 (RTM-CU24) (KB5080999) - 16.0.4245.2 (X64)
OS macOS 26.3.1, Ubuntu 24.04, and Windows 11 [10.0.26200.8037]

Analysis

The documentation says

native_uuid
A Boolean that determines whether SQL_GUID columns, e.g. UNIQUEIDENTIFIER or UUID, are returned as text (with False, the default) or as uuid.UUID objects (with True). The default is False for backwards compatibility, but this may change in a future release.

Several tests modify pyodbc.native_uuid without restoring it to its original value. The implementation of test_sql_variant assumes that the last of those tests to have run will have left the flag turned on. That doesn't necessarily happen when the tests to be executed for a given run are specified explicitly, thus the failure of test_sql_variant. To add to the confusion, the comments on the tests disagree about what the default value is for the property, claiming False as the default in some places, but True elsewhere. One comment even claims that the flag will be reset, which never happens.

Remedy

  • Explicitly set pyodbc.native_uuid to the value assumed by the test wherever that value can affect the test's observed behavior.
  • Always save the original value of pyodbc.native_uuid before assigning a (possibly new) value.
  • Always restore the original value of pyodbc.native_uuid when it has been explicitly assigned for a test.
  • Remove comments identifying the default for pyodbc.native_uuid (which may change at some point) from the tests.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions