How should I deal with multiple imports having the same name?
How should I deal with multiple imports having the same name?

How should I deal with multiple imports having the same name

I have a repository that contains multiple programs:
. └── Programs ├── program1 │ └── Generic_named.py └── program2 └── Generic_named.py
I would like to add testing to this repository.
I have attempted to do it like this:
. ├── Programs │ ├── program1 │ │ └── Generic_named.py │ └── program2 │ └── Generic_named.py └── Tests ├── mock │ ├── 1 │ │ └── custom_module.py │ └── 2 │ └── custom_module.py ├── temp ├── test1.py └── test2.py
Where temp
is a folder to store each program temporarily with mock versions of any required imports that can not be stored directly with the program.
Suppose we use a hello world example like this:
cat Programs/program1/Generic_named.py import custom_module def main(): return custom_module.out() cat Programs/program2/Generic_named.py import custom_module def main(): return custom_module.out("Goodbye, World!") cat Tests/mock/1/custom_module.py def out():return "Hello, World!" cat Tests/mock/2/custom_module.py def out(x):return x
And I were to use these scripts to test it:
cat Tests/test1.py import unittest import os import sys import shutil if os.path.exists('Tests/temp/1'): shutil.rmtree('Tests/temp/1') shutil.copytree('Tests/mock/1', 'Tests/temp/1/') shutil.copyfile('Programs/program1/Generic_named.py', 'Tests/temp/1/Generic_named.py') sys.path.append('Tests/temp/1') import Generic_named sys.path.remove('Tests/temp/1') class Test(unittest.TestCase): def test_case1(self): self.assertEqual(Generic_named.main(), "Hello, World!") if __name__ == '__main__': unittest.main() cat Tests/test2.py import unittest import os import sys import shutil if os.path.exists('Tests/temp/2'): shutil.rmtree('Tests/temp/2') shutil.copytree('Tests/mock/2', 'Tests/temp/2') shutil.copyfile('Programs/program2/Generic_named.py', 'Tests/temp/2/Generic_named.py') sys.path.append('Tests/temp/2') import Generic_named sys.path.remove('Tests/temp/2') class Test(unittest.TestCase): def test_case1(self): self.assertEqual(Generic_named.main(), "Goodbye, World!") if __name__ == '__main__': unittest.main()
Both tests pass when run individually:
python3 -m unittest Tests/test1.py . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK python3 -m unittest Tests/test2.py . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
However, they fail when being run together:
python3 -m unittest discover -p test*.py -s Tests/ .F ====================================================================== FAIL: test_case1 (test2.Test) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/s/Documents/Coding practice/2024/Test Mess/1/Tests/test2.py", line 18, in test_case1 self.assertEqual(Generic_named.main(), "Goodbye, World!") AssertionError: 'Hello, World!' != 'Goodbye, World!' - Hello, World! + Goodbye, World! ---------------------------------------------------------------------- Ran 2 tests in 0.001s FAILED (failures=1)
If I try to use a different temporary name for one of the scripts I am trying to test,
cat Tests/test2.py import unittest import os import sys import shutil if os.path.exists('Tests/temp/2'): shutil.rmtree('Tests/temp/2') shutil.copytree('Tests/mock/2', 'Tests/temp/2') shutil.copyfile('Programs/program2/Generic_named.py', 'Tests/temp/2/Generic_named1.py') sys.path.append('Tests/temp/2') import Generic_named1 sys.path.remove('Tests/temp/2') class Test(unittest.TestCase): def test_case1(self): self.assertEqual(Generic_named1.main(), "Goodbye, World!") if __name__ == '__main__': unittest.main()
Then I get a different error:
python3 -m unittest discover -p test*.py -s Tests/ .E ====================================================================== ERROR: test_case1 (test2.Test) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/s/Documents/Coding practice/2024/Test Mess/2/Tests/test2.py", line 18, in test_case1 self.assertEqual(Generic_named1.main(), "Goodbye, World!") File "/home/s/Documents/Coding practice/2024/Test Mess/2/Tests/temp/2/Generic_named1.py", line 4, in main return custom_module.out("Goodbye, World!") TypeError: out() takes 0 positional arguments but 1 was given ---------------------------------------------------------------------- Ran 2 tests in 0.001s FAILED (errors=1)
It seems to be trying to import the same file, despite me using a different file from a different path with the same name. This seems strange, as I've been making sure to undo any changes to the Python Path after importing what I wish to test. Is there any way to mock the path? I can't change the name of the custom_module
, as that would require changing the programs I wish to test.
How should I write, approach, or setup these tests such that they can be tested with unittest discover the same as they can individually?