Python, unit test – Pass command line arguments to setUp of unittest.TestCase

Question:

I have a script that acts as a wrapper for some unit tests written using the Python unittest module. In addition to cleaning up some files, creating an output stream and generating some code, it loads test cases into a suite using

unittest.TestLoader().loadTestsFromTestCase()

I am already using optparse to pull out several command-line arguments used for determining the output location, whether to regenerate code and whether to do some clean up. I also want to pass a configuration variable, namely an endpoint URI, for use within the test cases.

I realize I can add an OptionParser to the setUp method of the TestCase, but I want to instead pass the option to setUp. Is this possible using loadTestsFromTestCase()? I can iterate over the returned TestSuite‘s TestCases, but can I manually call setUp on the TestCases?

** EDIT **
I wanted to point out that I am able to pass the arguments to setUp if I iterate over the tests and call setUp manually like:

(options, args) = op.parse_args()
suite = unittest.TestLoader().loadTestsFromTestCase(MyTests.TestSOAPFunctions)
for test in suite:
    test.setUp(options.soap_uri)

However, I am using xmlrunner for this and its run method takes a TestSuite as an argument. I assume it will run the setUp method itself, so I would need the parameters available within the XMLTestRunner.

Asked By: sberry

||

Answers:

I would definitely advise against passing arguments to setUp like this; setUp is intended to be called implicitly when running a test, so you shouldn’t be explicitly calling it like this.

One way you could tackle this would be to set the values you need to set either as environment variables or values in a globally accessible “context” module, which would allow test cases to access them as needed. I would go for using environment variables, as it is more flexible in terms of running the tests (you’re then no longer relying on command line arguments).

Answered By: Gabriel Reid

Well, I want to do the same thing and was going to ask this question myself. I wanted to improve over the following code because it has duplication. It does let me send in arguments to test TestCase however:

import unittest
import helpspot

class TestHelpSpot(unittest.TestCase):
    "A few simple tests for HelpSpot"

    def __init__(self, testname, path, user, pword):
        super(TestHelpSpot, self).__init__(testname)
        self.hs = helpspot.HelpSpot(path, user, pword)

    def test_version(self):
        a = self.hs.version()
        b = self.hs.private_version()
        self.assertEqual(a, b)

    def test_get_with_param(self):
        a = self.hs.filter_get(xFilter=1)

    def test_unknown_method(self):
        self.assertRaises(helpspot.HelpSpotError, self.hs.private_wuggienorple)

if __name__ == '__main__':
    import sys
    user = sys.argv[1]
    pword = sys.argv[2]
    path = sys.argv[3]

    test_loader = unittest.TestLoader()
    test_names = test_loader.getTestCaseNames(TestHelpSpot)

    suite = unittest.TestSuite()
    for test_name in test_names:
        suite.addTest(TestHelpSpot(test_name, path, user, pword))

    result = unittest.TextTestRunner().run(suite)
    sys.exit(not result.wasSuccessful())
Answered By: jps

If you define the attributes in the init method, then you can simply pass them all in the constructor like this..

import unittest
import helpspot

class TestHelpSpot(unittest.TestCase):
    "A few simple tests for HelpSpot"

    def __init__(self, testname, path, user, pword):
        super(TestHelpSpot, self).__init__(testname)
        self.path = path
        self.user = user
        self.pword = pword
....
....
....


if __name__ == '__main__':
    True

    suite = unittest.TestSuite()
    suite.addTest(TestHelpSpot("test_version", path, user, pword))    

    unittest.TextTestRunner().run(suite)
Answered By: user1048839
if __name__ == '__main__':
    from optparse import OptionParser
    parser = OptionParser()
    parser.add_option("-z", "--zebra",
                      action="store_true", dest="zebra", default=False,
                      help="run like a zebra")    


    (options, args) = parser.parse_args()

    if options.zebra:
        zebrafy()


    # remove our args because we don't want to send them to unittest
    for x in sum([h._long_opts+h._short_opts for h in parser.option_list],[]):
        if x in sys.argv:
            sys.argv.remove(x)


    unittest.main()
Answered By: Ken Seehart
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.