Я разрабатываю большой бэкэнд для некоторых веб-приложений.Это мой первый проект на Python и SQLAlchemy, поэтому меня смущают некоторые вещи.И был отчасти испорчен инструментами программирования Java и IDE по сравнению с python (я все равно использую pydev в eclipse).Мне нужна помощь с тем, как структурировать проект и написать тесты.Сначала я опишу ситуацию.
В PyDev я назвал мой проект, например, «ProjectName», а ниже я показал мою текущую папку / пакет и структуру файлов.
- ProjectName
- имя проекта
- __ init __. Py
- some_package
- __ init __. Py
- Foo.py
- Bar.py
- тесты
- unit_tests
- __ init __. py
- some_package
- __ init __. py
- TestFoo.py
- TestBar.py
- load_tests
- gration_tests
- __ init __. Py
Я использую декларативный стиль в SQLAlchemy.Foo и Bar - это некоторые классы, например, Foo расширяет декларативную базу SQLAlchemy, а Bar расширяет Foo.Под 'projectname.some_package' в __init__.py у меня есть этот код:
engine = create_engine('mysql+mysqldb://user:pass@localhost:3306/SomeDataBase', pool_recycle=3600)
Session = sessionmaker(bind=engine)
Base = declarative_base()
Итак, Foo импортирует эту базу и расширяет ее, а Bar импортирует Foo и расширяет ее.Мой первый вопрос: должен ли я хранить Base в этом __init__.py и использовать его так, как я начал с этих 2 классов?Это create_engine просто временно, я хотел бы иметь конфигурационный файл и загрузить его настройки оттуда, как это сделать?Где я должен вызвать Base.metadata.create_all (), чтобы он мог создавать все таблицы базы данных одновременно?
Далее, в классах тестирования, например в TestFoo, у меня есть этот код:
def setUp(self):
#create database tables and session object
self.engine = create_engine('mysql+mysqldb://user:pass@localhost:3306/SomeDatabase', pool_recycle=3600)
Session = sessionmaker(bind=self.engine)
Foo.metadata.create_all(bind=self.engine)
self.session = Session()
def tearDown(self):
#drop all tables and close session object
self.session.close()
meta = MetaData(self.engine)
meta.reflect()
meta.drop_all()
Конец, тогда у меня есть несколько тестовых методов в этом тестовом классе, и он работает нормально.В классе TestBar разница в том, что
Foo.metadata.create_all(bind=self.engine)
:
Bar.metadata.create_all(bind=self.engine)
Когда я запускаю TestBar, он также работает нормально.Но когда я выбираю оба тестовых класса и запускаю их, я получаю ошибки:
/usr/local/lib/python2.7/dist-packages/sqlalchemy/ext/declarative.py:1336: SAWarning: The classname 'Foo' is already in the registry of this declarative base, mapped to <class 'projectname.some_package.Foo.Foo'>
_as_declarative(cls, classname, cls.__dict__)
/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/default.py:330: Warning: Field 'id' doesn't have a default value
cursor.execute(statement, parameters)
В чем здесь проблема?Я пытался запустить тесты с носовыми и пидевскими бегунами и получал те же ошибки.Затем я попытался переместить создание таблиц базы данных в __init__.py в some_package в unit_tests, но не смог заставить его работать.Кроме того, я запутался в том, как работает импорт python.Например, если я добавляю импорт Foo в класс TestBar, я также получаю ошибки, подобные тем, что я уже показал.Как я могу запустить много модульных тестов, которые одновременно тестируют классы SQLAlchemy?
Итак, чтобы снова извлечь наиболее важные вопросы:
- Как структурировать проект Python, который использует декларативный стиль SQLAlchemy июниттесты правильно.Кстати, у меня есть много методов классов в Foo и Bar, которые взаимодействуют с базой данных, в контексте их соответствующих классов, я надеюсь, что это нормально?
- Где хранить декларативный класс Base и как правильно использовать его во всем проекте, и как извлечь всю схему базы данных (которую я определенно определил в моих классах) в любом месте проекта и использовать ее?
- Как лучше всего использовать юнит-тесты с SQLAlchemy и запускать несколько юнит-тестов одновременно?
- Если у вас есть какие-либо другие предложения, не стесняйтесь добавлять его?
Большое спасибо за помощь.