Проблема с sys.argv [1], когда модуль unittest находится в скрипте - PullRequest
11 голосов
/ 11 мая 2010

У меня есть сценарий, который выполняет различные действия и получает доступ к параметрам, используя sys.argv, но когда сценарий попадает в часть кода unittest, он говорит, что для этого нет модуля. Сценарий, который у меня есть:

class MyScript():

    def __init__(self):
        self.value = sys.argv[1]

    def hello(self):
        print self.value

    def suite(self):
        modules_to_test = ('external_sanity_onvif', 'starttest')
        alltests = unittest.TestSuite()
        for module in map(__import__, modules_to_test):
            alltests.addTest(unittest.findTestCases(module))
        return alltests


if __name__ == '__main__': 
    Run = MyScript()
    Run.hello()
    log_file = 'log_file.txt'
    test_file = open(log_file, "w") 
    runner = unittest.TextTestRunner(test_file)
    unittest.main(defaultTest='Run.suite', testRunner=runner)

Скажите, что я ввожу ./script.py Hello в командной строке. Я получаю ошибку:

AttributeError: 'module' object has no attribute 'Hello'

Если я удаляю модуль unittest, он работает. Также, если я удалю журнал testrunner и оставлю его по адресу:

unittest.main(defaultTest='Run.suite')

Это все еще не работает.

Может кто-нибудь помочь.

Спасибо

Я попробовал этот хак, но он все еще пытается прочитать sys.argv.

project = sys.argv[4:]
sys.argv = sys.argv[0:4]

Я пробовал это только с argv, но все еще устает читать дополнительные параметры.

Ответы [ 4 ]

16 голосов
/ 15 мая 2010

Проблема в том, что unittest.main() хочет, чтобы ваш драгоценный argv использовался им самим! Он использует либо argv, который вы передаете ему в качестве параметра функции, либо sys.argv, если вы не передаете его argv явно, и пытается загрузить тесты с именами аргументов, которые вы даете. В этом случае это означает, что он ищет подмодуль с именем Hello, класс TestCase с именем Hello, метод тестового примера в классе тестового случая с именем Hello или вызываемый объект с именем Hello, который возвращает экземпляр TestCase или TestSuite, все в пределах вашего модуля 'script'.

Есть несколько способов исправить это:

  • Обходите unittest.main() и вызывайте функции юнит-теста нижнего уровня для настройки и запуска тестовых примеров, которые вы имеете в виду.
  • Удалите зависимость вашего кода от sys.argv и используйте поведение unittest.main() в ваших интересах. Если ваш модуль не предназначен для запуска независимо , за исключением в качестве модульного теста, это, вероятно, имеет смысл, поскольку вызывающие модули вашего модуля могут не ожидать, что вы прочитаете их argv!
  • Разделите тестовый код и основную процедуру на отдельный тестовый модуль. Вам все равно придется выяснить, как получить правильный argv в ваш код из тестового модуля.
  • Укажите argv=[sys.argv[0]] в качестве аргумента unittest.main(); это должно удерживать его от попыток прочитать ваше.
6 голосов
/ 13 августа 2011

Если вам не нужны функции командной строки модуля unittest, вы можете заставить модули optparse и unittest хорошо играть вместе, изменив sys.argv непосредственно перед вызовом unittest.main()

Попробуйте это прямо перед вашим unittest.main() звонком:

del sys.argv[1:]

При этом удаляются аргументы командной строки до того, как unittest их видит.

Если вы не используете модуль optparse, вы можете сделать это вместо этого:

my_args = sys.argv[1:]
del sys.argv[1:]
# do_stuff(my_args)
unittest.main()
1 голос
/ 11 мая 2010

Вообще говоря, идея модульного тестирования заключается в том, что тесты выполняются без внешнего драйвера. Например. Вы не хотите зависеть от некоторого ввода из командной строки. Решение, которое вы ищете, может быть через использование светильников?

import sys
import unittest

class MyScript(unittest.TestCase):
    def setUp(self):
        self.value = "Default Value"

    def setHello(self, value):
        self.value = value

    def hello(self):
        return self.value

class UserA(MyScript):
    def setUp(self):
        self.setHello("UserA")

    def testMyName(self):
        self.failUnlessEqual(self.hello(), "UserA")

class UserB(MyScript):
    def setUp(self):
        self.setHello("UserB")

    def testMyName(self):
        self.failUnlessEqual(self.hello(), "UserB")

if __name__ == '__main__': 
    unittest.main()
0 голосов
/ 11 мая 2010

Python предоставляет вам всю информацию, которую он может, и если вы не хотите публиковать весь набор вещей, которые вы пытаетесь проверить, мы можем только догадываться о том, чего вы пытаетесь достичь. Ошибка говорит, что нет атрибута с именем «Hello», поэтому, возможно, модули, которые вы пытаетесь протестировать, должны получить такую ​​переменную, функцию или иное.

Есть ли причина, по которой вы не просто используете unittest.main()?

...