首页 > 编程问答 >编写 Django 单元测试的更优雅的方法

编写 Django 单元测试的更优雅的方法

时间:2024-08-09 14:54:33浏览次数:6  
标签:python django python-unittest django-testing django-unittest

我目前正在使用 Django 的单元测试(基于 Python 标准库模块:unittest)编写测试。我已经为我的 Contact 模型编写了这个测试,它通过了:

class ContactTestCase(TestCase):
    def setUp(self):
        """Create model objects."""
        Contact.objects.create(
            name='Jane Doe',
            email='[email protected]',
            phone='+2348123940567',
            subject='Sample Subject',
            message='This is my test message for Contact object.'
        )


    def test_user_can_compose_message(self):
        """ Test whether a user can compose a messsage in the contact form."""
        test_user = Contact.objects.get(name='Jane Doe')
        self.assertEqual(test_user.email, '[email protected]')
        self.assertEqual(test_user.phone, '+2348123940567')
        self.assertEqual(test_user.subject, 'Sample Subject')
        self.assertEqual(test_user.message, 'This is my test message for Contact object.')
Found 1 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.005s

OK
Destroying test database for alias 'default'...

但是,我必须在这个测试中使用 assertEqual 方法 4 次(当测试具有更多字段的模型时可能会更多)。这似乎不遵循 DRY 原则。

我从 文档 测试中知道第一个和第二个是相等的。如果这些值不相等,测试就会失败。 assertEqual(first, second, msg=None) 是否有解决方法或更优雅的方法来编写此类测试?

Is there a workaround or a more elegant approach to writing such tests?


你说的对,一遍遍重复使用 assertEqual 会让你的测试代码冗长且难以维护,尤其是在有很多字段需要校验的时候。

这里提供几种更优雅地编写 Django 单元测试,并遵循 DRY 原则的方法:

1. 使用字典和循环:

你可以创建一个包含预期值的字典,然后循环遍历它来进行断言:

class ContactTestCase(TestCase):
    def setUp(self):
        """Create model objects."""
        Contact.objects.create(
            name='Jane Doe',
            email='[email protected]',
            phone='+2348123940567',
            subject='Sample Subject',
            message='This is my test message for Contact object.'
        )

    def test_user_can_compose_message(self):
        """ Test whether a user can compose a message in the contact form."""
        test_user = Contact.objects.get(name='Jane Doe')
        expected_values = {
            'email': '[email protected]',
            'phone': '+2348123940567',
            'subject': 'Sample Subject',
            'message': 'This is my test message for Contact object.'
        }
        for field, expected_value in expected_values.items():
            self.assertEqual(getattr(test_user, field), expected_value, f"{field} does not match expected value")

2. 使用 assertDictEqual (针对多个字段):

如果你的模型字段和预期值可以构成一个字典,你可以直接使用 assertDictEqual :

from django.forms.models import model_to_dict

class ContactTestCase(TestCase):
    # ... (setUp 方法同上)

    def test_user_can_compose_message(self):
        """ Test whether a user can compose a message in the contact form."""
        test_user = Contact.objects.get(name='Jane Doe')
        expected_data = {
            'email': '[email protected]',
            'phone': '+2348123940567',
            'subject': 'Sample Subject',
            'message': 'This is my test message for Contact object.'
        }
        self.assertDictEqual(model_to_dict(test_user, fields=expected_data.keys()), expected_data)

3. 使用自定义断言方法:

你可以创建一个自定义断言方法来比较模型实例和预期值:

class ContactTestCase(TestCase):
    # ... (setUp 方法同上)

    def assertContactDataEqual(self, contact, **expected_data):
        for field, expected_value in expected_data.items():
            self.assertEqual(getattr(contact, field), expected_value, f"{field} does not match expected value")

    def test_user_can_compose_message(self):
        """ Test whether a user can compose a message in the contact form."""
        test_user = Contact.objects.get(name='Jane Doe')
        self.assertContactDataEqual(
            test_user,
            email='[email protected]',
            phone='+2348123940567',
            subject='Sample Subject',
            message='This is my test message for Contact object.'
        )

4. 使用 Factory Boy 或 Model Bakery 生成测试数据:

这些第三方库可以帮助你更方便地生成测试数据,并可以减少重复代码。

例如,使用 Factory Boy:

import factory
from .models import Contact

class ContactFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Contact

    name = factory.Faker('name')
    email = factory.Faker('email')
    phone = factory.Faker('phone_number')
    subject = factory.Faker('sentence')
    message = factory.Faker('paragraph')

class ContactTestCase(TestCase):
    def test_user_can_compose_message(self):
        test_user = ContactFactory()
        self.assertEqual(test_user.email, test_user.email)  # 验证数据是否生成成功

选择哪种方法取决于你的个人偏好和项目的具体情况。但是,这些方法都可以帮助你编写更简洁、更易维护的 Django 单元测试。

标签:python,django,python-unittest,django-testing,django-unittest
From: 78841378

相关文章

  • 零基础学习人工智能—Python—Pytorch学习(三)
    前言这篇文章主要两个内容。一,把上一篇关于requires_grad的内容补充一下。二,介绍一下线性回归。关闭张量计算关闭张量计算。这个相对简单,阅读下面代码即可。print("============关闭require_grad==============")x=torch.randn(3,requires_grad=True)print(x)x.requir......
  • python配置pip镜像
    Python配置pip的镜像国内的网络通过pip下载软件包只有不到10k的下载速度。不仅下载的慢,还容易引发超时错误,导致下载失败。而将给pip配置国内的镜像源可以完美的解决这个问题。本文讲解了pip在windows和macos/linux的配置过程(在windows实操成功)一、找到配置文件1.windows在......
  • Pytorch深度学习入门基础(三):python 加载数据初认识
    目录 一、 导入二、数据集中数据和label的组成形式三、Dataset读入数据四、Dataset类代码实战4.1创建函数4.2  设置初始化函数4.3读取每一个图片4.4设置获取数据长度函数4.5创建实例4.5.1单个图片数据集4.5.2 多个图片数据集    现在来开......
  • python多版本共存和虚拟环境
    多版本共存1.调用方式"py-3.10",即可使用对应版本的python虚拟环境1.vscode底部切到CMD,敲"py-3.8-mvenv.venv"(虚拟环境文件夹名,通常用".venv")2.点击vscode右下角,选择虚拟环境作为解释器注:以"."开头的文件在计算机系统中通常被称为隐藏文件。这些文件在许多操作系统中默认是不......
  • Python练习:数据类型篇
    一、逻辑推理练习  1、在不运行下面程序的前提下,说出答案。 1.4.0==42."4.0"==43.bool("1")4.bool("0")5.str(32)6.int(6.26)7.float(32)8.float("3.21")9.int("434")10.int("3.42")11.bool(-1)12......
  • MySQL——使用Python操作MySQL
    文章目录安装PyMySQL使用PyMySQL操作MySQL在Python中操作MySQL数据库时,我们使用较多的库是PyMySQL,如果你选择使用PyMySQL库,那么首先需要通过pip安装它。pipinstallpymysql命令就是用来安装PyMySQL的。安装PyMySQL1.打开你的命令行工具(如cmd、PowerShell、......
  • Python按条件删除Excel表格数据的方法
      本文介绍基于Python语言,读取Excel表格文件,基于我们给定的规则,对其中的数据加以筛选,将不在指定数据范围内的数据剔除,保留符合我们需要的数据的方法。  首先,我们来明确一下本文的具体需求。现有一个Excel表格文件(在本文中我们就以.csv格式的文件为例),如下图所示。  其中,Ex......
  • Python 提取出SQL语句中Where的值的方法
    1.方法一:使用sqlparse库的方法为了提取SQL语句中WHERE子句的值,我们可以利用Python的sqlparse库,这是一个专门用于解析SQL语句的库。以下是一个示例代码,演示如何使用sqlparse来提取WHERE子句中的条件。首先,确保安装了sqlparse库。如果未安装,可以使用pip安装:bash复制代码pipins......
  • 12-python函数的传参——形参、实参、装包 *args和**kwargs
    函数的参数1形参和实参函数的参数:在定义函数时,可以再函数名后()中定义数量不等的形参,注意可以有也可以没有,可有一个也可有多个,多个形参之间用逗号隔开形参(形式参数):定义形参就相当于在函数内部声明了变量,但是并不赋值实参(实际参数):在函数定义时指定了形参,在调用的时......
  • 《信息学奥赛一本通编程启蒙》3031-3050(Scratch、C、C++、python)
    3031:练7.3买图书(C、C++、python)3031:练7.3买图书(C、C++、python)-CSDN博客3032:练7.4梯形面积(C、C++、python)3032:练7.4梯形面积(C、C++、python)-CSDN博客3033:【例8.1】人民币支付(Scratch、C、C++、python)3033:【例8.1】人民币支付(Scratch、C、C++、python)-CSDN博客3......