2013-12-09 6 views
3

Я получаю противоречивое поведение с модульными тестами Django. На моей машине разработки с использованием sqlite, если я запускаю тесты по двум моим приложениям отдельно, тесты проходят, но если я запустил manage.py test, чтобы проверить все сразу, я сразу же получаю сбои тестирования модулей на двух тестах.Единичные тесты Django не работают при работе с другими тестовыми примерами

На моем промежуточном сервере, который использует Postgres, у меня есть специальный тест, который работает при его тестировании отдельно (например, manage.py test MyApp.tests.MyTestCase.testSomething), но не работает при запуске всего тестового примера (например, manage.py test MyApp.tests.TestCase).

Другие смежные вопросы StackOverflow, кажется, есть два решения:

  1. Использование Django TestCase вместо питона эквивалентного
  2. Использование TransactionTestCase, чтобы убедиться, что база данных очищается должным образом после каждого теста.

Я пробовал оба безрезультатно. Из разочарования я также попытался использовать django-нос вместо этого, но я видел те же ошибки. Я на Django 1.6.

+1

Какая именно ошибка? – e4c5

+0

Ошибка не имеет большого смысла, не видя всего модульного теста, но в основном тест не отвечает, что объект, который должен был быть создан после выполнения POST, не существует. – mathew

+0

@mathew вы можете опубликовать все ваши юнит-тесты и полную ошибку? Используете ли вы django 'TestCase' для всех своих тестов? У вас есть утечка данных? Что приятно в «TestCase» django, он вытирает ваш db после каждого теста – dm03514

ответ

1

Помимо использования TestCase для всех ваших тестов, вы должны убедиться, что вы срывать любые заплатки, что было сделано в ваших методах установки:

def setUp(self): 
    self.patcher = patch('my.app.module') 

def tearDown(self): 
    self.patcher.stop() 
1

Я только что провел весь день отладки подобной проблемы. В моем случае вопрос был следующим.

В одной из моих функций функции я использовал функцию Django send_mail(). В моем тесте, вместо того, чтобы это отправить мне по электронной почте каждый раз, когда я выбежала мои тесты, я patch ред send_mail в моем методе испытаний:

from mock import patch 
... 

def test_stuff(self): 
    ... 

    with patch('django.core.mail.send_mail') as mocked_send_mail: 

    ... 

Таким образом, после того, как моя функция зрения называется, я могу проверить, что send_mail был вызван с:

self.assertTrue(mocked_send_mail.called) 

Это работало нормально при выполнении теста самостоятельно, но не удавалось при выполнении других тестов в наборе. Причина, по которой это не удается, заключается в том, что когда она запускается как часть пакета, другие представления вызываются заранее, в результате чего загружается файл views.py, в результате чего send_mail должен быть импортирован до Я получаю возможность patch. Поэтому, когда на мой взгляд вызывается send_mail, это фактический send_mail, который вызывается, а не моя исправленная версия. Когда я запускаю только тест, функция получает издевательство до, она импортируется, поэтому исправленная версия заканчивается тем, что импортируется, когда загружается views.py. Эта ситуация описана в mock documentation, которую я прочитал несколько раз раньше, но теперь хорошо понимаю, узнав трудный путь ...

Решение было простым: вместо исправления django.core.mail.send_mail Я только что запустил версию, уже был импортирован в мой views.py - myapp.views.send_mail. Другими словами:

with patch('myapp.views.send_mail') as mocked_send_mail: 
... 

Это заняло у меня много времени для отладки, поэтому я решил поделиться своим решением. Надеюсь, это сработает и для вас. Возможно, вы не используете издевки, и в этом случае это, вероятно, вам не поможет, но я надеюсь, что это поможет кому-то.

Смежные вопросы