笔记-python-standard library-26.4 unittest
source code:Lib/unittest/__init__.py
它是python自带的单元测试框架,封装好了一些校验返回的结果方法和一些用例执行前的初始化操作。
在开始之前,有几个概念:
它表示一个或多个测试用例,还有相关的清理动作;
单元测试的最小单元是测试用例,典型的test case如下:
import unittest
class DefaultWidgetSizeTestCase(unittest.TestCase):
def test_default_widget_size(self):
widget = Widget(‘The widget‘)
self.assertEqual(widget.size(), (50, 50))
测试用例应该是完全独立的。
测试用例可以有多个,使用setUp()来安装;
运行各种测试的顺序是通过根据字符串的内置顺序对测试方法名称进行排序来确定的。
import unittest
class WidgetTestCase(unittest.TestCase):
def setUp(self):
self.widget = Widget(‘The widget‘)
def tearDown(self):
self.widget.dispose()
tearDown()则是用于测试后环境清理。如果setUp() succeeded,tearDown() will be run whether the test method succeeded or not.
上面的代码段被称为fixture。
测试用例会很多,unittest为此提供的更高级别的抽象实现;suite
def suite():
suite = unittest.TestSuite()
suite.addTest(WidgetTestCase(‘test_default_widget_size‘))
suite.addTest(WidgetTestCase(‘test_widget_resize‘))
return suite
if __name__ == ‘__main__‘:
runner = unittest.TextTestRunner()
runner.run(suite())
这样最重要的益处是可以将用例和测试代码分开。
Unittest支持跳过测试用例和预期失败处理。
跳过测试用例使用skip() decorator,或者其变型。
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
输出如下:
test_format (__main__.MyTestCase) ... skipped ‘not supported in this library version‘
test_nothing (__main__.MyTestCase) ... skipped ‘demonstrating skipping‘
test_windows_support (__main__.MyTestCase) ... skipped ‘requires Windows‘
----------------------------------------------------------------------
Ran 3 tests in 0.005s
OK (skipped=3)
Classes can be skipped just like methods:
@unittest.skip("showing class skipping")
class MySkippedTestCase(unittest.TestCase):
def test_not_run(self):
pass
Expected failures use the expectedFailure() decorator.
class ExpectedFailureTestCase(unittest.TestCase):
@unittest.expectedFailure
def test_fail(self):
self.assertEqual(1, 0, "broken")
@unittest.skip(reason)
Unconditionally skip the decorated test. reason should describe why the test is being skipped.
@unittest.skipIf(condition, reason)
Skip the decorated test if condition is true.
@unittest.skipUnless(condition, reason)
Skip the decorated test unless condition is true.
@unittest.expectedFailure
Mark the test as an expected failure. If the test fails when run, the test is not counted as a failure.
exception unittest.SkipTest(reason)
This exception is raised to skip a test.
This section describes in depth the API of unittest.
class unittest.TestCase(methodName=‘runTest‘)
常用的也就setUp(),tearDown()了。
TestCase提供了一些assert方法
Method |
Checks that |
New in |
assertEqual(a, b) |
a == b |
|
assertNotEqual(a, b) |
a != b |
|
assertTrue(x) |
bool(x) is True |
|
assertFalse(x) |
bool(x) is False |
|
assertIs(a, b) |
a is b |
3.1 |
assertIsNot(a, b) |
a is not b |
3.1 |
assertIsNone(x) |
x is None |
3.1 |
assertIsNotNone(x) |
x is not None |
3.1 |
assertIn(a, b) |
a in b |
3.1 |
assertNotIn(a, b) |
a not in b |
3.1 |
assertIsInstance(a, b) |
isinstance(a, b) |
3.2 |
assertNotIsInstance(a, b) |
not isinstance(a, b) |
3.2 |
下面还有很多方法,使用的时候可以查,这里不多写。
class unittest.TestSuite(tests=())
Add a TestCase or TestSuite to the suite.
Add all the tests from an iterable of TestCase and TestSuite instances to this test suite.
This is equivalent to iterating over tests, calling addTest() for each element.
Return the number of tests represented by this test object, including all individual tests and sub-suites.
class unittest.TestLoader
The TestLoader class is used to create test suites from classes and modules. Normally, there is no need to create an instance of this class; the unittest module provides an instance that can be shared as unittest.defaultTestLoader. Using a subclass or instance, however, allows customization of some configurable properties.
class unittest.TestResult
This class is used to compile information about which tests have succeeded and which have failed.
有一个需要注意的
unittest.main(module=‘__main__‘, defaultTest=None, argv=None, testRunner=None, testLoader=unittest.defaultTestLoader, exit=True, verbosity=1, failfast=None, catchbreak=None, buffer=None, warnings=None)
A command-line program that loads a set of tests from module and runs them; this is primarily for making test modules conveniently executable. The simplest use for this function is to include the following line at the end of a test script:
if __name__ == ‘__main__‘:
unittest.main()
You can run tests with more detailed information by passing in the verbosity argument:
if __name__ == ‘__main__‘:
unittest.main(verbosity=2)
一般情况下都会使用main,这时可以通过verbosity参数指定结果的详细程度。
另一个常用的是
class unittest.TextTestRunner(stream=None, descriptions=True, verbosity=1, failfast=False, buffer=False, resultclass=None, warnings=None, *, tb_locals=False)
A basic test runner implementation that outputs results to a stream. If stream is None, the default, sys.stderr is used as the output stream. This class has a few configurable parameters, but is essentially very simple. Graphical applications which run test suites should provide alternate implementations. Such implementations should accept **kwargs as the interface to construct runners changes when features are added to unittest.
基本的runner执行函数,输出指向一个stream。常用于输出测试结果到文件中。
Class and module level fixtures are implemented in TestSuite. When the test suite encounters a test from a new class then tearDownClass() from the previous class (if there is one) is called, followed by setUpClass() from the new class.
These must be implemented as class methods:
import unittest
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._connection = createExpensiveConnectionObject()
@classmethod
def tearDownClass(cls):
cls._connection.destroy()
基本版测试
import unittest
class MyTest(unittest.TestCase): # 继承unittest.TestCase
def tearDown(self):
# 每个测试用例执行之后做操作
print(‘tear down‘)
def setUp(self):
# 每个测试用例执行之前做操作
print(‘set up‘)
@classmethod
def tearDownClass(self):
# 必须使用 @ classmethod装饰器, 所有test运行完后运行一次
print(‘tear down class‘)
@classmethod
def setUpClass(self):
# 必须使用@classmethod 装饰器,所有test运行前运行一次
print(‘set up class‘)
def test_a_run(self):
self.assertEqual(1, 1) # 测试用例
def test_b_run(self):
self.assertEqual(2, 2) # 测试用例
if __name__ == ‘__main__‘:
unittest.main()#运行所有的测试用例
输出:
===== RESTART: E:\python\person_code\python libs tests\unittest_test1.py =====
set up class
set up
tear down
.set up
tear down
.tear down class
----------------------------------------------------------------------
Ran 2 tests in 0.086s
OK
>>>
#coding:utf-8
import unittest
from unittest_test1 import MyTest
if __name__ == ‘__main__‘:
suite = unittest.TestSuite()
tests = [MyTest("test_a_run"), MyTest("test_b_run")]
suite.addTests(tests)
with open(‘UnittestTextReport.txt‘, ‘a‘) as f:
runner = unittest.TextTestRunner(stream=f, verbosity=2)
runner.run(suite)
输出:
=========== RESTART: E:\python\person_code\python libs tests\d.py ===========
set up class
set up
tear down
set up
tear down
tear down class
>>>
txt格式的文本执行报告过于简陋,这里学习一下借助HTMLTestRunner生成HTML报告。首先需要下载HTMLTestRunner.py,并放到当前目录下,或者python目录下的Lib中,就可以导入运行了。
下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html
当然,测试代码需要改一部分
#coding:utf-8
import unittest
from unittest_test1 import MyTest
from HTMLTestRunner import HTMLTestRunner
if __name__ == ‘__main__‘:
suite = unittest.TestSuite()
tests = [MyTest("test_a_run"), MyTest("test_b_run")]
suite.addTests(tests)
with open(‘UnittestTextReport.html‘, ‘a‘) as f:
runner = HTMLTestRunner(stream=f,
title = ‘MathFunc Test Report‘,
description=‘generated by HTMLTestRunner.‘,
verbosity=2
)
runner.run(suite)
输出:
在使用HTMLTestRunner时报错:
ModuleNotFoundError: No module named ‘StringIO‘
原因为python3中StringIO已改到io中
需要对HTMLTestRunner作如下改变:
第94行,将import StringIO修改成import io as StringIO
第539行,将self.outputBuffer = StringIO.StringIO()修改成self.outputBuffer = io.StringIO()
第642行,将if not rmap.has_key(cls):修改成if not cls in rmap:
第766行,将uo = o.decode(‘latin-1‘)修改成uo = e
第775行,将ue = e.decode(‘latin-1‘)修改成ue = e
第631行,将print >> sys.stderr, ‘\nTime Elapsed: %s‘ % (self.stopTime-self.startTime)修改成print(sys.stderr, ‘\nTime Elapsed: %s‘ % (self.stopTime-self.startTime))
第689行 self.stream.write(output.encode(‘utf-8’))改为self.stream.write(output)
1、unittest是python自带的单元测试框架,我们可以用其来作为我们自动化测试框架的用例组织执行框架。
2、unittest的流程:写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,我们通过命令行或者unittest.main()执行时,main会调用TextTestRunner中的run来执行,或者我们可以直接通过TextTestRunner来执行用例。
3、一个class继承unittest.TestCase即是一个TestCase,其中以 test 开头的方法在load时被加载为一个真正的TestCase。
4、verbosity参数可以控制执行结果的输出,0 是简单报告、1 是一般报告、2 是详细报告。
5、可以通过addTest和addTests向suite中添加case或suite,可以用TestLoader的loadTestsFrom__()方法。
6、用 setUp()、tearDown()、setUpClass()以及 tearDownClass()可以在用例执行前布置环境,以及在用例执行后清理环境
7、我们可以通过skip,skipIf,skipUnless装饰器跳过某个case,或者用TestCase.skipTest方法。
8、参数中加stream,可以将报告输出到文件:可以用TextTestRunner输出txt报告,以及可以用HTMLTestRunner输出html报告。
笔记-python-standard library-26.4 unittest
原文:https://www.cnblogs.com/wodeboke-y/p/9925734.html