https://dagster.io/ logo
Title
p

Phil Dreizen

05/23/2023, 4:17 PM
Hi! I’m trying to implement some unit tests. I think I’m doing it correctly. But, when I have an exception in my unit test, including from an assertion error, I have a series of exceptions from sql alchemy/sqllite that aren’t directly related to my code. I’m wondering if I’m doing something wrong.
During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/phil/code/dagster/.venv/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 763, in _finalize_fairy
    fairy._reset(pool, transaction_was_reset)
  File "/Users/phil/code/dagster/.venv/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 1038, in _reset
    pool._dialect.do_rollback(self)
  File "/Users/phil/code/dagster/.venv/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 683, in do_rollback
    dbapi_connection.rollback()
sqlite3.ProgrammingError: Cannot operate on a closed database.
Full error in thread
FAILED civitech_dagster_tests/test_usvf.py::test_elections - Exception: FORCED
==================================================================== 1 failed, 1 passed, 4 warnings in 3.66s ====================================================================
Exception during reset or similar
Traceback (most recent call last):
  File "/Users/phil/code/dagster/.venv/lib/python3.8/site-packages/dagster/_core/execution/api.py", line 280, in ephemeral_instance_if_missing
    yield ephemeral_instance
GeneratorExit

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/phil/code/dagster/.venv/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 763, in _finalize_fairy
    fairy._reset(pool, transaction_was_reset)
  File "/Users/phil/code/dagster/.venv/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 1038, in _reset
    pool._dialect.do_rollback(self)
  File "/Users/phil/code/dagster/.venv/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 683, in do_rollback
    dbapi_connection.rollback()
sqlite3.ProgrammingError: Cannot operate on a closed database.
Exception during reset or similar
Traceback (most recent call last):
  File "/Users/phil/code/dagster/.venv/lib/python3.8/site-packages/dagster/_core/execution/api.py", line 280, in ephemeral_instance_if_missing
    yield ephemeral_instance
GeneratorExit

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/phil/code/dagster/.venv/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 763, in _finalize_fairy
    fairy._reset(pool, transaction_was_reset)
  File "/Users/phil/code/dagster/.venv/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 1038, in _reset
    pool._dialect.do_rollback(self)
  File "/Users/phil/code/dagster/.venv/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 683, in do_rollback
    dbapi_connection.rollback()
sqlite3.ProgrammingError: Cannot operate on a closed database.
My unit test basically looks like this:
def test_asset():
    mock_api = mock.Mock()

    mock_api.get.return_value = [...]

    expected = [...]
    context = dagster.build_op_context()
    actual = asset(context, the_api=mock_api)

    assert actual == expected
^ Is that the correct way to set up a unit test for an asset?
d

daniel

05/23/2023, 4:25 PM
Does the error go away if you do this instead?
with dagster.build_op_context() as context:
    actual = asset(context, the_api=mock_api)
p

Phil Dreizen

05/23/2023, 4:27 PM
I just gave that a try: I still get the error
d

daniel

05/23/2023, 4:31 PM
OK next try as a workaround:
with DagsterInstance.ephemeral() as instance:
  context = dagster.build_op_context(instance=instance)
  actual = asset(context, the_api=mock_api)
If that fixes it, there may be an underlying resource cleanup issue with our asset invocation API that we can investigate
(you'll need to 'from dagster import DagsterInstance' for that code to work)
p

Phil Dreizen

05/23/2023, 4:37 PM
That worked! Thank you!
d

daniel

05/23/2023, 4:37 PM
Great - I'll see if this is a problem on our end, that workaround likely should not be needed
👍 1
having some trouble reproducing - Does your asset reference context.instance at all? Any chance that is sharable?
oh wait, no i can reproduce, nevermind
although weirdly i can only reproduce if the test fails
i.e. this reproduces but assert True does not:
from dagster import asset, build_op_context


@asset
def my_asset(context):
    pass


def test_asset() -> None:
    print("HELLO")

    expected = [...]
    context = build_op_context()
    actual = my_asset(context)

    assert False
p

Phil Dreizen

05/23/2023, 4:42 PM
Yes: same here: I only get the error if the assert fails (or any exception in the test)
d

daniel

05/23/2023, 4:42 PM
ah I think I see the problem
Is the error failing the test? Or just logspew?
p

Phil Dreizen

05/23/2023, 4:57 PM
I think it’s just logspew mostly
d

daniel

05/23/2023, 5:03 PM
Ah ok - if it's just logspew then I see why that would happen. The reason my workaround works is that it forces python to clean things up in the correct order that takes dependencies into account instead of in a random one
p

Phil Dreizen

05/23/2023, 5:34 PM
Ah, got it. Part of the reason I brought it up was that I wasn’t sure if I was making some kind of error in how I wrote the test