1. 测试套件 (Test Suites)
测试套件允许你组合多个测试用例,并且能够以不同的方式组织和运行这些测试。这是对测试进行分组和控制测试执行顺序的有效手段。
import unittest
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
def test_isupper(self):
self.assertTrue('FOO'.isupper())
self.assertFalse('Foo'.isupper())
if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTest(TestStringMethods('test_upper'))
suite.addTest(TestStringMethods('test_isupper'))
runner = unittest.TextTestRunner()
runner.run(suite)
2. 装饰器 (Decorators)
unittest 提供了几个装饰器来控制测试行为,比如 skip 和 expectedFailure。、
import unittest
class TestDecorators(unittest.TestCase):
@unittest.skip("demonstrating skipping")
def test_nothing(self):
self.fail("shouldn't happen")
@unittest.expectedFailure
def test_fail(self):
self.assertEqual(1, 0, "broken")
if __name__ == '__main__':
unittest.main()
3. 参数化测试 (Parameterized Tests)
通过 parameterized 库,你可以为同一个测试方法提供不同的输入数据,从而避免重复编写相似的测试代码。
安装 parameterized 库
pip install parameterized
import unittest
from parameterized import parameterized
class TestMath(unittest.TestCase):
@parameterized.expand([
(2, 3, 5),
(7, 6, 13),
(-1, 1, 0)
])
def test_add(self, a, b, expected):
self.assertEqual(a + b, expected)
if __name__ == '__main__':
unittest.main()
4. 嵌套测试 (Nested Tests)
虽然 unittest 不直接支持嵌套测试,但可以通过子类化来实现类似的功能。
import unittest
class TestNested(unittest.TestCase):
class TestSub(unittest.TestCase):
def test_subtest(self):
self.assertEqual(1 + 1, 2)
def test_nested(self):
suite = unittest.TestLoader().loadTestsFromTestCase(self.TestSub)
result = unittest.TextTestRunner(verbosity=2).run(suite)
self.assertTrue(result.wasSuccessful())
if __name__ == '__main__':
unittest.main()
5. 动态生成测试 (Dynamic Test Generation)
你可以动态创建测试用例,这在某些情况下非常有用,比如当测试依赖于外部数据源时。
import unittest
def load_tests(loader, tests, pattern):
suite = unittest.TestSuite()
for i in range(1, 4):
suite.addTest(MyTest('test_method', i))
return suite
class MyTest(unittest.TestCase):
def __init__(self, methodName, data):
super().__init__(methodName)
self.data = data
def test_method(self):
self.assertEqual(self.data % 2, 0)
if __name__ == '__main__':
unittest.main()
6. 测试加载器 (Test Loaders)
unittest 提供了多种测试加载器,用于自动发现和加载测试用例。
import unittest
class TestLoaders(unittest.TestCase):
def test_one(self):
self.assertEqual(1 + 1, 2)
if __name__ == '__main__':
loader = unittest.TestLoader()
suite = loader.loadTestsFromTestCase(TestLoaders)
unittest.TextTestRunner().run(suite)
7. 捕获异常 (AssertRaises)
unittest 提供了 assertRaises 方法来检查一个函数是否抛出了预期的异常。、
import unittest
class TestExceptions(unittest.TestCase):
def test_divide_by_zero(self):
with self.assertRaises(ZeroDivisionError):
1 / 0
if __name__ == '__main__':
unittest.main()
8. 子测试 (Subtests)
子测试允许你在一个测试方法中执行多个断言,并确保即使其中一个失败也不会中断其他断言的执行。、
import unittest
class TestSubtests(unittest.TestCase):
def test_subtest(self):
for value in [2, 4, 6]:
with self.subTest(i=value):
self.assertEqual(value % 2, 0)
if __name__ == '__main__':
unittest.main()
9. 设置和清理 (Setup and Teardown)
unittest 提供了 setUp 和 tearDown 方法,用于在每个测试方法前后执行初始化和清理工作。此外,还可以使用 setUpClass 和 tearDownClass 方法来处理整个测试类的初始化和清理工作。
import unittest
import tempfile
class TestFileOperations(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.temp_dir = tempfile.TemporaryDirectory()
@classmethod
def tearDownClass(cls):
cls.temp_dir.cleanup()
def setUp(self):
self.filename = self.temp_dir.name + '/testfile.txt'
with open(self.filename, 'w') as f:
f.write('Hello, World!')
def tearDown(self):
try:
os.remove(self.filename)
except OSError:
pass
def test_file_content(self):
with open(self.filename, 'r') as f:
content = f.read()
self.assertEqual(content, 'Hello, World!')
if __name__ == '__main__':
unittest.main()
10. 断言方法 (Assertion Methods)
unittest 提供了一系列断言方法,它们比普通的 assert 更强大并且提供了更好的错误消息。例如,assertEqual, assertTrue, assertFalse, assertIn, assertNotIn, assertRaises, 等等。
import unittest
class TestAsserts(unittest.TestCase):
def test_assert_equal(self):
self.assertEqual(1 + 1, 2)
def test_assert_true(self):
self.assertTrue(1 == 1)
def test_assert_false(self):
self.assertFalse(1 == 2)
def test_assert_in(self):
self.assertIn('a', 'abc')
def test_assert_not_in(self):
self.assertNotIn('z', 'abc')
if __name__ == '__main__':
unittest.main()
11. 忽略测试 (Skipping Tests)
有时你需要有条件地跳过某个测试。unittest 提供了 skipIf 和 skipUnless 装饰器,使得可以根据条件跳过测试。
import unittest
import sys
class TestSkipConditions(unittest.TestCase):
@unittest.skipIf(sys.version_info < (3, 8), "requires Python 3.8 or higher")
def test_python_version(self):
self.assertGreaterEqual(sys.version_info, (3, 8))
if __name__ == '__main__':
unittest.main()
12. 捕获输出 (Capturing Output)
有时候你需要捕获测试过程中的标准输出(stdout)或标准错误(stderr)。unittest 的 capture_output 上下文管理器可以帮助完成这项任务。
import unittest
from io import StringIO
class TestOutputCapture(unittest.TestCase):
def test_captured_output(self):
with self.assertLogs() as cm:
print("This is a test message.")
self.assertIn("This is a test message.", cm.output[0])
if __name__ == '__main__':
unittest.main()
13. 异步测试 (Async Tests)
对于异步代码,可以使用 unittest.IsolatedAsyncioTestCase 来编写异步测试。
import asyncio
import unittest
class TestAsyncMethods(unittest.IsolatedAsyncioTestCase):
async def test_async_method(self):
result = await self.async_method()
self.assertEqual(result, 'expected_result')
async def async_method(self):
await asyncio.sleep(0.1)
return 'expected_result'
if __name__ == '__main__':
unittest.main()
14. 自定义断言 (Custom Assertions)
你可以扩展 unittest.TestCase 类来自定义新的断言方法。
import unittest
class CustomAsserts(unittest.TestCase):
def assertIsNone(self, obj, msg=None):
if obj is not None:
standardMsg = '%s is not None' % str(obj)
self.fail(self._formatMessage(msg, standardMsg))
def test_custom_assertion(self):
self.assertIsNone(None)
if __name__ == '__main__':
unittest.main()
最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走!
软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。