笔记-python-standard library-26.4 unittest

1.      unittest

source code:Lib/unittest/__init__.py

它是python自带的单元测试框架,封装好了一些校验返回的结果方法和一些用例执行前的初始化操作。

在开始之前,有几个概念:

  1. test fixture

它表示一个或多个测试用例,还有相关的清理动作;

  1. test case:测试用例,unittest提供了一个基类,TestCase;
  2. test suite:测试用例集合,也可包含test suite,
  3. 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=())

  1. addTest(test)

Add a TestCase or TestSuite to the suite.

  1. 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.

  1. 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的更多相关文章

  1. The Python Standard Library

    The Python Standard Library¶ While The Python Language Reference describes the exact syntax and sema ...

  2. Python Standard Library

    Python Standard Library "We'd like to pretend that 'Fredrik' is a role, but even hundreds of vo ...

  3. Python语言中对于json数据的编解码——Usage of json a Python standard library

    一.概述 1.1 关于JSON数据格式 JSON (JavaScript Object Notation), specified by RFC 7159 (which obsoletes RFC 46 ...

  4. 《The Python Standard Library》——http模块阅读笔记1

    官方文档:https://docs.python.org/3.5/library/http.html 偷个懒,截图如下: 即,http客户端编程一般用urllib.request库(主要用于“在这复杂 ...

  5. 《The Python Standard Library》——http模块阅读笔记2

    http.server是用来构建HTTP服务器(web服务器)的模块,定义了许多相关的类. 创建及运行服务器的代码一般为: def run(server_class=HTTPServer, handl ...

  6. 《The Python Standard Library》——http模块阅读笔记3

    http.cookies — HTTP state management http.cookies模块定义了一系列类来抽象cookies这个概念,一个HTTP状态管理机制.该模块支持string-on ...

  7. Python Standard Library 学习(一) -- Built-in Functions 内建函数

    内建函数列表 Built-in Functions abs() divmod() input() open() staticmethod() all() enumerate() int() ord() ...

  8. [译]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模块为与操作系统 ...

  9. C++11新特性——The C++ standard library, 2nd Edition 笔记(一)

    前言 这是我阅读<The C++ standard library, 2nd Edition>所做读书笔记的第一篇.这个系列基本上会以一章一篇的节奏来写,少数以C++03为主的章节会和其它 ...

  10. [译]The Python Tutorial#11. Brief Tour of the Standard Library — Part II

    [译]The Python Tutorial#Brief Tour of the Standard Library - Part II 第二部分介绍更多满足专业编程需求的高级模块,这些模块在小型脚本中 ...

随机推荐

  1. android 屏幕单击位置测试

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools= ...

  2. Azure 1 月新公布

    Azure 1 月新发布:Microsoft Power BI Embedded 公共预览和计算机视觉 API 标准版的更新以及 Azure IoT 网关 SDK 和中心设备管理新功能正式发布以及关于 ...

  3. bootstrap文件上传fileupload插件

    Bootstrap FileInput中文API整理:https://blog.csdn.net/u012526194/article/details/69937741 SpringMVC + boo ...

  4. JavaScript如何转换数据库DateTime字段类型?

    Javascript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在html(标 ...

  5. windows cmd窗口,输出UTF-8格式文件,显示乱码

    本文来自网络,参考文档见文档末尾 想在windows cmd窗口中查看utf-8中文,需要先执行以下步骤 chcp 65001 将CMD窗口切换成UTF-8代码页 在命令行标题栏上点击右键,选择&qu ...

  6. Xapian简明教程(未完成)

    第一章 简介 1.1 简介 Xapian是一个开源的搜索引擎库,它可以让开发者自定义的开发一些高级的的索引和查找因素应用在他们的应用中. 通过阅读这篇文档,希望可以帮助你创建第一个你的索引数据库和了解 ...

  7. MVC中某个页面不需要引用母版页的正确写法

    有些页面想使用单独的样式不想用母版页的时候,可以在开始声明下,就可以不用母版页的CSS和JS引用了语法如下: @{Layout = "";} . 非常之简单

  8. POJ-3614 Sunscreen---贪心+优先队列

    题目链接: https://vjudge.net/problem/POJ-3614 题目大意: 有C个奶牛去晒太阳 (1 <=C <= 2500),每个奶牛各自能够忍受的阳光强度有一个最小 ...

  9. log4net为什么会打印两次?

    用“log4net 使用”做关键字在bing上搜索,点开排序第一的链接:http://33liuhongwei33.blog.163.com/blog/static/39923778201156101 ...

  10. 线程 Thread类 的四个构造方法简介

    在线程中,Thread类有四个构造方法: 当我们使用 Thread类创建对象的时候,传入参数,就会用到构造方法.ThreadStart 和ParameterizedThreadStart 都是 委托类 ...