Running single test from unittest.TestCase via command line

前端 未结 7 1602
甜味超标
甜味超标 2020-11-28 01:14

In our team, we define most test cases like this:

One \"framework\" class ourtcfw.py:

import unittest

class OurTcFw(unittest.TestCase):         


        
相关标签:
7条回答
  • 2020-11-28 01:37

    Inspired by @yarkee I combined it with some of the code I already got. You can also call this from another script, just by calling the function run_unit_tests() without requiring to use the command line, or just call it from the command line with python3 my_test_file.py.

    import my_test_file
    my_test_file.run_unit_tests()
    

    Sadly this only works for Python 3.3 or superior:

    import unittest
    
    class LineBalancingUnitTests(unittest.TestCase):
    
        @classmethod
        def setUp(self):
            self.maxDiff = None
    
        def test_it_is_sunny(self):
            self.assertTrue("a" == "a")
    
        def test_it_is_hot(self):
            self.assertTrue("a" != "b")
    

    Runner code:

    #! /usr/bin/env python3
    # -*- coding: utf-8 -*-
    import unittest
    from .somewhere import LineBalancingUnitTests
    
    def create_suite(classes, unit_tests_to_run):
        suite = unittest.TestSuite()
        unit_tests_to_run_count = len( unit_tests_to_run )
    
        for _class in classes:
            _object = _class()
            for function_name in dir( _object ):
                if function_name.lower().startswith( "test" ):
                    if unit_tests_to_run_count > 0 \
                            and function_name not in unit_tests_to_run:
                        continue
                    suite.addTest( _class( function_name ) )
        return suite
    
    def run_unit_tests():
        runner = unittest.TextTestRunner()
        classes =  [
            LineBalancingUnitTests,
        ]
    
        # Comment all the tests names on this list, to run all Unit Tests
        unit_tests_to_run =  [
            "test_it_is_sunny",
            # "test_it_is_hot",
        ]
        runner.run( create_suite( classes, unit_tests_to_run ) )
    
    if __name__ == "__main__":
        print( "\n\n" )
        run_unit_tests()
    

    Editing the code a little, you can pass an array with all unit tests you would like to call:

    ...
    def run_unit_tests(unit_tests_to_run):
        runner = unittest.TextTestRunner()
    
        classes = \
        [
            LineBalancingUnitTests,
        ]
    
        runner.run( suite( classes, unit_tests_to_run ) )
    ...
    

    And another file:

    import my_test_file
    
    # Comment all the tests names on this list, to run all Unit Tests
    unit_tests_to_run = \
    [
        "test_it_is_sunny",
        # "test_it_is_hot",
    ]
    
    my_test_file.run_unit_tests( unit_tests_to_run )
    

    Alternatively, you can use https://docs.python.org/3/library/unittest.html#load-tests-protocol and define the following method on your test module/file:

    def load_tests(loader, standard_tests, pattern):
        suite = unittest.TestSuite()
    
        # To add a single test from this file
        suite.addTest( LineBalancingUnitTests( 'test_it_is_sunny' ) )
    
        # To add a single test class from this file
        suite.addTests( unittest.TestLoader().loadTestsFromTestCase( LineBalancingUnitTests ) )
    
        return suite
    

    If you want to limit the execution to one single test file, you just need to set the test discovery pattern to the only file where you defined the load_tests() function.

    #! /usr/bin/env python3
    # -*- coding: utf-8 -*-
    import os
    import sys
    import unittest
    
    test_pattern = 'mytest/module/name.py'
    PACKAGE_ROOT_DIRECTORY = os.path.dirname( os.path.realpath( __file__ ) )
    
    loader = unittest.TestLoader()
    start_dir = os.path.join( PACKAGE_ROOT_DIRECTORY, 'testing' )
    
    suite = loader.discover( start_dir, test_pattern )
    runner = unittest.TextTestRunner( verbosity=2 )
    results = runner.run( suite )
    
    print( "results: %s" % results )
    print( "results.wasSuccessful: %s" % results.wasSuccessful() )
    
    sys.exit( not results.wasSuccessful() )
    

    References:

    1. Problem with sys.argv[1] when unittest module is in a script
    2. Is there a way to loop through and execute all of the functions in a Python class?
    3. looping over all member variables of a class in python

    Alternatively to the last main program example, I came up with the following variation after reading the unittest.main() method implementation:

    1. https://github.com/python/cpython/blob/master/Lib/unittest/main.py#L65
    #! /usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import os
    import sys
    import unittest
    
    PACKAGE_ROOT_DIRECTORY = os.path.dirname( os.path.realpath( __file__ ) )
    start_dir = os.path.join( PACKAGE_ROOT_DIRECTORY, 'testing' )
    
    from testing_package import main_unit_tests_module
    testNames = ["TestCaseClassName.test_nameHelloWorld"]
    
    loader = unittest.TestLoader()
    suite = loader.loadTestsFromNames( testNames, main_unit_tests_module )
    
    runner = unittest.TextTestRunner(verbosity=2)
    results = runner.run( suite )
    
    print( "results: %s" % results )
    print( "results.wasSuccessful: %s" % results.wasSuccessful() )
    sys.exit( not results.wasSuccessful() )
    
    0 讨论(0)
  • 2020-11-28 01:41

    If you organize your test cases, that is, follow the same organization like the actual code and also use relative imports for modules in the same package

    You can also use the following command format:

    python -m unittest mypkg.tests.test_module.TestClass.test_method
    # In your case, this would be:
    python -m unittest testMyCase.MyCase.testItIsHot
    

    Python3 documentation for this: https://docs.python.org/3/library/unittest.html#command-line-interface

    0 讨论(0)
  • 2020-11-28 01:50

    This works as you suggest - you just have to specify the class name as well:

    python testMyCase.py MyCase.testItIsHot
    
    0 讨论(0)
  • 2020-11-28 01:50

    Maybe, it will be helpful for somebody. In case you want to run only tests from specific class:

    if __name__ == "__main__":
        unittest.main(MyCase())
    

    It works for me in python 3.6

    0 讨论(0)
  • 2020-11-28 01:51

    If you check out the help of the unittest module it tells you about several combinations that allow you to run test case classes from a module and test methods from a test case class.

    python3 -m unittest -h
    
    [...]
    
    Examples:
      python3 -m unittest test_module               - run tests from test_module
      python3 -m unittest module.TestClass          - run tests from module.TestClass
      python3 -m unittest module.Class.test_method  - run specified test method
    

    It does not require you to define a unittest.main() as the default behaviour of your module.

    0 讨论(0)
  • 2020-11-28 01:53

    It can work well as you guess

    python testMyCase.py MyCase.testItIsHot
    

    And there is another way to just test testItIsHot:

        suite = unittest.TestSuite()
        suite.addTest(MyCase("testItIsHot"))
        runner = unittest.TextTestRunner()
        runner.run(suite)
    
    0 讨论(0)
提交回复
热议问题