Перезаписать auto_now для unittest - PullRequest
6 голосов
/ 16 февраля 2010

Я определил некоторые временные метки для событий в базе данных как auto_now_add, поскольку информация должна храниться вместе с ее временной меткой одновременно с сохранением события.

Описание событий что-то вроде

class NewEvent(models.Model):
    '''
    Individual event
    '''
    name = models.CharField(max_length=100)
    quantity = models.FloatField(null=True)
    timestamp = models.DateTimeField(auto_now_add=True)

Чтобы проверить модуль, я генерирую некоторую информацию в базе данных в файле test.py, таким образом:

    for event in EVENT_TYPES:
        time = datetime.datetime.now() - datetime.timedelta(days=1)
        for i in range(48):
            time = time.replace(hour=i / 2)
            NewEvent(name=event,
                     timestamp=time,
                     quantity=i).save()

Я должен генерировать события с временной меткой вчерашнего дня (модуль затем суммирует их). Проблема в том, что вы не можете перезаписать метку времени. Временная метка - это дата, когда производится событие, в документации это очень четко указано.

Итак, как генерировать данные с соответствующими временными метками для тестирования? У меня было несколько идей:

  • Может быть, генерировать данные базы данных другим способом, вне классов Model. Где и как?
  • Каким-то образом определите другой класс или измените класс, чтобы он вел себя по-разному во время теста, что-то вроде

_

 if testing:
     timestamp = models.DateTimeField(auto_now_add=True)
 else:
     timestamp = models.DateTimeField(auto_now_add=False)

Или, может быть, есть еще более простой способ сделать это ... Есть идеи?

Ответы [ 3 ]

3 голосов
/ 04 июня 2013

Проблема с приборами для меня заключается в том, что мне нужно проверить, что некоторые записи, которые старше 30 дней, не возвращаются, а те, которые не являются 30 днями, возвращаются ... с помощью статических приборов это невозможно сделать ( ленивым способом). Поэтому я решил смоделировать функцию timezone.now, которую django использует для получения даты и времени.

from django.utils import timezone 

class SomeTestCase(TestCase):
    def test_auto_add(self):
        now = timezone.now()
        now_31 = now - datetime.timedelta(days=31)
        self.mock('timezone.now', returns=now_31, tracker=None)
        SomeObject.objects.create() # has auto_now_add field ...   

для насмешек я использую minimocktest

2 голосов
/ 16 февраля 2010

Мне удалось создать данные, переопределяющие значения по умолчанию, с помощью прибора.

Я создал test_data.json файл с данными в следующем формате:

[
{
    "model": "stats_agg.newevent",
    "pk": 1,
    "fields": {
        "name": "event1",
        "quantity":0.0,
        "timestamp": "2010-02-15 00:27:40"
     }
},
{
    "model": "stats_agg.newevent",
    "pk": 2,
    "fields": {
        "name": "event1",
        "quantity":1.0,
        "timestamp": "2010-02-15 00:27:40"
     }
},
...

, а затем добавить в тестовый блок

class SimpleTest(TestCase):
   fixtures = ['test_data.json']
1 голос
/ 25 октября 2017

Другой способ справиться с этим - использовать QuerySet update после создания экземпляра, что может быть более полезным в зависимости от вашего варианта использования.

Поскольку вызов update выполняется на уровне SQL, он пропускает проверку, сигналы и пользовательские функции сохранения. Это потребует вторичного вызова базы данных, который может повлиять на производительность, поэтому его следует использовать с учётом.

for event in EVENT_TYPES:
    time = datetime.datetime.now() - datetime.timedelta(days=1)
    for i in range(48):
        time = time.replace(hour=i / 2)
        instance = NewEvent(name=event, quantity=i).save()
        NewEvent.objects.filter(pk=instance.pk).update(timestamp=time)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...