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

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

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, но он по-прежнему устает читать дополнительные параметры.

Ответ 1

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

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

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

Ответ 2

Если вам не нужны функции командной строки модуля 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()

Ответ 3

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

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()

Ответ 4

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

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