【问题标题】:Unit-testing datetime单元测试日期时间
【发布时间】:2021-11-09 20:02:36
【问题描述】:

有人可以帮我对这行代码进行单元测试吗?

from datetime import datetime, timedelta, timezone

def get_timestamp_plus_100_year():
    return int((datetime.now(timezone.utc) + timedelta(days=100 * 365)).timestamp())

我试试这个,但我不知道如何分配值:

@patch("src.shared.utils.timedelta")
@patch("src.shared.utils.datetime")
def test_get_timestamp_now_plus_100_years(self, mock_datetime, mock_timedelta):
    mock_datetime.now.return_value = 2021-09-14 15:54:25.284087+00:00
    mock_timedelta.return_value = 36500 days, 0:00:00

    self.assertEqual(
        get_timestamp_plus_100_year(),
        int((mock_datetime.now.return_value 
             + mock_timedelta.return_value).timestamp_return_value ),
    )

【问题讨论】:

  • 你想在这里实现什么?请注意,并非每年都有 365 天。

标签: python python-3.x python-unittest python-datetime python-unittest.mock


【解决方案1】:

首先更正实现。正如@MrFuppes 所指出的,并非所有年份都是365 天。假设今天是2021-9-15,您的原始实现将导致:

>>> datetime.now(timezone.utc) + timedelta(days=100 * 365)
datetime.datetime(2121, 8, 22, 9, 19, 30, 468735, tzinfo=datetime.timezone.utc)

在这里,您可以看到我们得到的不是预期的2121-9-15,而是2121-8-22

选项1:使用datetime.replace()year替换为year+100

>>> (dt := datetime.now(timezone.utc)).replace(year=dt.year + 100)
datetime.datetime(2121, 9, 15, 9, 24, 52, 139984, tzinfo=datetime.timezone.utc)

选项 2: 使用 dateutil.relativedelta.relativedelta 添加 +100 年。这需要pip install python-dateutil

>>> datetime.now(timezone.utc) + relativedelta(years=100)
datetime.datetime(2121, 9, 15, 9, 28, 16, 789807, tzinfo=datetime.timezone.utc)

然后,您不需要模拟 timedelta(或我们更正代码中的 relativedelta),因为它的值将始终为 100 年。您只需要通过datetime.now() 模拟当前日期,因为它是加法的基础,我们需要断言结果。

假设这是文件树:

.
├── src.py
└── test_src.py

src.py

from datetime import datetime, timezone

from dateutil.relativedelta import relativedelta


def get_timestamp_plus_100_year():
    return int((datetime.now(timezone.utc) + relativedelta(years=100)).timestamp())

解决方案一:

from datetime import datetime
import unittest
from unittest.mock import patch

from dateutil.relativedelta import relativedelta

from src import get_timestamp_plus_100_year


class TestDates(unittest.TestCase):
    @patch("src.datetime")
    def test_get_timestamp_now_plus_100_years(self, mock_datetime):
        frozen_dt = datetime(year=2021, month=9, day=15)
        mock_datetime.now.return_value = frozen_dt

        # Solution 1.1
        self.assertEqual(
            get_timestamp_plus_100_year(),
            int((frozen_dt + relativedelta(years=100)).timestamp()),
        )

        # Solution 1.2
        frozen_dt_100 = datetime(year=2121, month=9, day=15)  # Since we already know the value of +100 years, we can just define it here
        self.assertEqual(
            get_timestamp_plus_100_year(),
            int(frozen_dt_100.timestamp()),
        )

解决方案 2

这需要freezegun 通过pip install freezegun

from datetime import datetime
import unittest

from freezegun import freeze_time

from src import get_timestamp_plus_100_year


@freeze_time("2021-09-15")  # Either here
class TestDates(unittest.TestCase):
    @freeze_time("2021-09-15")  # Or here
    def test_get_timestamp_now_plus_100_years_2(self):
        frozen_dt_100 = datetime(year=2121, month=9, day=15)  # Since we already know the value of +100 years, we can just define it here
        self.assertEqual(
            get_timestamp_plus_100_year(),
            int(frozen_dt_100.timestamp()),
        )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    • 2017-01-08
    • 2017-09-01
    相关资源
    最近更新 更多