Проблема с созданием тестовых фабрик из автоматически сгенерированных моделей - PullRequest
0 голосов
/ 16 октября 2019

У меня есть база данных mysql, в которой есть две таблицы, которые я хочу использовать в тестах - Shop и Discrict. Прежде всего, вот список desc:

root@localhost [flowershop]> describe catalog_shop;
+-------------------+--------------+------+-----+---------+----------------+
| Field             | Type         | Null | Key | Default | Extra          |
+-------------------+--------------+------+-----+---------+----------------+
| id                | int(11)      | NO   | PRI | NULL    | auto_increment |
| hours             | varchar(255) | NO   |     | NULL    |                |
| lat               | varchar(255) | NO   |     | NULL    |                |
| lng               | varchar(255) | NO   |     | NULL    |                |
| phone             | varchar(255) | NO   |     | NULL    |                |
| address           | varchar(255) | NO   |     | NULL    |                |
| calltracking_id   | int(11)      | YES  |     | NULL    |                |
| district_id       | int(11)      | NO   | MUL | NULL    |                |
| modification_date | datetime(6)  | NO   |     | NULL    |                |
| show_on_site      | tinyint(1)   | NO   |     | NULL    |                |
| sms_phone         | varchar(255) | NO   |     | NULL    |                |
| user_id           | int(11)      | YES  | UNI | NULL    |                |
+-------------------+--------------+------+-----+---------+----------------+
12 rows in set (0.07 sec)

root@localhost [flowershop]> describe catalog_district;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | NO   |     | NULL    |                |
| article_id | int(11)      | YES  | MUL | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

В моих models.py:

from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import relationship
from sqlalchemy import Column, ForeignKey
from tornado_sqlalchemy import make_session_factory

from .settings import DATABASE_URL


session_factory = make_session_factory(DATABASE_URL)

AutoBase = automap_base()
AutoBase.prepare(session_factory.engine, reflect=True)

Shop = AutoBase.classes.catalog_shop
District = AutoBase.classes.catalog_district

tests / factories.py:

import factory
from packages.models import Shop, District, session_factory


session = session_factory.make_session()


class DistrictFactory(factory.alchemy.SQLAlchemyModelFactory):

    class Meta:
        model = District
        sqlalchemy_session = session
        sqlalchemy_session_persistence = 'commit'


class ShopFactory(factory.alchemy.SQLAlchemyModelFactory):

    district = factory.SubFactory(DistrictFactory)
    address = factory.Faker('address')
    phone = factory.Faker('phone_number')

    class Meta:
        model = Shop
        sqlalchemy_session = session
        sqlalchemy_session_persistence = 'commit'

test_handlers.py:

from tornado.testing import AsyncTestCase
from .factories import ShopFactory


class StartHandlerTest(AsyncTestCase):

    def test_simple_start(self):

        shop = ShopFactory.create()

Который при вызове дает мне обратную трассировку:

ERROR: test_simple_start (packages.tests.test_handlers.StartHandlerTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/tornado/testing.py", line 98, in __call__
    result = self.orig_method(*args, **kwargs)
  File "/Users/alkalit/.virtualenvs/flowershop/telegram_bot/packages/tests/test_handlers.py", line 13, in test_simple_start
    shop = ShopFactory.create()
  File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/factory/base.py", line 564, in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
  File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/factory/base.py", line 501, in _generate
    return step.build()
  File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/factory/builder.py", line 279, in build
    kwargs=kwargs,
  File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/factory/base.py", line 315, in instantiate
    return self.factory._create(model, *args, **kwargs)
  File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/factory/alchemy.py", line 75, in _create
    obj = model_class(*args, **kwargs)
  File "<string>", line 4, in __init__
  File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/sqlalchemy/orm/state.py", line 441, in _initialize_instance
    manager.dispatch.init_failure(self, args, kwargs)
  File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 153, in reraise
    raise value
  File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/sqlalchemy/orm/state.py", line 438, in _initialize_instance
    return manager.original_init(*mixed[1:], **kwargs)
  File "/Users/alkalit/.virtualenvs/flowershop/lib/python3.7/site-packages/sqlalchemy/ext/declarative/base.py", line 840, in _declarative_constructor
    "%r is an invalid keyword argument for %s" % (k, cls_.__name__)
TypeError: 'district' is an invalid keyword argument for catalog_shop

Я также ссылался на себя с документами sqlalchemy, которые утверждают, что при создании автоматической модели он также обеспечивает отношения: https://docs.sqlalchemy.org/en/13/orm/extensions/automap.html#basic-use

а именно: session.add(Address(email_address="foo@bar.com", user=User(name="foo")))

Итак, вопрос в том - что я делаю не так?

Я также пытался использовать "родной" создатель сессий в factories.py

from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy import create_engine

engine = create_engine(DATABASE_URL)
session = scoped_session(sessionmaker(bind=engine))

с тем же результатом.

libs:

  • tornado == 6.0.3
  • tornado-sqlalchemy == 0.6.1
  • SQLAlchemy == 1.3.10
  • factory-boy == 2.12.0

Редактировать: добавлено sqlalchemy_session_persistence = 'commit', но все равно появляется ошибка.

...