Тест Django с setUpTestData не сохраняет изменений между тестами - PullRequest
0 голосов
/ 04 октября 2019

classmethod TestCase.setUpTestData ()

Описанный выше атомарный блок уровня класса позволяет создавать начальные данные на уровне класса, один раз для всего TestCase.

[...]

Будьте осторожны, чтобы не изменять любые объекты, созданные в setUpTestData () в ваших тестовых методах. Изменения, вносимые в объекты в оперативной памяти в результате работы по настройке, выполненной на уровне класса, будут сохраняться между методами тестирования.

Цит. django.test.TestCase.setUpTestData

Рассмотрим этот пример:

class FoobarTest(TestCase):

    @classmethod
    def setUpTestData(cls):
        cls.post = Post()
        cls.post.stats = {}
        cls.post.save()

    def setUp(self):
        self.post.refresh_from_db()

    def test_foo(self):
        self.post.stats['foo'] = 1
        self.post.save()
        self.assertEquals(self.post.stats, {'foo': 1}) # this should fail

    def test_bar(self): # this run first cause alphabetical order
        self.post.stats['bar'] = 1
        self.post.save()
        self.assertEquals(self.post.stats, {'bar': 1})

Начиная с

Изменения объектов в памяти из установкиработа, выполненная на уровне класса, будет продолжаться между методами тестирования

Я ожидаю, что один из двух методов тестирования потерпит неудачу, поскольку у объекта post также будет другое свойство, и равенство должно завершиться неудачей.

Но этот тест пройден без проблем.

Если я навязываю порядок выполнения, он на самом деле ведет себя как ожидалось:

class FoobarTest(TestCase):

    @classmethod
    def setUpTestData(cls):
        cls.post = Post()
        cls.post.stats = {}
        cls.post.save()

    def setUp(self):
        self.post.refresh_from_db()

    def _foo(self):
        self.post.stats['foo'] = 1
        self.post.save()
        self.assertEquals(self.post.stats, {'foo': 1})

    def _bar(self):
        self.post.stats['bar'] = 1
        self.post.save()
        self.assertEquals(self.post.stats, {'bar': 1})

    def test_foo_bar(self):
        self._foo()
        self._bar() # this fail

Вопрос:

вПервый пример: методы тестирования работают в некотором параллелизме? Могут ли они действительно потерпеть неудачу при некоторых совпадениях, связанных со временем?

Документы Django о порядке, в котором выполняются тесты не говорят о методах тестирования.

В этот пост я обнаружил, что порядок методов тестирования может быть изменен, но один за другим, без параллелизма, если я не использую python manage.py test --parallel.

1 Ответ

1 голос
/ 04 октября 2019

Это мой тест, использующий память вместо базы данных:

from django.test import TestCase

class Post(object):
    def __init__(self):
        self.stats = {}

    def refresh_from_db(self):
        pass

    def save(self):
        pass


class FoobarTest(TestCase):

    @classmethod
    def setUpTestData(cls):
        cls.post = Post()
        cls.post.stats = {}

    def setUp(self):
        self.post.refresh_from_db()

    def test_foo(self):
        self.post.stats['foo'] = 1
        self.post.save()
        self.assertEquals(self.post.stats, {'foo': 1})  # this should fail

    def test_bar(self):  # this run first cause alphabetical order
        self.post.stats['bar'] = 1
        self.post.save()
        self.assertEquals(self.post.stats, {'bar': 1})

И это мой результат:

    self.assertEquals(self.post.stats, {'foo': 1})  # this should fail
AssertionError: {'bar': 1, 'foo': 1} != {'foo': 1}
- {'bar': 1, 'foo': 1}
+ {'foo': 1}

Изменение метода foo на afoo,результат, как и ожидалось:

    self.assertEquals(self.post.stats, {'bar': 1})
AssertionError: {'foo': 1, 'bar': 1} != {'bar': 1}
- {'bar': 1, 'foo': 1}
+ {'bar': 1}

Так, может быть, это проблема с базой данных?

По вашему утверждению вы проверяете объекты в памяти: если save не удается, refresh_from_db возвращаетначальный пустой объект, поэтому следующая проверка пройдена.

Попробуйте вернуть данные после save, затем проверьте их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...