Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python SQLAlchemy中查询的单元测试_Python_Unit Testing_Sqlalchemy - Fatal编程技术网

Python SQLAlchemy中查询的单元测试

Python SQLAlchemy中查询的单元测试,python,unit-testing,sqlalchemy,Python,Unit Testing,Sqlalchemy,如何在SQLAlchemy中测试查询?例如,假设我们有这个models.py from sqlalchemy import ( Column, Integer, String, ) from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Panel(Base): __tablename__ = 'Panels'

如何在SQLAlchemy中测试查询?例如,假设我们有这个
models.py

from sqlalchemy import (
        Column,
        Integer,
        String,
)
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Panel(Base):
    __tablename__ = 'Panels'

    id = Column(Integer, primary_key=True)
    category = Column(Integer, nullable=False)
    platform = Column(String, nullable=False)
    region = Column(String, nullable=False)

    def __init__(self, category, platform, region):
        self.category = category
        self.platform = platform
        self.region = region


    def __repr__(self):
        return (
            "<Panel('{self.category}', '{self.platform}', "
            "'{self.region}')>".format(self=self)
        )
import unittest

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from models import Base, Panel


class TestQuery(unittest.TestCase):

    engine = create_engine('sqlite:///:memory:')
    Session = sessionmaker(bind=engine)
    session = Session()

    def setUp(self):
        Base.metadata.create_all(self.engine)
        self.session.add(Panel(1, 'ion torrent', 'start'))
        self.session.commit()

    def tearDown(self):
        Base.metadata.drop_all(self.engine)

    def test_query_panel(self):
        expected = [Panel(1, 'ion torrent', 'start')]
        result = self.session.query(Panel).all()
        self.assertEqual(result, expected)
当我们尝试运行测试时,它失败了,即使两个面板看起来完全相同

$ nosetests
F
======================================================================
FAIL: test_query_panel (tests.TestQuery)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/clasher/tmp/tests.py", line 31, in test_query_panel
    self.assertEqual(result, expected)
AssertionError: Lists differ: [<Panel('1', 'ion torrent', 's... != [<Panel('1', 'ion torrent', 's...

First differing element 0:
<Panel('1', 'ion torrent', 'start')>
<Panel('1', 'ion torrent', 'start')>

  [<Panel('1', 'ion torrent', 'start')>, <Panel('2', 'ion torrent', 'end')>]

----------------------------------------------------------------------
Ran 1 test in 0.063s

FAILED (failures=1)

不过,这让我觉得非常难看,而且我甚至还没有达到我要测试的复杂过滤查询的程度。是否有更优雅的解决方案,或者我总是需要手动进行一系列单独的查询?

您最初的测试是正确的,您只需要做两件事中的一件:或者确保具有相同主键标识的两个
面板
对象与
True
进行比较:

class Panel(Base):
    # ...

    def __eq__(self, other):
        return isinstance(other, Panel) and other.id == self.id
或者,您可以组织您的测试,以确保您正在对照相同的
面板
实例进行检查(因为这里我们利用了以下优势):


至于引擎/会话设置/拆卸,我会选择一种模式,在这种模式中,所有测试都使用一个引擎,并且假设您的模式是固定的,所有测试都使用一个模式,然后确保您使用的数据在可以回滚的事务中执行。
会话
可以通过这种方式工作,这样调用
commit()
就不会通过将整个测试包装在显式的
事务
中实际提交“真实”事务。上的示例说明了此用法。在每个测试夹具上使用“:memory:”引擎将占用大量内存,并且不会真正扩展到SQLite以外的其他数据库。

这里的关键思想是,您需要在设置过程中实例化所有对象,通过将它们作为属性分配给
self
来保留它们,并在以后检索它们,而不是再次查询数据库,但是通过那些
自我
属性。此外,实现
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;SQLAlchemy似乎将返回与模型完全相同的实例(即,
创建的\u模型\u实例是来自\u查询的实例
返回
True
)。最后,它将有助于修改答案以使用事务回滚模式,即使可以通过阅读提供的链接上的SQLAlchemy文档来推断。
class Panel(Base):
    # ...

    def __eq__(self, other):
        return isinstance(other, Panel) and other.id == self.id
class TestQuery(unittest.TestCase):
    def setUp(self):
        self.engine = create_engine('sqlite:///:memory:')
        self.session = Session(engine)
        Base.metadata.create_all(self.engine)
        self.panel = Panel(1, 'ion torrent', 'start')
        self.session.add(self.panel)
        self.session.commit()

    def tearDown(self):
        Base.metadata.drop_all(self.engine)

    def test_query_panel(self):
        expected = [self.panel]
        result = self.session.query(Panel).all()
        self.assertEqual(result, expected)