Перегрузка имени модуля и путь импорта - PullRequest
1 голос
/ 06 января 2012

Приведенный ниже код завершается ошибкой, потому что twisted.trial.unittest.TestCase, требуемый базовый класс, не является базовым классом.

from twisted.trial import unittest
from unittest import TestCase
import myapp

class Feature(TestCase):

  def setUp(self):
    self.callbackCounter = 0

  def checkCbCalled(self, expected):
      self.assertEqual(self.callbackCounter, expected)

  def testTrialCallsDeferred(self):

      d = myapp.buildFeature()
      self.addCleanup(self.checkCbCalled, expected=1)
      def cb(res):
        self.callbackCounter += 1
      d.addCallback(cb).addErrback(self.fail)
      return d           # does not fire because of 'import rules'?

Если бы я сказал

from twisted.trial import unittest as trialut
from trialut import TestCase 

или, что лучше:

from twisted.trial.unittest import TestCase

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

Кажется, что локальная недавно импортированная вещь должна была заменить замену доступной в {lib / pythonX.X / unittest}.Я понимаю, что это должно быть правило, основанное на sys.path или что-то еще неявное или явное.Это сбило меня с толку слишком долго, потому что у меня не было вызова addCleanup, и все тесты проходили, потому что возвращенный отложенный экземпляр не запускался.

Я нарушил некоторые правила, пожалуйста, посоветуйте прочитатьили другое.

Спасибо, Майк

1 Ответ

2 голосов
/ 06 января 2012

Очень непонятно, как вы ожидаете, что это будет работать, но, похоже, вы, по крайней мере, несколько озадачены поведением модулей в Python.

Оператор import (иногда) загружает модуль изисходный файл, а затем привязывает имя в локальной области видимости к этому объекту модуля.

Итак, когда вы делаете:

from twisted.trial import unittest

Вы загружаете модуль twisted.trial.unittest и затем привязываетелокальное имя unittest it.

Это не очень интересно взаимодействует со следующим оператором:

from unittest import TestCase

, который загружает модуль unittest и затем привязывает локальное имя TestCase кобъект, на который ссылается атрибут TestCase этого модуля.

Когда вы позже подклассом TestCase:

class Feature(TestCase):
    ...

, вы прямо используете имя TestCase в своем локальномscope - имя, которое ссылается на класс TestCase, определенный модулем unittest.Обратите внимание, что он не имеет ничего общего с модулем Twisted twisted.trial.unittest, даже если вы загрузили этот модуль тоже.Вы должны использовать один из его атрибутов, чтобы использовать его функциональность.

Чтобы изменить поведение вашего кода, нужно просто прекратить вообще использовать стандартный модуль библиотеки unittest.Удалите эту строку:

from unittest import TestCase

И замените определение вашего класса на:

class Feature(unittest.TestCase):

Не смущайтесь тем, что модуль стандартной библиотеки unittest разделяет часть именимодуля Twisted twisted.trial.unittest.Это разные модули с разными (хотя и похожими, иногда перекрывающимися) функциями.Определение класса в приведенном выше примере использует twisted.trial.unittest, потому что оно идет после исходной строки:

from twisted.trial import unittest

Как только вы фактически используете Twisted TestCase (из twisted.trial.unittest), а не стандартную библиотекуTestCase (из unittest), вы получите ожидаемое поведение, когда тестовый метод вернет Deferred.Это связано с тем, что Twisted предоставляет эту функцию, а не стандартную библиотеку.

...