gpt4 book ai didi

单元测试中的 SQLAlchemy session 投票

转载 作者:行者123 更新时间:2023-12-05 00:37:27 26 4
gpt4 key购买 nike

几天前我刚刚开始使用 SQLAlchemy,现在我遇到了一个问题,我希望任何人都可以在我失去所有头发之前弄清楚。

当我运行单元测试时,请参阅下面的代码片段,只有序列中的第一个测试通过。测试 testPhysicalPrint 工作正常,但 testRecordingItem 因 NoResultFound 异常而失败 - 未找到 one() 的行。但是如果我从测试类中删除 testPhysicalPrint,那么 testRecordingItem 就可以工作了。

我认为问题与 session 有关,但我无法真正掌握它。

如果有人想知道,设置如下:

  • 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()

    更新

    这是工作代码片段。
    # -*- 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()

    最佳答案

    这种行为最可能的原因是在测试之间没有正确清理数据。这解释了为什么当您只运行一项测试时它会起作用。
    setUp在每次测试之前调用,并且 tearDown - 后。
    根据您想要实现的目标,您有两种选择:

  • 为所有测试只创建一次数据。
    在这种情况下,如果你有 Python-2.7+ 或 Python-3.2+,你可以使用 tearDownClass方法。在您的情况下,您可以使用 bool 类变量来处理它以防止您在 setUp 中的代码。运行不止一次。
  • 每次测试前重新创建数据
    在这种情况下,您需要确保在 tearDown 中你删除所有数据。这是您现在没有做的事情,我怀疑在运行第二个测试时,调用 one()失败不是因为它没有找到一个对象,而是因为它找到了更多两个符合条件的对象。


  • 检查此代码的输出以了解调用序列:
    import unittest
    class TestSchema(unittest.TestCase):
    def testOne(self):
    print '==testOne'
    def testTwo(self):
    print '==testTwo'
    def setUp(self):
    print '>>setUp'
    def tearDown(self):
    print '<<tearDown'
    @classmethod
    def setUpClass():
    print '>>setUpClass'
    @classmethod
    def tearDownClass():
    print '<<tearDownClass'
    if __name__ == '__main__':
    unittest.main()

    输出:
    >>setUp
    ==testOne
    <<tearDown
    >>setUp
    ==testTwo
    <<tearDown

    关于单元测试中的 SQLAlchemy session 投票,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6941368/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com