20

クライアント用にペイウォール CMS + 請求システムを構築しましたが、テストをより厳密にする必要があります。

私はすべてのデータを Django ORM に保管し、さまざまな間隔で実行される一連の Celery タスクを使用して、ユーザーが請求書を支払わないときに新しい請求書と請求書のリマインダーが送信され、アクセスがカットされるようにします。

たとえば、次のようなテストを実行できるようになりたいです。

  1. 新しいユーザーを作成し、サイトへの X 日間のアクセスに対する請求書を生成します

  2. X + 1 日の経過をシミュレートし、Celery で設定したすべてのタスクを実行します。

  3. 他の X 日間の新しい請求書がユーザーに発行されていることを確認します。

私がこれまでに思いついた KISS のアプローチは、すべてのテストを別のマシンで行い、実際に OS レベルで日付/時刻を操作することです。したがって、テスト スクリプトは次のようになります。

  1. システム日付を 1 日目に設定する

  2. 新しいユーザーを作成し、X 日間のアクセスに対する最初の請求書を作成します

  3. システム日付を 1 日進めます。すべてのセロリ タスクを実行します。X + 1 日が「経過」するまで繰り返す

  4. 新しい請求書が発行されたことを確認する

少し面倒ですが、うまくいくと思います。それを成し遂げる方法に関する他のアイデアはありますか?

4

3 に答える 3

18

モックを使用して、時間を取得するために使用する関数の戻り値を変更できます (たとえばdatetime.datetime.now)。

これにはさまざまな方法があります (モックのドキュメントを参照)。

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、 now が呼び出されたときに定数値を返すことを除いて、すべて同じ方法で行う偽の datetime クラスを作成します。

于 2012-05-18T12:29:12.897 に答える
4

特別なモック ライブラリを使用せずに、(おそらくグローバル変数によって) モックアップ モードになるようにコードを準備することを提案します。モックアップ モードでは、通常の時間関数 (time.time() など) を呼び出す代わりに、特別な場合に必要なものを返すモックアップ時間関数を呼び出すことができます。

システム時刻の変更には反対票を投じます。これは単体テストのようには見えませんが、そのマシン上の他のものと並行して実行できないため、機能テストのように見えます。

于 2012-05-18T13:28:41.980 に答える