1

Let's say I have a Python script file that uses sys.argv variables. And I want to test the sys.argv with different values in multiple tests. The issue is that I have to patch and import it multiple times but i think it holds the sys.args values only from the first import so both TestCases print the same values ['test1', 'Test1']. Is my approach wrong?

example.py

import sys
ex1 = sys.argv[0]
ex2 = sys.argv[1]

print(ex1)
print(ex2)

test_example.py

import unittest
import mock
import sys

class TestExample(unittest.TestCase):
    @mock.patch.object(sys, 'argv', ['test1', 'Test1'])
    def test_example1(self):
        import example

    @mock.patch.object(sys, 'argv', ['test2', 'Test2'])
    def test_example2(self):
        import example
joanis
  • 10,635
  • 14
  • 30
  • 40
pikk
  • 837
  • 5
  • 21
  • 38
  • 1
    I think the problem is that Python sees that you've already imported that file and won't import it again the second time. But question: do the print statements in `example.py` get executed just once, or actually twice? – joanis Aug 31 '22 at 12:54
  • Answering my own question: I ran your code with `python -m unittest` and I only see `test1\nTest1` printed, but not `test2\nTest2`, so indeed, your second import doesn't do anything. – joanis Aug 31 '22 at 12:59

1 Answers1

1

The problem is that Python will not (unless you work hard at it) reimport the same file more than once.

What you should do is have the import only define stuff, and define a main() function in your module that gets called when it's time to run stuff. You call this main() function directly in the script when the script is called by itself (see the last two lines of example.py below), but then you can also call that function by name during unit testing.

For what it's worth, this is best practice in Python: your scripts and module should mostly define functions, classes and whatnot on import, but not run much. Then you call your main() function in a __name__ guard. See What does if __name__ == "__main__": do? for more details about that.

Here's your code modified to work, testing your module with two different sets of sys.argv values:

example.py:

import sys

def main():
    ex1 = sys.argv[0]
    ex2 = sys.argv[1]

    print(ex1)
    print(ex2)

if __name__ == "__main__":
    main()

test-example.py:

import unittest
import mock
import sys

import example

class TestExample(unittest.TestCase):
    @mock.patch.object(sys, 'argv', ['test1', 'Test1'])
    def test_example1(self):
        example.main()

    @mock.patch.object(sys, 'argv', ['test2', 'Test2'])
    def test_example2(self):
        example.main()

Results from python -m unittest:

..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK
test1
Test1
test2
Test2
joanis
  • 10,635
  • 14
  • 30
  • 40