前幾天我剛開始使用SQLAlchemy,現在我遇到了一個問題,我希望任何人都可以在釋放所有頭髮之前揭示一些問題。SQLAlchemy session unit vtest in unittest
當我運行unittest時,請參閱下面的代碼片段,只有序列中的第一個測試通過。測試testPhysicalPrint工作得很好,但testRecordingItem失敗,出現NoResultFound異常 - 找不到一行()的行()。但是,如果我從測試類中刪除testPhysicalPrint,那麼testRecordingItem就起作用。
我認爲問題與會話有關,但我無法真正掌握它。
在任何人的情況下奇觀,設置如下:
- 的Python 3.1(Ubuntu的10.04封裝)
- SQLAlchemy的0.7.2(easy_install的:ED)
- 的PostgreSQL 8.4.8(Ubuntu的10.04包)
- PsycoPG2 2.4.2(easy_installed:ED)
爲例試驗:
class TestSchema(unittest.TestCase):
test_items = [
# Some parent class products
PrintItem(key='p1', title='Possession', dimension='30x24'),
PrintItem(key='p2', title='Andrzej Żuławski - a director', dimension='22x14'),
DigitalItem(key='d1', title='Every Man His Own University', url='http://www.gutenberg.org/files/36955/36955-h/36955-h.htm'),
DigitalItem(key='d2', title='City Ballads', url='http://www.gutenberg.org/files/36954/36954-h/36954-h.htm'),
]
def testPrintItem(self):
item = self.session.query(PrintItem).filter(PrintItem.key == 'p1').one()
assert item.title == 'Possession', 'Title mismatch'
def testDigitalItem(self):
item2 = self.session.query(DigitalItem).filter(DigitalItem.key == 'd2').one()
assert item2.title == 'City Ballads', 'Title mismatch'
def setUp(self):
Base.metadata.create_all()
self.session = DBSession()
self.session.add_all(self.test_items)
self.session.commit()
def tearDown(self):
self.session.close()
Base.metadata.drop_all()
if __name__ == '__main__':
unittest.main()
UPDATE
這裏是工作的代碼片段。
# -*- coding: utf-8 -*-
import time
import unittest
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import *
Base = declarative_base()
engine = create_engine('sqlite:///testdb', echo=False)
DBSession = sessionmaker(bind=engine)
class ItemMixin(object):
"""
Commons attributes for items, ie books, DVD:s...
"""
__tablename__ = 'testitems'
__table_args__ = {'extend_existing':True}
id = Column(Integer, autoincrement=True, primary_key=True)
key = Column(Unicode(16), unique=True, nullable=False)
title = Column(UnicodeText, default=None)
item_type = Column(Unicode(20), default=None)
__mapper_args__ = {'polymorphic_on': item_type}
def __init__(self, key, title=None):
self.key = key
self.title = title
class FooItem(Base, ItemMixin):
foo = Column(UnicodeText, default=None)
__mapper_args__ = {'polymorphic_identity':'foo'}
def __init__(self, foo=None, **kwargs):
ItemMixin.__init__(self, **kwargs)
self.foo = foo
class BarItem(Base, ItemMixin):
bar = Column(UnicodeText, default=None)
__mapper_args__ = {'polymorphic_identity':'bar'}
def __init__(self, bar=None, **kwargs):
ItemMixin.__init__(self, **kwargs)
self.bar = bar
# Tests
class TestSchema(unittest.TestCase):
# Class variables
is_setup = False
session = None
metadata = None
test_items = [
FooItem(key='f1', title='Possession', foo='Hello'),
FooItem(key='f2', title='Andrzej Żuławsk', foo='World'),
BarItem(key='b1', title='Wikipedia', bar='World'),
BarItem(key='b2', title='City Ballads', bar='Hello'),
]
def testFooItem(self):
print ('Test Foo Item')
item = self.__class__.session.query(FooItem).filter(FooItem.key == 'f1').first()
assert item.title == 'Possession', 'Title mismatch'
def testBarItem(self):
print ('Test Bar Item')
item = self.__class__.session.query(BarItem).filter(BarItem.key == 'b2').first()
assert item.title == 'City Ballads', 'Title mismatch'
def setUp(self):
if not self.__class__.is_setup:
self.__class__.session = DBSession()
self.metadata = Base.metadata
self.metadata.bind = engine
self.metadata.drop_all() # Drop table
self.metadata.create_all() # Create tables
self.__class__.session.add_all(self.test_items) # Add data
self.__class__.session.commit() # Commit
self.__class__.is_setup = True
def tearDown(self):
if self.__class__.is_setup:
self.__class__.session.close()
# Just for Python >=2.7 or >=3.2
@classmethod
def setUpClass(cls):
pass
#Just for Python >=2.7 or >=3.2
@classmethod
def tearDownClass(cls):
pass
if __name__ == '__main__':
unittest.main()
Hi Van!感謝您的意見。在tearDown中,我已經把Base.metadata.drop_all() - 不會刪除有問題的表,並因此在每次測試後刪除數據? –
你說得對。但由於某些原因,數據實際上並未被第二次插入。如果您爲引擎設置了'echo = True'並查看生成的SQL語句,則會看到數據行沒有被第二次插入。在這一點上,我不知道爲什麼。不過,您可以實現選項1並僅創建一次數據(如果測試不刪除它),這將解決問題。 – van
刪除setUp中的提交併在tearDown中關閉會話之前添加回滾之後,它將起作用。嗯... –