Giter Site home page Giter Site logo

pytest-sqlalchemy-mock's Introduction

Hi there, I'm Resul ๐Ÿ‘‹

๐Ÿ’ซ About Me:

๐Ÿ”ญ Iโ€™m currently working for @datazone
๐Ÿ’ฌ Ask me about Python

๐ŸŒ Socials:

LinkedIn Stack Overflow Twitter

๐Ÿ’ป Tech Stack:

JavaScript Python AWS Google Cloud DjangoREST React FastAPI NodeJS Pandas Notion Kubernetes Docker Postgres Redis

pytest-sqlalchemy-mock's People

Contributors

fomalhautweisszwerg avatar resulyrt93 avatar serhatyavas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

pytest-sqlalchemy-mock's Issues

Fixtures missing in 0.1.6?

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
  • With 0.1.5, we see in the logs:
    • plugins: sqlalchemy-mock-0.1.5
    • fixtures defined from pytest_sqlalchemy_mock.base
  • With 0.1.6, this output is missing.

Here's the full output:

For 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 ==============================================================================================

For 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 =============================================================================================

Does not resolve declared "through/m2m" tables

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?

model refs

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

conftest.py

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"
        },
    ])
    ]

test_model.py

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})

Mocking database with association table

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.