UFO ET IT

Python unittest 전달 인수

ufoet 2020. 11. 29. 12:41
반응형

Python unittest 전달 인수


파이썬에서 명령 줄에서 unittest 함수로 인수를 전달하는 방법은 무엇입니까? 지금까지의 코드는… 틀렸다는 것을 알고 있습니다.

class TestingClass(unittest.TestCase):

    def testEmails(self):
        assertEqual(email_from_argument, "my_email@example.com")


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

단위 테스트에 대한 위의 주석으로 확장합니다. 단위 테스트는 이메일을 설정하는 경우와 같이 설정 및 분해 요구 사항 이외의 종속성이 없다는 점에서 독립적이어야합니다. 이를 통해 각 테스트에는 테스트에 대한 매우 구체적인 부작용과 반응이 있습니다. 매개 변수를 전달하면 단위 테스트의이 속성이 무효화되므로 어떤 의미에서는 무효화됩니다. 테스트 구성을 사용하는 것이 가장 쉬운 방법이며, 단위 테스트가 테스트를 수행하기 위해 외부 정보에 의존해서는 안되기 때문에 더 적절합니다. 그것은 통합 테스트를위한 것입니다.


그래서 여기 의사들은 "그게 아파요? 그럼 그렇게하지 마세요!"라고 말합니다. 아마 옳다. 그러나 정말로 원한다면 단위 테스트에 인수를 전달하는 한 가지 방법이 있습니다.

import sys
import unittest

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

    def test_logins_or_something(self):
        print 'username', self.USERNAME
        print 'password', 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 자체를 엉망으로 만들지 않도록 s 가 필요합니다 .

[업데이트] 살펴보고 싶은 다른 것은 환경 변수를 사용하는 것입니다.

import os
import unittest

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

    def test_logins_or_something(self):
        print 'username', self.USERNAME
        print 'password', 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에서 그렇게 작동하지 않는다는 것입니다 ...


하지 말아야 할 올바른 발언에도 불구하고 이것을 정말로 원하는 사람들을위한 또 다른 방법 :

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)

당신이 사용하려는 경우 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)

Have a same problem. My solution is after you handle with parsing arguments using argparse or other way, remove arguments from sys.argv

sys.argv = sys.argv[:1]  

If you need you can filter unittest arguments from main.parseArgs()


Even if the test gurus say that we should not do it: I do. In some context it makes a lot of sense to have parameters to drive the test in the right direction, for example:

  • which of the dozen identical USB cards should I use for this test now?
  • which server should I use for this test now?
  • which XXX should I use?

For me, the use of the environment variable is good enough for this puprose because you do not have to write dedicated code to pass your parameters around; it is supported by Python. It is clean and simple.

Of course, I'm not advocating for fully parametrizable tests. But we have to be pragmatic and, as I said, in some context you need a parameter or two. We should not abouse of it :)

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

Then from the command line (tested on Linux)

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

OK

Unit testing is meant for testing the very basic functionality (the lowest level functions of the application) to be sure that your application building blocks work correctly. There is probably no formal definition of what does that exactly mean, but you should consider other kinds of testing for the bigger functionality -- see Integration testing. The unit testing framework may not be ideal for the purpose.

참고URL : https://stackoverflow.com/questions/11380413/python-unittest-passing-arguments

반응형