unittest

基本概念

  • test fixture 测试夹具

    测试预先操作以及测试的后置操作

  • test case 测试用例

    测试用例 unittes 提供一个基础类TestCase

  • test suit 测试套

    测试用例的集合容器,聚集要一起执行的用例

  • test runner 测试运行器

    协调测试执行并向用户提供结果的组件

simlpe example

import unittest

class TestNumber(unittest.TestCase):
    def test_01(self):
        self.assertEqual(1, 1)
    
    def test_02(self):
        self.assertFalse(1==2)

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

# ..
# ----------------------------------------------------------------------
# Ran 2 tests in 0.000s

# OK
  • 测试类继承unittest.Testcase
  • 测试方法名test开头

命令行接口

python -m unittest test_module1 test_module2
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method
python -m unittest tests/test_something.py
(.venv) PS D:\project\howtospider> python -m unittest main.TestNumber.test_01
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

当没有参数时候 测试发现被启动

命令行选项 以及测试发现选项

(.venv) PS D:\project\howtospider> python -m unittest -h
usage: python.exe -m unittest [-h] [-v] [-q] [--locals] [--durations N] [-f] [-c] [-b] [-k TESTNAMEPATTERNS] [tests ...]

positional arguments:
  tests                a list of any number of test modules, classes and test methods.

options:
  -h, --help           show this help message and exit
  -v, --verbose        Verbose output  显示详细信息
  -q, --quiet          Quiet output     显示简略信息
  --locals             Show local variables in tracebacks   在tracebacks中显示变量
  --durations N        Show the N slowest test cases (N=0 for all)  显示最慢的几个测试用例
  -f, --failfast       Stop on first fail or error  遇到第一个失败的用例就停止
  -c, --catch          Catch Ctrl-C and display results so far  按ctrl c 运行完当前用例结束则返回测试结果, 再按ctrl c 就触发KeyboardInterrupt异常
  -b, --buffer         Buffer stdout and stderr during tests 缓存标准输出 错误输出
  -k TESTNAMEPATTERNS  Only run tests which match the given substring 运行符合关键词的用例

Examples:
  python.exe -m unittest test_module               - run tests from test_module
  python.exe -m unittest module.TestClass          - run tests from module.TestClass
  python.exe -m unittest module.Class.test_method  - run specified test method
  python.exe -m unittest path/to/test_file.py      - run tests from test_file.py

usage: python.exe -m unittest discover [-h] [-v] [-q] [--locals] [--durations N] [-f] [-c] [-b] [-k TESTNAMEPATTERNS] [-s START] [-p PATTERN] [-t TOP]

options:
  -h, --help            show this help message and exit
  -v, --verbose         Verbose output
  -q, --quiet           Quiet output
  --locals              Show local variables in tracebacks
  --durations N         Show the N slowest test cases (N=0 for all)
  -f, --failfast        Stop on first fail or error
  -c, --catch           Catch Ctrl-C and display results so far
  -b, --buffer          Buffer stdout and stderr during tests
  -k TESTNAMEPATTERNS   Only run tests which match the given substring
  -s START, --start-directory START
                        Directory to start discovery ('.' default)
  -p PATTERN, --pattern PATTERN
                        Pattern to match tests ('test*.py' default)
  -t TOP, --top-level-directory TOP
                        Top level directory of project (defaults to start directory)

For test discovery all test modules must be importable from the top level directory of the project.
python -m unittest discover -s project_directory -p "*_test.py"
python -m unittest discover project_directory "*_test.py"

组织测试

测试夹具

import unittest

class TestNumber(unittest.TestCase):
    def setUp(self):
        print('setUp-----------')

    def test_01(self):
        print('test_01')
        self.assertEqual(1, 1)
    
    def test_02(self):
        print('test_02')
        self.assertFalse(1==2)

    def tearDown(self):
        print('tearDown---------')

# setUp-----------
# test_01
# tearDown---------
# .setUp-----------
# test_02
# tearDown---------
# .
# ----------------------------------------------------------------------
# Ran 2 tests in 0.001s

# OK

testsuit

from pdb import run
import unittest

class TestCase01(unittest.TestCase):
    def test_01(self):
        print('TestCase01_test_01')

    def test_02(self):
        print('TestCase01_test_02')


class TestCase02(unittest.TestCase):
    def test_01(self):
        print('TestCase02_test_01')

    def test_02(self):
        print('TestCase02_test_02')


def suite():
    suite = unittest.TestSuite()
    suite.addTest(TestCase01('test_01'))
    suite.addTest(TestCase02('test_01'))
    return suite

if __name__ == "__main__":
    runner = unittest.TextTestRunner()
    runner.run(suite())

# TestCase01_test_01
# .TestCase02_test_01
# .
# ----------------------------------------------------------------------
# Ran 2 tests in 0.001s

# OK

function to TestCase

from pdb import run
import unittest

def testsomething():
    assert 1 == 1

def beforetest():
    print('beforetest')

def aftertest():
    print('aftertest')

testcase = unittest.FunctionTestCase(testsomething, setUp=beforetest, tearDown=aftertest)


def suite():
    suite = unittest.TestSuite()
    suite.addTest(testcase)
    return suite

if __name__ == '__main__':
    runner = unittest.TextTestRunner()
    runner.run(suite())

# beforetest
# aftertest
# .
# ----------------------------------------------------------------------
# Ran 1 test in 0.001s

# OK

跳过用例和预期错误

# @unittest.skip("showing class skipping")
class MyTestCase(unittest.TestCase):

    @unittest.skip("demonstrating skipping")
    def test_nothing(self):
        self.fail("shouldn't happen")

    @unittest.skipIf(mylib.__version__ < (1, 3),
                     "not supported in this library version")
    def test_format(self):
        # Tests that work for only a certain version of the library.
        pass

    @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
    def test_windows_support(self):
        # windows specific testing code
        pass

    def test_maybe_skipped(self):
        if not external_resource_available():
            self.skipTest("external resource not available")
        # test code that depends on the external resource
        pass
class ExpectedFailureTestCase(unittest.TestCase):
    @unittest.expectedFailure
    def test_fail(self):
        self.assertEqual(1, 0, "broken")
# 自定义装饰器
def skipUnlessHasattr(obj, attr):
    if hasattr(obj, attr):
        return lambda func: func
    return unittest.skip("{!r} doesn't have {!r}".format(obj, attr))

子测试

class NumbersTest(unittest.TestCase):

    def test_even(self):
        """
        Test that numbers between 0 and 5 are all even.
        """
        for i in range(0, 6):
            with self.subTest(i=i):
                self.assertEqual(i % 2, 0)
                
# FFF
# ======================================================================
# FAIL: test_even (main.NumbersTest.test_even) (i=1)
# Test that numbers between 0 and 5 are all even.
# ----------------------------------------------------------------------
# Traceback (most recent call last):
#   File "D:\project\howtospider\main.py", line 11, in test_even
#     self.assertEqual(i % 2, 0)
# AssertionError: 1 != 0

# ======================================================================
# FAIL: test_even (main.NumbersTest.test_even) (i=3)
# Test that numbers between 0 and 5 are all even.
# ----------------------------------------------------------------------
# Traceback (most recent call last):
#   File "D:\project\howtospider\main.py", line 11, in test_even
#     self.assertEqual(i % 2, 0)
# AssertionError: 1 != 0

# ======================================================================
# FAIL: test_even (main.NumbersTest.test_even) (i=5)
# Test that numbers between 0 and 5 are all even.
# ----------------------------------------------------------------------
# Traceback (most recent call last):
#   File "D:\project\howtospider\main.py", line 11, in test_even
#     self.assertEqual(i % 2, 0)
# AssertionError: 1 != 0

# ----------------------------------------------------------------------
# Ran 1 test in 0.001s

# FAILED (failures=3)
posted @ 2025-02-02 22:36  且任荣枯  阅读(5)  评论(0编辑  收藏  举报