gpt4 book ai didi

python - 使用基于日期/时间的对象进行 Django 单元测试

转载 作者:IT老高 更新时间:2023-10-28 22:18:01 28 4
gpt4 key购买 nike

假设我有以下 Event 模型:

from django.db import models
import datetime

class Event(models.Model):
date_start = models.DateField()
date_end = models.DateField()

def is_over(self):
return datetime.date.today() > self.date_end

我想测试 Event.is_over(),方法是创建一个在未来(今天 + 1 或其他)结束的事件,并 stub 日期和时间,以便系统认为我们已经到达那个 future 的日期。

就 python 而言,我希望能够 stub 所有系统时间对象。这包括 datetime.date.today()datetime.datetime.now() 和任何其他标准日期/时间对象。

执行此操作的标准方法是什么?

最佳答案

编辑:由于我的答案是此处公认的答案,因此我将对其进行更新,以让每个人都知道同时创建了更好的方法, freezegun 库:https://pypi.python.org/pypi/freezegun .当我想影响测试时间时,我会在所有项目中使用它。看看吧。

原答案:

更换这样的内部 Material 总是很危险的,因为它可能会产生令人讨厌的副作用。所以你真正想要的是让猴子补丁尽可能地本地化。

我们使用 Michael Foord 出色的模拟库:http://www.voidspace.org.uk/python/mock/有一个 @patch 装饰器可以修补某些功能,但是猴子补丁只存在于测试功能的范围内,并且在功能用完其范围后一切都会自动恢复。

唯一的问题是内部的 datetime 模块是用 C 实现的,所以默认情况下您无法对其进行修补。我们通过制作自己的简单实现来解决这个问题,可以模拟。

整个解决方案是这样的(示例是在 Django 项目中使用的验证器函数,用于验证日期是否在未来)。请注意,我从一个项目中取出了这个,但取出了不重要的东西,所以在复制粘贴时,事情可能实际上不起作用,但我希望你明白了 :)

首先,我们在一个名为 utils/date.py 的文件中定义我们自己非常简单的 datetime.date.today 实现:

import datetime

def today():
return datetime.date.today()

然后我们在 tests.py 中为这个验证器创建单元测试:

import datetime
import mock
from unittest2 import TestCase

from django.core.exceptions import ValidationError

from .. import validators

class ValidationTests(TestCase):
@mock.patch('utils.date.today')
def test_validate_future_date(self, today_mock):
# Pin python's today to returning the same date
# always so we can actually keep on unit testing in the future :)
today_mock.return_value = datetime.date(2010, 1, 1)

# A future date should work
validators.validate_future_date(datetime.date(2010, 1, 2))

# The mocked today's date should fail
with self.assertRaises(ValidationError) as e:
validators.validate_future_date(datetime.date(2010, 1, 1))
self.assertEquals([u'Date should be in the future.'], e.exception.messages)

# Date in the past should also fail
with self.assertRaises(ValidationError) as e:
validators.validate_future_date(datetime.date(2009, 12, 31))
self.assertEquals([u'Date should be in the future.'], e.exception.messages)

最终的实现如下所示:

from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError

from utils import date

def validate_future_date(value):
if value <= date.today():
raise ValidationError(_('Date should be in the future.'))

希望对你有帮助

关于python - 使用基于日期/时间的对象进行 Django 单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1042900/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com