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

Python 如何使fixtures库忽略SQLalchemy中的外键,python,testing,sqlalchemy,fixtures,Python,Testing,Sqlalchemy,Fixtures,我正在为一个带有遗留MSSQL数据库的web应用程序开发一些测试。数据库相当大,有许多表与外键互连。我正在使用创建包含测试数据的表,这些表基于我在中的应用程序中定义的模型 我遇到的问题是,当我将一个表添加到具有外键的fixture中时,运行测试还需要添加连接的表,即使我没有使用它 ProgrammingError: (ProgrammingError) ('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Foreig

我正在为一个带有遗留MSSQL数据库的web应用程序开发一些测试。数据库相当大,有许多表与外键互连。我正在使用创建包含测试数据的表,这些表基于我在中的应用程序中定义的模型

我遇到的问题是,当我将一个表添加到具有外键的fixture中时,运行测试还需要添加连接的表,即使我没有使用它

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.
例如,我需要“俱乐部”数据,但俱乐部是“区域”的一部分;我需要在设备中添加一个“面积”表才能继续。添加“区域”后,无法创建表,因为区域链接到国家,所以现在我需要将国家表添加到我的装置中。同样,Countries链接到directdebit_类型,所以现在我也需要添加它,尽管我只想模拟一些俱乐部数据

上面的示例错误是我每次开始测试时得到的,fixture尝试设置表。在这种特定情况下,它是从国家/地区到direcu类型的外键。 遵循并创建所有互连表将导致实际上必须为一个简单的测试创建整个数据库

这有什么办法吗

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

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)
...

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


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

您可以从真实数据库中生成装置,该数据库使用fixture命令遵循所有外键关系。这将在使用fixture命令的部分中记录。它可能看起来像:

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

然而,我发现依赖如此多的数据通常表明应用程序的模块化程度不足以进行测试。更具体地说,不必直接访问俱乐部模型,您可以在其前面放置一个门面,类似于
get\u Club(id)
。这将允许您的测试剔除
get_club
函数,并返回一个伪对象,而不是接触真实的数据库。这只是一个做作的例子。我们的想法是将您的应用程序分离成更小的独立部分,这样就可以在不集成太多较大系统的情况下对它们进行测试。

Hi Octavian。谢谢你的意见;我们有一个基于数据库生成模型的脚本,因为这是一个遗留数据库。如果我们要调整外键,这将是对我们的脚本和这个应用程序已经存在的代码的重大更改。这是可行的,但工作量很大。我希望有一个更简单的解决方案,最好是装置本身…^^,好吧,我明白你的意思了。我也想从这个问题中得到一个更简单的解决方案。谢谢库马尔的意见。我理解你的意思,但你描述的是一个单元测试。fixture不是特别适合功能测试吗?在功能测试中,应用程序的大部分功能都是经过测试的?我们有针对特定函数的单元测试,它们使用模拟对象,而不是数据库。然而,我们还需要测试涉及(例如)从数据库收集和计算数据集的函数。我们想在这种情况下使用fixture。SQLalchemy模型似乎强制创建相关的表。当然,数据库装置有其位置,特别是在功能测试中。功能测试真的很难做到正确,我认为它们对于所需的维护量并不总是有用的。您可以采取的另一种方法是编写一个API,功能测试套件可以使用该API在测试之前创建所需的对象——这样您就不会将测试锁定到数据库模式中。
fixture application.models.Clubs --where id=123 --dsn=<ODBC connection string>