Search code examples
pythonunit-testingsubdirectory

Run all tests from subdirectories in Python


I am at my wits end with trying to get all my unittest to run in Python. I have searched about 30 different posts and the unit test documentation but still cannot figure it out.

First I have two test classes that I can run each individually and all the tests pass:

File: unittest.subfolder1.TestObject1.py

class TestObject1(unittest.TestCase):
  def test_case1(self):
    ...some code...
    ...some assertions...

if __name__ == '__main__':
  unittest.main()

File: unittest.subfolder2.TestObject2.py

class TestObject2(unittest.TestCase):
  def test_case1(self):
    ...some code...
    ...some assertions...

if __name__ == '__main__':
  unittest.main()

Starting in the top level directory above 'unittest' I am trying to us unittest.discover to find and run all my tests:

import unittest

loader = unittest.TestLoader()
suite = loader.discover('unittest')
unittest.TextTestRunner().run(suite)

When I do this I get the error `ModuleNotFoundError: No module named 'subfolder1.TestObject1'

What am I doing wrong?


Solution

  • So I had to do my own workaround but at least I can get them all to run with the above file structure. It requires that I reinstantiate the TestLoader and the TestSuite each time I give it a new file path, so first I need to collect all relevant file paths in the unittest directory.

    import os
    import unittest
    import traceback
    
    
    class UnitTestLauncher(object):
    
      def runTests(self):
        #logging.INFO("Running unit tests...")
    
    
        lsPaths = []
    
        #Find all relevant subdirectories that contain unit tests
        #Exclude 'unittest' directory, but include subdirectories, with code `path != 'unittest'`
        for path,subdirs,files in os.walk('unittest'):
          if "pycache" not in path and path != 'unittest':
            lsPaths.append(path)
    
        #loop through subdirectories and run individually
        for path in lsPaths:
          loader = unittest.TestLoader()
          suite = unittest.TestSuite()
          suite = loader.discover(path)
          unittest.TextTestRunner().run(suite)
    

    This solution is not perfect and each different directory comes out as a line of output so you have to look through each line manually for failed tests.