Python Django夹具和所有可能的组合?

Python Django夹具和所有可能的组合?,python,django,unit-testing,fixtures,Python,Django,Unit Testing,Fixtures,我正在尝试测试一个统计函数,它统计数据库中的对象类型。为此,我想为每个可能的模型字段组合创建至少一个实例。随机测试数据需要大量的测试对象来确保满足所有可能的组合 下面是我的一个模型的简化示例: class Member(models.Model) is_active = models.BooleanField() name = models.CharField() balance = models.IntegerField() division = models.

我正在尝试测试一个统计函数,它统计数据库中的对象类型。为此,我想为每个可能的模型字段组合创建至少一个实例。随机测试数据需要大量的测试对象来确保满足所有可能的组合

下面是我的一个模型的简化示例:

class Member(models.Model)
    is_active = models.BooleanField()
    name = models.CharField()
    balance = models.IntegerField()
    division = models.ForeignKey(Division, on_delete=models.CASCADE)

Class Division(models.Model)
    name = models.CharField()
这就是我现在使用django_dynamic_fixture的方式:

from django.test import TestCase
from django_dynamic_fixture import G
from members.models import Member

class StatisticsTestCase(TestCase):
    def setUp(self):
        for is_active in [True, False]:
            for balance in [-100, 0, 100]:
                for division in Division.objects.all()
                    G(Member, is_active=is_active, balance=balance, division=division)
但这看起来很糟糕,很难理解。是否有一种更简单的方法,通过更好的代码来创建对象所有可能的属性组合

我对不同的测试数据生成器持开放态度,只要它们与Python3和Django配合良好。

import itertools
组合=列表(itertools.product(*[[True,False],-100,0100]]))
对于division.objects.all()中的除法:
对于处于活动状态,组合平衡:
G(成员,活跃=活跃,平衡=平衡,分部=分部)

更新:


Sara的回答是一个很好的进步,但是我仍然对代码的可读性不满意,所以我要回答我自己的问题

variants = {
    'is_active': [True, False],
    'balance': [-100, 0, 100],
    'division': list(Division.objects.all())
}

names = sorted(variants)
products = [dict(zip(names, prod)) for prod in it.product(*(variants[name] for name in names))]

for combination in products:
    G(Member, **combination)

现在,任何想要更改此测试的人都可以很容易地看到使用哪个值测试哪个属性。感谢您访问问答获取dict解决方案。

此处-
产品(*[[True,False],-100,0100]])
-为什么要在列表中传递参数,然后解压列表?只要
产品([True,False],-100,0100])
就可以了。也无需将生成器转换为
列表
。生成器比普通列表效率更高。此外,您还可以通过将
除法
对象放入
组合
中来进一步改进答案。是的,好主意,我将编写一个更新,对于您的第一个问题,我认为任何一种方法都有效,因为函数没有指定输入长度:Hm,我认为这是更好的阅读,但仍然不令人满意。现在我要建立一个长长的价值列表,与它们的意义无关,而是与它们的顺序有关。对于3个属性来说这很好,但是如果你有10个属性,那么最好有一个dict,其中的值连接到一个标签上。另外,我希望在一些测试数据/夹具生成器中找到这个现成的特性;)在
[*Division.objects.all()]
的代码中有一个
语法错误。不能在列表中解包列表。你说得对。我的视野很窄。@xyres
Division.objects.all()
返回一个
django.db.models.query.QuerySet
,可以像这样解包。但是因为我是在谈论可读性:
list(Division.objects.all()
更容易理解。感谢您指出这一点。不,
[*Division.objects.all()]
是一个
SyntaxError
。它与Django
QuerySet
无关,因为
SyntaxError
意味着它不是一个有效的Python语法。除了向函数传递参数外,不能在任何地方使用
*
解包。你可以在Python shell中尝试一下,看看我的意思。@xyres可以吗你可能没有意识到我的问题是关于Python3的?因为它是,在Python3中,
[*[1,2]]
不是语法错误。
variants = {
    'is_active': [True, False],
    'balance': [-100, 0, 100],
    'division': list(Division.objects.all())
}

names = sorted(variants)
products = [dict(zip(names, prod)) for prod in it.product(*(variants[name] for name in names))]

for combination in products:
    G(Member, **combination)