笔记-python-standard library-26.4 unittest
笔记-python-standard library-26.4 unittest
1. unittest
source code:Lib/unittest/__init__.py
它是python自带的单元测试框架,封装好了一些校验返回的结果方法和一些用例执行前的初始化操作。
在开始之前,有几个概念:
- test fixture
它表示一个或多个测试用例,还有相关的清理动作;
- test case:测试用例,unittest提供了一个基类,TestCase;
- test suite:测试用例集合,也可包含test suite,
- test runner:它是一个执行测试并输出测试结果的组件。
1.1. test case和更高级别的用例集合
单元测试的最小单元是测试用例,典型的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())
这样最重要的益处是可以将用例和测试代码分开。
1.2. skipping tests and expected failures
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")
1.2.1. skip装饰器及其变型
@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.
1.3. class and functions
This section describes in depth the API of unittest.
1.3.1. test case
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 |
下面还有很多方法,使用的时候可以查,这里不多写。
1.3.2. group tests
class unittest.TestSuite(tests=())
- addTest(test)
Add a TestCase or TestSuite to the suite.
- addTests(tests)
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.
- countTestCases()
Return the number of tests represented by this test object, including all individual tests and sub-suites.
1.3.3. loading and running tests
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。常用于输出测试结果到文件中。
1.4. Class and Module Fixtures
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.
1.4.1. setUpClass and tearDownClass
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()
2. 案例实测
2.1. 案例1
基本版测试
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
>>>
2.2. 测试结果输出到文件
#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
>>>
3. 扩展
3.1. 测试结果美化
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)
输出:
3.1.1. 问题
在使用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)
4. 总结
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的更多相关文章
- The Python Standard Library
The Python Standard Library¶ While The Python Language Reference describes the exact syntax and sema ...
- Python Standard Library
Python Standard Library "We'd like to pretend that 'Fredrik' is a role, but even hundreds of vo ...
- Python语言中对于json数据的编解码——Usage of json a Python standard library
一.概述 1.1 关于JSON数据格式 JSON (JavaScript Object Notation), specified by RFC 7159 (which obsoletes RFC 46 ...
- 《The Python Standard Library》——http模块阅读笔记1
官方文档:https://docs.python.org/3.5/library/http.html 偷个懒,截图如下: 即,http客户端编程一般用urllib.request库(主要用于“在这复杂 ...
- 《The Python Standard Library》——http模块阅读笔记2
http.server是用来构建HTTP服务器(web服务器)的模块,定义了许多相关的类. 创建及运行服务器的代码一般为: def run(server_class=HTTPServer, handl ...
- 《The Python Standard Library》——http模块阅读笔记3
http.cookies — HTTP state management http.cookies模块定义了一系列类来抽象cookies这个概念,一个HTTP状态管理机制.该模块支持string-on ...
- Python Standard Library 学习(一) -- Built-in Functions 内建函数
内建函数列表 Built-in Functions abs() divmod() input() open() staticmethod() all() enumerate() int() ord() ...
- [译]The Python Tutorial#10. Brief Tour of the Standard Library
[译]The Python Tutorial#Brief Tour of the Standard Library 10.1 Operating System Interface os模块为与操作系统 ...
- C++11新特性——The C++ standard library, 2nd Edition 笔记(一)
前言 这是我阅读<The C++ standard library, 2nd Edition>所做读书笔记的第一篇.这个系列基本上会以一章一篇的节奏来写,少数以C++03为主的章节会和其它 ...
- [译]The Python Tutorial#11. Brief Tour of the Standard Library — Part II
[译]The Python Tutorial#Brief Tour of the Standard Library - Part II 第二部分介绍更多满足专业编程需求的高级模块,这些模块在小型脚本中 ...
随机推荐
- angular解决压缩问题,和传送数据
1.angular解决压缩的方法 var app = angular.module("mk",[]); app.controller("ctrl",['$sco ...
- CSS3伪类使用方法实例
有时候在网页设计中会涉及到很多看上去很繁琐的设计图,这时候都会很让人头疼,那么这时候伪类就可以来帮助你解决问题了. 下面有一段实例大家可以参考一下: <!DOCTYPE html> < ...
- C++ Knowledge series 4
Programming language evolves always along with Compiler's evolvement The Semantics of Function C++ s ...
- Python开发环境Wing IDE使用教程之matplotlib 2D绘图库代码调试技巧
Wing IDE是一个集成开发环境,可用于加快matplotlib2D图形库的Python代码的编写和调试进程.Wing IDE提供自动完成.调用提示.调试器,以及许多其他功能,可帮助用户编写.浏览和 ...
- APK加固之类抽取分析与修复
0x00 简单介绍 目前我己知的APK加固主要有以下两种方式(或有其它的方式有待发现) 隐藏dex文件:通过对目标DEX文件进行整体加密或压缩方式把整个dex转换为另外一个文件存放在assets文 ...
- SpringCloud的学习记录(1)
最近一段时间重新学习一边SpringCloud(有半年不用了),这里简单记录一下. 我用的是IntelliJ IDEA开发工具, SpringBoot的版本是2.1.3.RELEASE. 1. 构建M ...
- seleenium与Vs结合
Vs 自带自动化测试录制工具.selenium则是开源的大众工具.在使用发现vs 自带的工具录制方便,但是修改很难.但是可以提供后续的BUG管理和邮件通知,自动构建等功能.selenium在.net平 ...
- 分布式系统ID生成方案汇总
在分布式系统中,需要对大量的数据.消息.请求等进行唯一的标识,例如分布式数据库的ID需要满足唯一且多数据库同步,在单一系统中,使用数据库自增主键可以满足需求,但是在分布式系统中就需要一个能够生成全局唯 ...
- mybatis由JDBC的演化过程分析
我们知道,mybatis是对JDBC的封装,那么他是如何演变过来的呢? 摘自传智传媒Java培训资料 关于mybatis的演化原理,我们先看看我们最熟悉也是最基础的通过JDBC查询数据库数据,一般需要 ...
- [译文]PHP千年虫(y2k compliance)
时钟将我们无情地逼近2000年的最后一年,第二年厄运塞耶斯都预言前所未有的电脑故障在每一个可以想象的领域.通常被称为2000年问题,或千年虫,这种 情况很容易解释.程序解释两位在形成XX日期19 XX ...