通过命令行从unittest.TestCase运行单个测试

时间:2013-04-12 12:43:14

标签: python unit-testing

在我们的团队中,我们定义了大多数测试用例:

一个“框架”类ourtcfw.py:

import unittest

class OurTcFw(unittest.TestCase):
    def setUp:
        # something

    # other stuff that we want to use everywhere

和很多测试用例如testMyCase.py:

import localweather

class MyCase(OurTcFw):

    def testItIsSunny(self):
        self.assertTrue(localweather.sunny)

    def testItIsHot(self):
        self.assertTrue(localweather.temperature > 20)

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

当我编写新的测试代码并希望经常运行它并节省时间时,我所做的就是将“__”放在所有其他测试之前。但它很麻烦,让我分心,因为我写的代码和创建的提交噪音很烦人。

所以,例如在对testItIsHot()进行更改时,我希望能够执行此操作:

$ python testMyCase.py testItIsHot

unittest仅运行 <{em> testItIsHot()

我怎样才能做到这一点?

我试图重写if __name__ == "__main__":部分,但由于我是Python的新手,我感到很迷茫并且不断抨击除了方法之外的其他所有内容。

9 个答案:

答案 0 :(得分:236)

这可以按照您的建议运行 - 您只需要指定类名:

python testMyCase.py MyCase.testItIsHot

答案 1 :(得分:117)

如果您组织测试用例,即遵循与实际代码相同的组织,并使用相同包中的模块的相对导入

您还可以使用以下命令格式:

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

答案 2 :(得分:54)

它可以正常运作

python testMyCase.py MyCase.testItIsHot

还有另一种方法可以测试testItIsHot

    suite = unittest.TestSuite()
    suite.addTest(MyCase("testItIsHot"))
    runner = unittest.TextTestRunner()
    runner.run(suite)

答案 3 :(得分:18)

如果您查看unittest模块的帮助,它会告诉您几个允许您从模块运行测试用例类和从测试用例类测试方法的组合。

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

它不要求您将unittest.main()定义为模块的默认行为。

答案 4 :(得分:4)

也许对某人会有帮助。如果您只想运行特定类别的测试:

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

它在python 3.6中对我有效

答案 5 :(得分:1)

灵感来自@yarkee我将它与我已经获得的一些代码相结合。您也可以从另一个脚本调用此方法,只需调用函数run_unit_tests()而无需使用命令行,或者只需使用python3 my_test_file.py从命令行调用它。

import my_test_file
my_test_file.run_unit_tests()

可悲的是,这仅适用于Python 3.3或更高级:

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")

赛跑者代码:

#! /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()

稍微编辑代码,您可以传递一个包含您想要调用的所有单元测试的数组:

...
def run_unit_tests(unit_tests_to_run):
    runner = unittest.TextTestRunner()

    classes = \
    [
        LineBalancingUnitTests,
    ]

    runner.run( suite( classes, unit_tests_to_run ) )
...

另一个文件:

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 )

或者,您可以使用https://docs.python.org/3/library/unittest.html#load-tests-protocol并在测试模块/文件上定义以下方法:

def load_tests(loader, standard_tests, pattern):
    suite = unittest.TestSuite()
    suite.addTest( LineBalancingUnitTests( 'test_it_is_sunny' ) )
    return suite

如果要将执行限制为单个测试,则只需将测试发现模式设置为您定义load_tests()函数的唯一文件。

#! /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() )

参考文献:

  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
  4. 除了上一个主程序示例之外,我在阅读unittest.main()方法实现后想出了以下变体:

    1. https://github.com/python/cpython/blob/master/Lib/unittest/main.py#L65
    2. #! /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 )
      
      runner = unittest.TextTestRunner(verbosity=2)
      results = runner.run( suite )
      
      print( "results: %s" % results )
      print( "results.wasSuccessful: %s" % results.wasSuccessful() )
      sys.exit( not results.wasSuccessful() )
      

答案 6 :(得分:0)

TL; DR :这很有可能会起作用:

python mypkg/tests/test_module.py MyCase.testItIsHot

说明

  • 便捷方式

    python mypkg/tests/test_module.py MyCase.testItIsHot
    

    可以正常工作,但前提是您已经在测试文件中(通常在末尾)包含了此常规代码段。

    if __name__ == "__main__":
        unittest.main()
    
  • 不便的方式

    python -m unittest mypkg.tests.test_module.TestClass.test_method
    

    始终可以正常工作,而无需在测试源文件中包含if __name__ == "__main__": unittest.main()代码段。

那么为什么第二种方法不方便?因为(_ 在此处插入您的身体部位之一 _)会导致您很难手动键入以点分隔的长路径。在第一种方法中,mypkg/tests/test_module.py部分可以由现代外壳程序或由您的编辑器自动完成。

PS:如果您认为身体部位在腰部以下,则您是真实的人。 :-)我的意思是说“手指关节”。打字过多对您的关节不利。 ;-)

答案 7 :(得分:0)

如果您想直接从脚本(例如,从 jupyter notebook)运行测试,您可以这样做以仅运行一个测试:

from testMyCase import MyCase
unittest.main(argv=['ignored', '-v', 'MyCase.testItIsHot'], exit=False)

答案 8 :(得分:-7)

这是另一种方式

self.text_description = UITextView(frame: CGRect(x: 100.0, y: 100.0, width: 200.0, height: 28.0))
self.text_description.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
self.view.addSubview(self.text_description)