๐ญ Iโm currently working for @datazone
๐ฌ Ask me about Python
resulyrt93 / pytest-sqlalchemy-mock Goto Github PK
View Code? Open in Web Editor NEWpytest plugin to mock sqlalchemy models
License: MIT License
pytest plugin to mock sqlalchemy models
License: MIT License
I noticed errors running tests with pytest after upgrading from 0.1.5 to 0.1.6:
E fixture 'mocked_session' not found
Instead of sharing a full project having the issue, the problem can be seen by installing the package and running pytest --fixtures
. This example uses pyenv to create a virtual environment called "test", using python 3.12.4.
pyenv virtualenv-delete test # if the env exists
pyenv virtualenv 3.12.4 test
pyenv activate test
pip install pytest-sqlalchemy-mock==0.1.5 # or 0.1.6
pytest --fixtures
plugins: sqlalchemy-mock-0.1.5
fixtures defined from pytest_sqlalchemy_mock.base
Here's the full output:
0.1.5
:=============================================================================================== test session starts ===============================================================================================
platform darwin -- Python 3.12.4, pytest-8.2.2, pluggy-1.5.0
rootdir: /private/tmp
plugins: sqlalchemy-mock-0.1.5
collected 0 items
cache -- .../_pytest/cacheprovider.py:560
Return a cache object that can persist state between testing sessions.
capsysbinary -- .../_pytest/capture.py:1003
Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.
capfd -- .../_pytest/capture.py:1030
Enable text capturing of writes to file descriptors ``1`` and ``2``.
capfdbinary -- .../_pytest/capture.py:1057
Enable bytes capturing of writes to file descriptors ``1`` and ``2``.
capsys -- .../_pytest/capture.py:976
Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.
doctest_namespace [session scope] -- .../_pytest/doctest.py:738
Fixture that returns a :py:class:`dict` that will be injected into the
namespace of doctests.
pytestconfig [session scope] -- .../_pytest/fixtures.py:1338
Session-scoped fixture that returns the session's :class:`pytest.Config`
object.
record_property -- .../_pytest/junitxml.py:284
Add extra properties to the calling test.
record_xml_attribute -- .../_pytest/junitxml.py:307
Add extra xml attributes to the tag for the calling test.
record_testsuite_property [session scope] -- .../_pytest/junitxml.py:345
Record a new ``<property>`` tag as child of the root ``<testsuite>``.
tmpdir_factory [session scope] -- .../_pytest/legacypath.py:303
Return a :class:`pytest.TempdirFactory` instance for the test session.
tmpdir -- .../_pytest/legacypath.py:310
Return a temporary directory path object which is unique to each test
function invocation, created as a sub directory of the base temporary
directory.
caplog -- .../_pytest/logging.py:602
Access and control log capturing.
monkeypatch -- .../_pytest/monkeypatch.py:33
A convenient fixture for monkey-patching.
recwarn -- .../_pytest/recwarn.py:32
Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions.
tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:242
Return a :class:`pytest.TempPathFactory` instance for the test session.
tmp_path -- .../_pytest/tmpdir.py:257
Return a temporary directory path object which is unique to each test
function invocation, created as a sub directory of the base temporary
directory.
-------------------------------------------------------------------------------- fixtures defined from pytest_sqlalchemy_mock.base --------------------------------------------------------------------------------
connection_url [session scope] -- ../../Users/calvarez/.pyenv/versions/3.12.4/envs/test/lib/python3.12/site-packages/pytest_sqlalchemy_mock/base.py:14
no docstring available
engine -- ../../Users/calvarez/.pyenv/versions/3.12.4/envs/test/lib/python3.12/site-packages/pytest_sqlalchemy_mock/base.py:19
no docstring available
sqlalchemy_declarative_base -- ../../Users/calvarez/.pyenv/versions/3.12.4/envs/test/lib/python3.12/site-packages/pytest_sqlalchemy_mock/base.py:24
no docstring available
sqlalchemy_mock_config -- ../../Users/calvarez/.pyenv/versions/3.12.4/envs/test/lib/python3.12/site-packages/pytest_sqlalchemy_mock/base.py:29
no docstring available
connection -- ../../Users/calvarez/.pyenv/versions/3.12.4/envs/test/lib/python3.12/site-packages/pytest_sqlalchemy_mock/base.py:34
no docstring available
session -- ../../Users/calvarez/.pyenv/versions/3.12.4/envs/test/lib/python3.12/site-packages/pytest_sqlalchemy_mock/base.py:41
no docstring available
mocked_session -- ../../Users/calvarez/.pyenv/versions/3.12.4/envs/test/lib/python3.12/site-packages/pytest_sqlalchemy_mock/base.py:48
no docstring available
============================================================================================== no tests ran in 0.16s ==============================================================================================
0.1.6
:============================================================================================== test session starts ==============================================================================================
platform darwin -- Python 3.12.4, pytest-8.2.2, pluggy-1.5.0
rootdir: /private/tmp
collected 0 items
cache -- .../_pytest/cacheprovider.py:560
Return a cache object that can persist state between testing sessions.
capsysbinary -- .../_pytest/capture.py:1003
Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.
capfd -- .../_pytest/capture.py:1030
Enable text capturing of writes to file descriptors ``1`` and ``2``.
capfdbinary -- .../_pytest/capture.py:1057
Enable bytes capturing of writes to file descriptors ``1`` and ``2``.
capsys -- .../_pytest/capture.py:976
Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.
doctest_namespace [session scope] -- .../_pytest/doctest.py:738
Fixture that returns a :py:class:`dict` that will be injected into the
namespace of doctests.
pytestconfig [session scope] -- .../_pytest/fixtures.py:1338
Session-scoped fixture that returns the session's :class:`pytest.Config`
object.
record_property -- .../_pytest/junitxml.py:284
Add extra properties to the calling test.
record_xml_attribute -- .../_pytest/junitxml.py:307
Add extra xml attributes to the tag for the calling test.
record_testsuite_property [session scope] -- .../_pytest/junitxml.py:345
Record a new ``<property>`` tag as child of the root ``<testsuite>``.
tmpdir_factory [session scope] -- .../_pytest/legacypath.py:303
Return a :class:`pytest.TempdirFactory` instance for the test session.
tmpdir -- .../_pytest/legacypath.py:310
Return a temporary directory path object which is unique to each test
function invocation, created as a sub directory of the base temporary
directory.
caplog -- .../_pytest/logging.py:602
Access and control log capturing.
monkeypatch -- .../_pytest/monkeypatch.py:33
A convenient fixture for monkey-patching.
recwarn -- .../_pytest/recwarn.py:32
Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions.
tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:242
Return a :class:`pytest.TempPathFactory` instance for the test session.
tmp_path -- .../_pytest/tmpdir.py:257
Return a temporary directory path object which is unique to each test
function invocation, created as a sub directory of the base temporary
directory.
============================================================================================= no tests ran in 0.08s =============================================================================================
Great tool โจ
I'm able to get "most" model relationships mocked with this package. I'm running into trouble when mocking "secondary" (through/m2m) relationships in the following schema below. No errors occur on test setup which makes me think the insert into the sqllite is fine (maybe). The problem is that the relationship cannot be resolved and is empty when probed in the example tests below. But other simpler reverse fkey relationships resolve fine.
Any sharp ideas on your end if I'm doing anything wrong here?
orm.Build.package_builds
has a secondary relationship:
https://github.com/Quansight/conda-store/blob/main/conda-store-server/conda_store_server/orm.py#L131
to this manually created m2m/through table:
https://github.com/Quansight/conda-store/blob/main/conda-store-server/conda_store_server/orm.py#L103-L112
import os
import sys
sys.path.append(os.path.join(os.getcwd(), 'conda-store-server'))
import pytest
from conda_store_server import orm, schema
@pytest.fixture(scope="function")
def sqlalchemy_declarative_base():
return orm.Base
@pytest.fixture(scope="function")
def sqlalchemy_mock_config():
return [("build", [
{
"id": 1,
"specification_id": 1,
"environment_id": 1,
"status": schema.BuildStatus.COMPLETED,
},
]),("build_artifact", [
{
"id": 1,
"build_id": 1,
"artifact_type": schema.BuildArtifactType.LOCKFILE
}
]),("build_conda_package_build", [
{
"build_id": 1,
"conda_package_build_id": 1,
},
{
"build_id": 1,
"conda_package_build_id": 2,
},
]),("conda_package_build", [
{
"id": 1,
"package_id": 1,
"channel_id": 1,
"subdir": "linux-64",
"build": "h27087fc_0",
"build_number": 1,
"depends": "[]",
"sha256": "sha256",
"size": 2314454,
"tarball_ext": ".conda",
"md5": "87473a15119779e021c314249d4b4aed",
},
{
"id": 2,
"package_id": 2,
"channel_id": 1,
"subdir": "linux-64",
"build": "pyhd8ed1ab_0",
"build_number": 1,
"depends": "[]",
"sha256": "sha256",
"size": 2314454,
"tarball_ext": ".tar.bz2",
"md5": "37d4251d34eb991ff9e40e546cc2e803",
},
]),("conda_package", [
{
"id": 1,
"channel_id": 1,
"name": "icu",
"version": "70.1",
},
{
"id": 2,
"channel_id": 1,
"name": "zarr",
"version": "2.12.0",
}
]),("conda_channel", [
{
"id": 1,
"name": "https://conda.anaconda.org/conda-forge"
},
])
]
from conda_store_server import orm, schema, api
import sys
def test_mocked_toolchain_example(mocked_session):
# an example making sure the mocking toolchain works
build = mocked_session.query(orm.Build).filter_by(id=1).first()
assert build.status == schema.BuildStatus.COMPLETED
build_artifact = mocked_session.query(orm.BuildArtifact).filter_by(id=1).first()
assert build_artifact.artifact_type == schema.BuildArtifactType.LOCKFILE
# THIS IS SUSPICIOUSLY EMPTY ALWAYS
print(f"[ CPB ]: {build.package_builds}")
# BUT OTHER M2O RELATIONSHIPS RESOLVE FINE
print(f"[ ARTIFACTS ]: {build.build_artifacts})
In my ORM file I have the classes "Image" and "Tag". Since there is a many-to-many relationship, I also have an association table that looks like this:
tag_to_image_association_table = Table(
"tag_to_image",
Base.metadata,
Column("image_id", Integer, ForeignKey("image.id")),
Column("tag_id", Integer, ForeignKey("tag.id")),
)
I tried to mock it like this:
@pytest.fixture(scope="function")
def sqlalchemy_mock_config() -> list:
mock_db = [
("image", [{"id": 1, "name": "image1"}, {"id": 2, "name": "image2"}]),
("tag", [{"id": 1, "name": "tag1"}, {"id": 2, "name": "tag2"}]),
("tag_to_image", [{"image_id": 1, "tag_id": 1}, {"image_id": 1, "tag_id": 2}]),
]
return mock_db
This works for the "image" and "tag" tables, but trying to join them using the association table just returns an empty list. So my question here is how do I mock this association table?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.