如何使fixtures库忽略SQLalchemy中的外键

时间:2015-02-05 08:21:17

标签: python testing sqlalchemy fixtures

我正在为具有旧版MSSQL数据库的Web应用程序开发一些测试。数据库相当大,并且有许多表与外键互连。我正在使用fixture library根据我在SQLalchemy的应用中定义的模型创建包含测试数据的表格。

我正在运行的问题是,当我向具有外键的灯具添加表时,运行测试还需要我添加连接表,即使我没有使用它。 / p>

ProgrammingError: (ProgrammingError) ('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Foreign key 'FK__countries__ctry___6C40A441' references invalid table 'directdebit_types'. (1767) (SQLExecDirectW); [42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Could not create constraint.

例如,我需要有“俱乐部”数据,但俱乐部是“区域”的一部分;我需要在我的灯具中添加一个“区域”表来继续。添加“区域”后,无法创建表格,因为区域链接到国家/地区,所以现在我需要将国家/地区表格添加到我的灯具中。国家再次与directdebit_types相关联,所以现在我也需要添加它,即使我只想模拟一些俱乐部数据!

上面的示例错误是我每次开始测试时得到的,并且fixture尝试设置表。在这种特定情况下,它是来自各国的外键到direcdebit_types。 跟随并创建所有互连的表将导致必须实际创建整个数据库以进行简单测试。

这有什么办法吗?

为了完整起见,这是我的夹具设置的相关部分:

class ClubsData(DataSet):
    """
    Fixture dataset class for Clubs
    """
    class accesscontrol_test_club:
        club_id = '22222222-2222-2222-2222-222222222222'
        club_name = 'accesscontrol test country'


class AreasData(DataSet):
    """
    Fixture dataset class for Areas
    """
    class accesscontrol_test_area:
        area_name = 'testarea'
        club = ClubsData.accesscontrol_test_club


class CountriesData(DataSet):
    """
    Fixture dataset class for Countries
    """
    class accesscontrol_test_country:
        ctry_shortname = 'accestan'
        area = AreasData.accesscontrol_test_area

我的模特

class Clubs(db.Model, clubs):
    """Club model class.
    """
    shift_terminal = relationship(
        "Terminals",
        primaryjoin="Terminals.term_id==Clubs.club_terminal_for_shift",
        foreign_keys=[clubs.club_terminal_for_shift],
        backref=backref('shift_terminal_clubs'))

    area = relationship("Areas", backref=backref('clubs'))

...

class Areas(db.Model, areas):
    """Area model class.
    """
    country = relationship("Countries", backref=backref('areas'))

    def __init__(self, *args, **kwargs):
        self.area_id = newid()
        super(Areas, self).__init__(*args, **kwargs)

...

class Countries(db.Model, countries):
    """
    Country model class.
    """
    directdebittype = relationship("DirectdebitTypes", backref=backref('countries'))

    def __init__(self, *args, **kwargs):
        self.ctry_id = newid()
        super(Countries, self).__init__(*args, **kwargs)
...

2 个答案:

答案 0 :(得分:0)

为什么不删除列定义中的外键,只需在关系中添加外键(它不会在数据库中生成密钥,但它具有相同的效果)?我想分享一段代码来帮助你。(db.Base由我自己封装):

class Post(db.Base):

    __tablename__ = 'post'

    id = Column(String(32), primary_key=True)


    category_id = Column(String(32))
    category = relationship('Category', backref='posts',
                           primaryjoin='Category.id==Post.category_id',
                           foreign_keys='Post.category_id')

如您所见,category_id中没有外键。

答案 1 :(得分:0)

您可以从真实数据库生成灯具,该灯具遵循夹具命令的所有外键关系。这在使用fixture命令一节中介绍。它可能看起来像:

fixture application.models.Clubs --where id=123 --dsn=<ODBC connection string>

但是,我发现依赖于如此多的数据通常表明您的应用程序模块化程度不足以进行测试。更具体地说,不是直接访问俱乐部模型,而是可以在其前面放置一个外观,例如get_club(id)。这将允许您的测试存根get_club函数并返回虚假对象而不是触及真实数据库。这只是一个人为的例子。我们的想法是将您的应用程序分成较小的独立部分,以便在不集成大型系统的情况下进行测试。