334

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

一个“框架”类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 testItIsHot()

我怎样才能做到这一点?

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

4

9 回答 9

402

这可以按照您的建议工作-您还必须指定类名:

python testMyCase.py MyCase.testItIsHot
于 2013-04-12T12:44:32.007 回答
186

如果你组织你的测试用例,即像实际代码一样遵循相同的组织,并且对同一个包中的模块也使用相对导入,你还可以使用以下命令格式:

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

# In your case, this would be:
python -m unittest testMyCase.MyCase.testItIsHot

Python 3 文档:命令行界面

于 2014-10-23T15:34:14.660 回答
86

如你所料,它可以很好地工作

python testMyCase.py MyCase.testItIsHot

还有另一种方法来测试testItIsHot

    suite = unittest.TestSuite()
    suite.addTest(MyCase("testItIsHot"))
    runner = unittest.TextTestRunner()
    runner.run(suite)
于 2013-04-12T12:53:32.630 回答
30

如果您查看 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
```lang-none

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

于 2017-03-26T13:54:18.797 回答
17

如果您只想运行特定类的测试:

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

它适用于我在 Python 3.6 中。

于 2018-09-13T11:48:07.313 回答
16

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部分可以通过现代外壳或您的编辑器自动完成。

于 2019-11-14T19:12:50.110 回答
3

受到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 )

或者,您可以使用load_tests 协议并在您的测试模块/文件中定义以下方法:

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

如果您想将执行限制为一个测试文件,您只需将测试发现模式设置为您定义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. 当 unittest 模块在脚本中时 sys.argv[1] 出现问题
  2. 有没有办法循环并执行 Python 类中的所有函数?
  3. 在python中循环一个类的​​所有成员变量

unittest.main()或者,对于最后一个主程序示例,我在阅读方法实现后想出了以下变体:

  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() )
于 2017-11-09T16:32:58.457 回答
3

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

from testMyCase import MyCase
unittest.main(argv=['ignored', '-v', 'MyCase.testItIsHot'], exit=False)
于 2021-08-04T14:39:04.660 回答
0

对我有用的是:

cd project_dir
python -m unittest -v path\to\test\testMyCase.py -k my_test_name

-v 用于 unittest 详细日志输出。

于 2022-01-18T15:22:30.097 回答