Developer guide#

Unit testing#

Magics (e.g., %sql, %%sql, etc)#

This guide will show you the basics of writing unit tests for JupySQL magics. Magics are commands that begin with % (line magics) and %% (cell magics).

In the unit testing suite, there are a few pytest fixtures that prepare the environment so you can get started:

  • ip_empty - Empty IPython session

  • ip - IPython session with some sample data

So a typical test will look like this:

def test_something(ip):
    ip.run_cell("%sql sqlite://")
    result = ip.run_cell(
        """%%sql
    SELECT * FROM test
    """
    )

    assert result.success

To see some sample tests, click here.

The IPython sessions are created like this:

from IPython.core.interactiveshell import InteractiveShell
from sql.magic import SqlMagic

ip_session = InteractiveShell()
ip_session.register_magics(SqlMagic)

To run some code:

out = ip_session.run_cell("1 + 1")
Out[1]: 2

To test the output:

assert out.result == 2

You can also check for execution success:

assert out.success

Important

Always check for success! Since run_cell won’t raise an error if the code fails

try:
    ip_session.run_cell("1 / 0")
except Exception as e:
    print(f"Error: {e}")
else:
    print("No error")
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
File <ipython-input-1-bc757c3fda29>:1
----> 1 1 / 0

ZeroDivisionError: division by zero
No error

Note that the run_cell only printed the error but did not raise an exception.

Capturing errors#

Let’s see how to test that the code raises an expected error:

out = ip_session.run_cell("1 / 0")
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
File <ipython-input-1-bc757c3fda29>:1
----> 1 1 / 0

ZeroDivisionError: division by zero
# this returns the raised exception
out.error_in_exec
ZeroDivisionError('division by zero')
# this raises the error
out.raise_error()
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[9], line 2
      1 # this raises the error
----> 2 out.raise_error()

File ~/checkouts/readthedocs.org/user_builds/jupysql/conda/latest/lib/python3.10/site-packages/IPython/core/interactiveshell.py:266, in ExecutionResult.raise_error(self)
    264     raise self.error_before_exec
    265 if self.error_in_exec is not None:
--> 266     raise self.error_in_exec

    [... skipping hidden 1 frame]

File <ipython-input-1-bc757c3fda29>:1
----> 1 1 / 0

ZeroDivisionError: division by zero

You can then use pytest to check the error:

import pytest
with pytest.raises(ZeroDivisionError):
    out.raise_error()

To check the error message:

with pytest.raises(ZeroDivisionError) as excinfo:
    out.raise_error()
assert str(excinfo.value) == "division by zero"