在 Python 中使用 Factory-Boy 生成假批量数据

您经常需要假数据来进行测试。当然,您可以在测试中使用一些示例数据。但是,如果您需要数百条甚至数千条测试数据怎么办?那么创建和维护就会变得乏味。有时,您只需要程序中类的假版本,但您希望它是行为类似于真实类的真实数据。工厂和假货让这一切成为可能。

在本文中,我们将使用 python 中的 factory-boy 包来生成假数据。

请确保使用命令 pip installfactory-boy==2.12.0 安装正确版本的factory-boy

让我们尝试使用 factory boy 生成一些假数据

import factory #import factory-boyname = factory.faker('name') #create faker object with 'name' providerfor _ in range(5):    print(name.generate()) #generate and print 5 unique names

结果:

立即学习“Python免费学习笔记(深入)”;

在 Python 中使用 Factory-Boy 生成假批量数据

factory.faker() 接受一个称为provider 的参数,用于生成数据类型,例如“name”provider 将用于生成名称,“email”provider 将用于生成电子邮件等。
让我们尝试使用更多的提供商

import factory #import factory-boyname = factory.faker('name') #create faker object with 'name' providercountry = factory.faker('country') #create faker object with 'country' provideremail = factory.faker('email') #create faker object with 'email' providerfor _ in range(3):    print(f'''my name is {name.generate()}i live in {country.generate()}reach out to me at {email.generate()}''')

结果:

立即学习“Python免费学习笔记(深入)”;

在 Python 中使用 Factory-Boy 生成假批量数据

除了faker类之外,factory-boy还有一个模块fuzzy,我们来看看它是如何工作的

import factory #import factory-boy moduleimport factory.fuzzy #import fuzzy modulename = factory.faker('name') #create faker object with 'name' providergender = factory.fuzzy.fuzzychoice(choices=['girl','boy']) #create fuzzychoice object which selects from the given optionsgrade = factory.fuzzy.fuzzyfloat(30,80) #create fuzzyfloat object which generates a random float number between the lower and upper limitage = factory.fuzzy.fuzzyinteger(12,18) #create fuzzyinteger object which generates a random float numbeer between the lower and upper limitfor _ in range(3):    print(f'''my name is {name.generate()}, i am a {gender.fuzz()} i got a grade of {grade.fuzz():.2f}% and my age is {age.fuzz()}''')

结果:

立即学习“Python免费学习笔记(深入)”;

fuzzy

要了解有关模糊模块中不同类的更多信息以及 faker 提供者的各种选项,请访问:https://factoryboy.readthedocs.io/en/stable

现在我们知道了 factory-boy 如何模仿数据,让我们尝试模仿通常用于为 flask、django 等应用程序创建数据库表的数据模型。
对于这个项目,创建一个requirements.txt并粘贴以下内容,然后使用pip3 install -rrequirements.txt安装所有必需的包

# pin dependancies that might cause breakagewerkzeug==2.1.2sqlalchemy==1.4.46# dependencies for this projectflask==2.1.2flask-sqlalchemy==2.5.1# testing dependenciesnose==1.3.7pinocchio==0.4.3coverage==6.3.2factory-boy==2.12.0pylint==2.14.0

由于我们将使用 nosetest 运行单元测试,请查看我之前的文章 – “使用 unittest 和 nose 在 python 中进行测试驱动开发” (https://dev.to/h4ck3rd33p/test-driven-development-in-python-使用-unittest-and-nosetest-24ck)

创建一个用于nosetests配置的setup.cfg文件并粘贴以下内容

[nosetests]verbosity=2with-spec=1spec-color=1with-coverage=1cover-erase=1cover-package=models[coverage:report]show_missing = true

现在创建两个文件夹模型,其中包含 account.py 中的数据模型和 __init__.py 中的基本设置,以及包含工厂模型的测试,该工厂模型将模仿factories.py中的实际模型以及用于测试的相关单元测试test_account.py 中的应用程序.
最终你的文件夹结构应该如下所示:

.├── models│   ├── account.py│   └── __init__.py├── requirements.txt├── setup.cfg└── tests    ├── factories.py    └── test_account.py2 directories, 6 files

假设我们需要测试一个处理客户帐户的数据模型。我们将从创建这个数据模型开始。我们将使用一种名为 sqlalchemy 的流行对象关系映射器,因此我们创建 sqlalchemy 类的数据库实例。现在我们构建我们的模型。我们创建一个名为 accounts 的类,它继承自 sqlalchemy 的基本模型。现在我们可以添加列,这些列将表示为类变量。我们添加一个id。它将作为非信息承载键,因此我们将 id 标记为主键。我们将名称添加为字符串,将电子邮件字段添加为字符串。我们还添加电话号码作为字符串。我们将该电话号码设置为可选,因此我们将 nullable 设置为 true。让我们添加一个布尔字段来确定该帐户是否被禁用,并将默认值设置为 false。最后,我们将添加一个日期连接列作为 datetime 并将其设置为可选。

模型 > __init__.py

"""data models"""from flask import flaskfrom flask_sqlalchemy import sqlalchemyapp = flask(__name__)app.config['sqlalchemy_track_modifications'] = falseapp.config['sqlalchemy_database_uri'] = 'sqlite:///test.db'db = sqlalchemy(app)

模型 > account.py

"""account class"""import loggingfrom sqlalchemy.sql import funcfrom models import dblogger = logging.getlogger()class datavalidationerror(exception):    """used for an data validation errors when deserializing"""class account(db.model):    """ class that represents an account """    id = db.column(db.integer, primary_key=true)    name = db.column(db.string(64))    email = db.column(db.string(64))    phone_number = db.column(db.string(32), nullable=true)    disabled = db.column(db.boolean(), nullable=false, default=false)    date_joined = db.column(db.date, nullable=false, server_default=func.now())    def __repr__(self):        return '' % self.name    def to_dict(self) -> dict:        """serializes the class as a dictionary"""        return {c.name: getattr(self, c.name) for c in self.__table__.columns}    def from_dict(self, data: dict) -> none:        """sets attributes from a dictionary"""        for key, value in data.items():            setattr(self, key, value)    def create(self):        """creates a account to the database"""        logger.info("creating %s", self.name)        db.session.add(self)        db.session.commit()    def update(self):        """updates a account to the database"""        logger.info("saving %s", self.name)        if not self.id:            raise datavalidationerror("update called with empty id field")        db.session.commit()    def delete(self):        """removes a account from the data store"""        logger.info("deleting %s", self.name)        db.session.delete(self)        db.session.commit()    ##################################################    # class methods    ##################################################    @classmethod    def all(cls) -> list:        """returns all of the accounts in the database"""        logger.info("processing all accounts")        return cls.query.all()    @classmethod    def find(cls, account_id: int):        """finds a account by it's id        :param account_id: the id of the account to find        :type account_id: int        :return: an instance with the account_id, or none if not found        :rtype: account        """        logger.info("processing lookup for id %s ...", account_id)        return cls.query.get(account_id)

现在让我们创建模仿原始 account 类的假类。我们将其命名为 accountfactory。还创建一个内部类 meta 并创建一个属性模型并将其设置为 account,这将使 factory-boy 确切地知道它必须模仿哪个数据类,因此 accountfactory 现在将自动拥有 account 类具有的所有方法。

测试 > 工厂.py

"""accountfactory class using factoryboy"""import factoryfrom datetime import datefrom factory.fuzzy import fuzzychoice, fuzzydatefrom models.account import accountclass accountfactory(factory.factory):    """ creates fake accounts """    class meta:        model = account    id = factory.sequence(lambda n: n)    name = factory.faker("name")    email = factory.faker("email")    phone_number = factory.faker("phone_number")    disabled = fuzzychoice(choices=[true, false])    date_joined = fuzzydate(date(2008, 1, 1))

id = factory.sequence(lambda n: n) 将生成连续的数字序列 0,1,2…

现在让我们编写单元测试来测试我们的 accountfactory

测试装置:这些是在运行测试用例之前和之后设置系统状态的方法。

setupclass(cls):这用于在运行类中的任何测试用例之前设置系统状态。在我们的示例中,它正在创建数据库和表。

teardownclass(cls):用于在运行当前类中的所有测试用例后清理系统。在我们的示例中,它删除所有剩余的测试数据并断开与数据库的连接。

setup(self):这用于在运行单个测试用例之前设置系统。在我们的示例中,它正在删除数据并保存它。

teardown(self):这用于在运行单个测试用例后重置系统状态。在我们的示例中,它正在关闭当前数据库会话。

setupall:这用于在进入任何类之前设置系统状态。 我们在示例中没有使用这个

teardownall:这用于在完成所有类后重置系统状态。 我们在示例中没有使用这个

测试 > test_account.py

"""Test Cases TestAccountModel"""from random import randrangefrom unittest import TestCasefrom models import dbfrom models.account import Account, DataValidationErrorfrom factories import AccountFactoryclass TestAccountModel(TestCase):    """Test Account Model"""    @classmethod    def setUpClass(cls): #Runs before running any unit test        """ Create table """        db.create_all()  # make our sqlalchemy tables    @classmethod    def tearDownClass(cls): #Runs after running all the tests        """Delete test data and Disconnext from database"""        db.session.query(Account).delete()        db.session.close()    def setUp(self): #Runs before running every individual test        """Drop the table"""        db.session.query(Account).delete()        db.session.commit()    def tearDown(self): #Runs after ruunning every individual test        """Remove the session"""        db.session.remove()    ######################################################################    #  T E S T   C A S E S    ######################################################################    def test_create_all_accounts(self):        """ Test creating multiple Accounts """        for _ in range(10):            account = AccountFactory()            account.create()        self.assertEqual(len(Account.all()), 10)    def test_create_an_account(self):        """ Test Account creation using known data """        account = AccountFactory()        account.create()        self.assertEqual(len(Account.all()), 1)    def test_repr(self):        """Test the representation of an account"""        account = Account()        account.name = "Foo"        self.assertEqual(str(account), "")    def test_to_dict(self):        """ Test account to dict """        account = AccountFactory()        result = account.to_dict()        self.assertEqual(account.name, result["name"])        self.assertEqual(account.email, result["email"])        self.assertEqual(account.phone_number, result["phone_number"])        self.assertEqual(account.disabled, result["disabled"])        self.assertEqual(account.date_joined, result["date_joined"])    def test_from_dict(self):        """ Test account from dict """        data = AccountFactory().to_dict()        account = Account()        account.from_dict(data)        self.assertEqual(account.name, data["name"])        self.assertEqual(account.email, data["email"])        self.assertEqual(account.phone_number, data["phone_number"])        self.assertEqual(account.disabled, data["disabled"])    def test_update_an_account(self):        """ Test Account update using known data """        account = AccountFactory()        account.create()        self.assertIsNotNone(account.id)        account.name = "Rumpelstiltskin"        account.update()        found = Account.find(account.id)        self.assertEqual(found.name, account.name)        self.assertIsNotNone(account.id)        account.name = "Rumpelstiltskin"        account.update()        found = Account.find(account.id)        self.assertEqual(found.name, account.name)    def test_invalid_id_on_update(self):        """ Test invalid ID update """        account = AccountFactory()        account.id = None        self.assertRaises(DataValidationError, account.update)    def test_delete_an_account(self):        """ Test Account update using known data """        account = AccountFactory()        account.create()        self.assertEqual(len(Account.all()), 1)        account.delete()        self.assertEqual(len(Account.all()), 0)

阅读评论以了解有关测试用例的更多信息。现在让我们运行鼻子测试

nosetests

恭喜!所有测试用例都已通过,因此我们可以得出结论,我们的 accountfactory 与 account 类完全相同,并且已使用 factory-boy 使用虚假数据测试了应用程序!

以上就是在 Python 中使用 Factory-Boy 生成假批量数据的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1348122.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月13日 11:45:35
下一篇 2025年12月13日 11:45:54

相关推荐

  • 你是什​​么蟒蛇?

    Python 是一种多范式解释型编程语言,这意味着它支持面向对象编程、命令式编程以及部分函数式编程和脚本编写。 重要的是要知道Python是跨平台和开源的;它允许开发人员创建大量的库或模块,以便能够用它做几乎任何事情。 因此,它是一种功能强大且易于学习的语言;它具有高效和高级的数据结构以及简单有效的…

    好文分享 2025年12月13日
    000
  • Python – 索引和切片

    索引和切片是python中的一个重要概念,尤其是当我们使用字符串时。 索引: wkt,字符串只不过是字符序列。 因此,每个字符都有一个位置,即 index,访问它们在该特定字符串中的位置称为 indexing。 在python中,我们有基于零的索引,即字符串的第一个字符的索引(位置)为0而不是1,然…

    2025年12月13日
    000
  • Python

    Python 由 Guido Van Rossum 开发,于 1991 年发布。• Python 是简单且流行的编程语言。• 可以在服务器上使用Python来创建Web应用程序。• Python 用于网络开发、软件开发、复杂数学和系统脚本编写。• 集成开发环境,即软件帮助我们创建其他软件。• 可以在…

    2025年12月13日
    000
  • 用有限的资源微调 LLAMA 或文本分类

    我最近需要对工作中的特定用例进行句子分类。记得 jeremy howard 的第 4 课:针对绝对初学者的 nlp 入门,我首先改编了他的笔记本来微调 deberta。 它有效,但并不令我满意,所以我很好奇如果我使用像 llama 3 这样的 llm 会发生什么。问题是什么? gpu 资源有限。我只…

    2025年12月13日
    000
  • 在 AWS Lambda 中使用 Application Load Balancer (ALB) 时获取实际客户端 IP

    当我刚接触 aws 时,我在执行对文档进行数字签名的任务时遇到了一个有趣的挑战,该任务需要客户的 ip 作为电子签名的一部分。最初,当第一次实现似乎完美运行时,我感到很兴奋。然而,我的兴奋是短暂的。在测试过程中,我注意到即使我从不同的机器访问应用程序,也会返回相同的 ip 地址。就在那时,我意识到我…

    2025年12月13日
    000
  • Python教程的努力成果——四

    from meimayakkam_ruleset import *print (“மெய்ம்மயக்கம் விளையாட்டை விளையாடலாமா”)print (“மெய்ம்மயக்க விளையாட்டை விளையாடப் படிநிலைகளுள் ஒன்றைத் தெரிவுசெய…

    2025年12月13日
    000
  • 通过Python培训课程取得的成果——三

    from MeiMayakkam_Ruleset import *print (“மெய்ம்மயக்கம் விளையாட்டை விளையாடலாமா”)print (“மெய்ம்மயக்க விளையாட்டை விளையாடப் படிநிலைகளுள் ஒன்றைத் தெரிவுசெய…

    2025年12月13日
    000
  • 通过Python教程取得的成果 – 一

    from meymayakkamfinal1 import *print (“மெய்ம்மயக்கம் விளையாட்டை விளையாடலாமா”)print (“மெய்ம்மயக்க விளையாட்டை விளையாடப் படிநிலைகளுள் ஒன்றைத் தெரிவுசெய்க…

    2025年12月13日
    000
  • 字符串和尾随逗号,耦合并成为,Tuple ():将错误复制并粘贴到错误和概念

    今天,我将讲述一个关于我的复制粘贴错误的故事,以及如何在我的 python 程序中将带有逗号的字符串耦合并成为 tuple()。奇怪的是,在犯这个错误之前我并不是没有意识到这个概念。 那么,让我们开始快速学习 python 中的字符串和元组。 细绳 定义: 用于存储和操作文本的字符序列。语法: 用单…

    2025年12月13日
    000
  • 使用自定义 Django 命令自动重新加载 Celery 工作线程

    celery 之前有一个 –autoreload 标志,现已被删除。然而,django 在其manage.py runserver 命令中内置了自动重新加载功能。 celery workers 中缺乏自动重新加载会造成令人困惑的开发体验:更新 python 代码会导致 django 服务…

    2025年12月13日
    000
  • “从概念到代码:使用 Python 构建提醒应用程序”

    大家好!我很高兴向您介绍我的最新项目 Promptly – 一款桌面提醒应用程序,旨在帮助您掌握任务和事件。这个项目结合了我对编码的热情和高效时间管理的实际需求。 项目概况: 在忙碌的生活中,我们很容易忘记重要的任务和事件。及时赶到是为了确保不会发生这种情况。借助 Promptly,您可以为任务设置…

    2025年12月13日
    000
  • Python 中的并发和并行编程(课程)

    刚刚完成了有关 Python 并发和并行编程的精彩课程,我很高兴分享我的经验!作为首席工程师,我一直在寻找优化性能和扩展知识的方法。 Max S 在 Udemy 上开设的这门课程是对异步编程、并行计算和线程的精彩回顾。 突出之处: 对复杂概念的清晰解释实际的、真实的例子动手编码的机会 讲师轻松分解 …

    2025年12月13日
    000
  • 在 C# NET 代码库中实现 Bootstrap 现代化:来自 o 5 的 Python 支持的迁移

    介绍 作为一名开发人员,我最近发现自己面临着一个令人兴奋的挑战:对仍在使用 bootstrap 3 的旧版 c# .net 代码库进行现代化改造。目标很明确 – 使用最新的 bootstrap 5 加快项目速度。但是,我很快就意识到实现如此重大的飞跃可能会充满风险且耗时。 就在那时我决定…

    2025年12月13日
    000
  • 通过单一提示构建和部署 AI 支持的 Web 服务

    在 shuttle,我们一直在开发一种新工具,我们认为它可以改变开发人员处理 ai 集成的方式。我们将其称为 shuttleai,它允许您通过单个提示构建和部署人工智能驱动的 web 服务。 这是 tl;dr: 用通俗易懂的语言描述您的人工智能服务shuttleai 生成项目规范供您查看批准或修改规…

    2025年12月13日
    000
  • 让我们制作一个计算器

    在我们真正制作计算器之前,我们先来看看一些基本的数学表达式… 1.添加 num1 = 2num2 = 3print(num1+num2) 5 2.减去 num1 = 7num2 = 5print(num1-num2)2 3.乘法 num1 = 5num2 = 5print(num1*nu…

    2025年12月13日
    000
  • Python – 运算符和条件

    在这篇博客中,我们将了解运算符、条件和 input() 函数。让我们进入运营商吧。 什么是运算符? 在计算机中执行特定数学/逻辑运算的符号。这有 3 种类型,即: 算术运算符比较运算符逻辑运算符 这些是什么以及它们执行什么功能? 让我告诉你一些事情,你们会惊讶地发现它是多么简单…&#82…

    2025年12月13日
    000
  • 运算符、条件、输入()

    *算术运算符* Python 中的六种算术运算符是:加法 (+)、减法 (-)、乘法 ()、除法 (/)、模 (%) 和指数 (*)。这些运算符允许您对数字数据类型(例如整数和浮点数)执行数学运算。 *比较运算符* 比较运算符用于比较两个值: ==, !=, =, >, 逻辑运算符.. Pyt…

    2025年12月13日
    000
  • Python:print() 方法

    大家好,今天学习了Python的print语句。知道Python有这么多的功能真是令人着迷。我将分享我今天学到的一些东西 sep,sep参数与print()函数一起使用,用于指定打印多个参数时的分隔符。转义序列如n(新行),t(添加空格),b(删除前一个字符)。串联 添加两个不同的字符串。连接 st…

    2025年12月13日
    000
  • 全面的 Python 数据结构备忘单

    全面的 python 数据结构备忘单 目录 列表元组套装词典弦乐数组堆栈排队链接列表树堆图表高级数据结构 列表 列表是有序的、可变的序列。 创建 empty_list = []list_with_items = [1, 2, 3]list_from_iterable = list(“abc”)lis…

    2025年12月13日
    000
  • 高级 Python 概念:综合指南

    高级 python 概念:综合指南 目录 简介装饰器生成器和迭代器上下文管理器元类结论 一、简介 python 是一种多功能且强大的编程语言,提供广泛的高级功能。本白皮书探讨了四个关键的高级概念:装饰器、生成器和迭代器、上下文管理器和元类。这些功能使开发人员能够编写更高效、可读和可维护的代码。虽然这…

    2025年12月13日
    000

发表回复

登录后才能评论
关注微信