运行来自unittest的单个测试。TestCase通过命令行

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

一个“framework"类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新手,我感到迷失,并继续抨击除方法之外的所有内容。

233019 次浏览

这就像你建议的那样-你只需要指定类名:

python testMyCase.py MyCase.testItIsHot

它可以像你猜的那样很好

python testMyCase.py MyCase.testItIsHot

还有另一种方法来测试testItIsHot:

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

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

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


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

Python 3文档:命令行接口 . sh

如果你查看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.


受到由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 Protocol并在你的测试模块/文件中定义以下方法:

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模块在脚本时,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() )

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

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

它在Python 3.6中为我工作。

博士TL;:这将很可能工作:

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部分可以通过现代shell或您的编辑器自动补全。

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

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

对我有用的是:

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

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