模拟单元测试中的时间流逝 [英] Simulating the passing of time in unittesting

查看:108
本文介绍了模拟单元测试中的时间流逝的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经为客户构建了付费墙CMS +开票系统,我需要对测试进行更严格的测试.

I've built a paywalled CMS + invoicing system for a client and I need to get more stringent with my testing.

我将所有数据保存在Django ORM中,并且有许多Celery任务以不同的时间间隔运行,以确保在用户不支付发票时发送新的发票和发票提醒,并减少访问权限.

I keep all my data in a Django ORM and have a bunch of Celery tasks that run at different intervals that makes sure that new invoices and invoice reminders get sent and cuts of access when users don't pay their invoices.

例如,我希望能够进行以下测试:

For example I'd like to be a able to run a test that:

  1. 创建新用户并生成X天访问网站的发票

  1. Creates a new user and generates an invoice for X days of access to the site

模拟X +1天的过去,并运行我在Celery中设置的所有任务.

Simulates the passing of X + 1 days, and runs all the tasks I've got set up in Celery.

检查是否已向用户发出了另外X天的新发票.

Checks that a new invoice for an other X days has been issued to the user.

到目前为止,我想出的KISS方法是在一台单独的机器上进行所有测试,并实际上在操作系统级别上操纵日期/时间.因此测试脚本将:

The KISS approach I've come up with so far is to do all the testing on a separate machine and actually manipulate the date/time at the OS-level. So the testing script would:

  1. 将系统日期设置为第一天

  1. Set the system date to day 1

创建一个新用户并生成X天的第一张发票

Create a new user and generate the first invoice for X days of access

将系统日期提前1天.运行我所有的芹菜任务.重复直到X + 1天已经过去"

Advance then system date 1 day. Run all my celery tasks. Repeat until X + 1 days have "passed"

检查是否已签发新发票

这有点笨拙,但我认为它可能会起作用.还有其他有关如何完成工作的想法吗?

It's a bit clunky but I think it might work. Any other ideas on how to get it done?

推荐答案

您可以使用 mock 更改用于获取时间的函数的返回值(例如datetime.datetime.now).

You can use mock to change the return value of the function you use to get the time (datetime.datetime.now for example).

有多种方法(请参见模拟文档),但这是一种方法:

There are various ways to do so (see the mock documentation), but here is one :

import unittest
import datetime
from mock import patch

class SomeTestCase(unittest.TestCase):
    def setUp(self):
        self.time = datetime.datetime(2012, 5, 18)
        class fakedatetime(datetime.datetime):
            @classmethod
            def now(cls):
                return self.time
        patcher = patch('datetime.datetime', fakedatetime)
        self.addCleanup(patcher.stop)
        patcher.start()

    def test_something(self):
        self.assertEqual(datetime.datetime.now(), datetime.datetime(2012, 5, 18))
        self.time = datetime.datetime(2012, 5, 20)
        self.assertEqual(datetime.datetime.now(), datetime.datetime(2012, 5, 20))

因为我们不能直接替换datetime.datetime.now,所以我们创建了一个伪造的datetime类,它以相同的方式进行所有操作,除了在调用now时返回恒定值.

Because we can't replace directly datetime.datetime.now, we create a fake datetime class that does everything the same way, except returning a constant value when now is called.

这篇关于模拟单元测试中的时间流逝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆