Подтвердить что ты не робот

Python unittest передает аргументы

В python, как передать аргумент из командной строки в функцию unittest. Вот код до сих пор... Я знаю, что это неправильно.

class TestingClass(unittest.TestCase):

    def testEmails(self):
        assertEqual(email_from_argument, "[email protected]")


if __name__ == "__main__":
    unittest.main(argv=[sys.argv[1]])
    email_from_argument = sys.argv[1] 
4b9b3361

Ответ 1

Развернуть с приведенным выше комментарием об модульных тестах. Единичные тесты должны быть автономными, поскольку они не имеют зависимостей вне их требований к настройке и срыву, например, в вашем случае с настройкой электронной почты. Это гарантирует, что каждый тест имеет очень специфические побочные эффекты и реакции на тест. Передача в параметре поражает это свойство модульных тестов и, таким образом, делает их в некотором смысле недействительными. Использование тестовой конфигурации было бы самым простым способом - и более правильным, потому что снова unit test никогда не должен полагаться на внешнюю информацию для проведения теста. То есть для тестов интеграции.

Ответ 2

Итак, врачи здесь говорят: "Вы говорите, что больно? Тогда не делайте этого!" вероятно правы. Но если вы действительно хотите, вот один из способов передачи аргументов в тест модульного теста:

import sys
import unittest

class MyTest(unittest.TestCase):
    USERNAME = "jemima"
    PASSWORD = "password"

    def test_logins_or_something(self):
        print('username : {}'.format(self.USERNAME))
        print('password : {}'.format(self.PASSWORD))


if __name__ == "__main__":
    if len(sys.argv) > 1:
        MyTest.USERNAME = sys.argv.pop()
        MyTest.PASSWORD = sys.argv.pop()
    unittest.main()

это позволит вам работать с:

python mytests.py ausername apassword

Вам нужен argv.pop, чтобы ваши параметры командной строки не связывались с собственным unittest...

[update] Другая вещь, на которую вы можете обратить внимание, - это использование переменных среды:

import os
import unittest

class MyTest(unittest.TestCase):
    USERNAME = "jemima"
    PASSWORD = "password"

    def test_logins_or_something(self):
        print('username : {}'.format(self.USERNAME))
        print('password : {}'.format(self.PASSWORD))


if __name__ == "__main__":
    MyTest.USERNAME = os.environ.get('TEST_USERNAME', MyTest.USERNAME)            
    MyTest.PASSWORD = os.environ.get('TEST_PASSWORD', MyTest.PASSWORD)
    unittest.main()

Это позволит вам работать с:

TEST_USERNAME=ausername TEST_PASSWORD=apassword python mytests.py

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

Ответ 3

Еще один метод для тех, кто действительно хочет сделать это, несмотря на правильные замечания, которые вы не должны делать:

import unittest

class MyTest(unittest.TestCase):

    def __init__(self, testName, extraArg):
        super(MyTest, self).__init__(testName)  # calling the super class init varies for different python versions.  This works for 2.7
        self.myExtraArg = extraArg

    def test_something(self):
        print(self.myExtraArg)

# call your test
suite = unittest.TestSuite()
suite.addTest(MyTest('test_something', extraArg))
unittest.TextTestRunner(verbosity=2).run(suite)

Ответ 4

Если вы хотите использовать подход steffens21 с помощью unittest.TestLoader, вы можете изменить оригинальный тестовый загрузчик (см. unittest.py):

import unittest
from unittest import suite

class TestLoaderWithKwargs(unittest.TestLoader):
    """A test loader which allows to parse keyword arguments to the
       test case class."""
    def loadTestsFromTestCase(self, testCaseClass, **kwargs):
        """Return a suite of all tests cases contained in 
           testCaseClass."""
        if issubclass(testCaseClass, suite.TestSuite):
            raise TypeError("Test cases should not be derived from "\
                            "TestSuite. Maybe you meant to derive from"\ 
                            " TestCase?")
        testCaseNames = self.getTestCaseNames(testCaseClass)
        if not testCaseNames and hasattr(testCaseClass, 'runTest'):
            testCaseNames = ['runTest']

        # Modification here: parse keyword arguments to testCaseClass.
        test_cases = []
        for test_case_name in testCaseNames:
            test_cases.append(testCaseClass(test_case_name, **kwargs))
        loaded_suite = self.suiteClass(test_cases)

        return loaded_suite 

# call your test
loader = TestLoaderWithKwargs()
suite = loader.loadTestsFromTestCase(MyTest, extraArg=extraArg)
unittest.TextTestRunner(verbosity=2).run(suite)

Ответ 5

Иметь такую ​​же проблему. Мое решение - после того, как вы обрабатываете аргументы анализа с помощью argparse или другим способом, удалите аргументы из sys.argv

sys.argv = sys.argv[:1]  

Если вам нужно, вы можете фильтровать unittest аргументы из main.parseArgs()

Ответ 6

Даже если тестовые гуру говорят, что мы не должны этого делать: я знаю. В некотором контексте имеет смысл иметь параметры для тестирования теста в правильном направлении, например:

  • какой из дюжины идентичных USB-карт следует использовать для этого теста сейчас?
  • какой сервер мне следует использовать для этого теста?
  • который XXX следует использовать?

Для меня использование переменной окружения достаточно хорошо для этого puprose, потому что вам не нужно писать выделенный код для передачи ваших параметров; он поддерживается Python. Это чисто и просто.

Конечно, я не сторонник полностью параметризуемых тестов. Но мы должны быть прагматичными и, как я уже сказал, в каком-то контексте вам нужен параметр или два. Мы не должны этого делать:)

import os
import unittest


class MyTest(unittest.TestCase):
    def setUp(self):
        self.var1 = os.environ["VAR1"]
        self.var2 = os.environ["VAR2"]

    def test_01(self):
        print("var1: {}, var2: {}".format(self.var1, self.var2))

Затем из командной строки (протестированной в Linux)

$ export VAR1=1
$ export VAR2=2
$ python -m unittest MyTest
var1: 1, var2: 2
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

Ответ 7

Модульные тесты предназначены для тестирования самой базовой функции (функции самого низкого уровня приложения), чтобы убедиться, что ваши строительные блоки приложений работают правильно. Вероятно, нет формального определения того, что именно это означает, но вы должны рассмотреть другие виды тестирования для большей функциональности - см. Интеграционное тестирование. Структурная схема тестирования может быть не идеальной для этой цели.