主要参考文章:
https://blog.csdn.net/xiaoquantouer/article/details/75089200
unittest中最核心的四部分是:
1.test fixture(测试固件)
2.test case(测试用例)
3.test suite(测试套件)
4.test runner(测试执行器 )
1.测试固件(test fixture):
一个测试用例环境的搭建和销毁,是一个fixture。
包括两部分setUp()和tearDown()
执行测试代码之前的准备部分和测试结束之后的清扫代码
(这里举例以下,例如要测试百度搜索selenium这个场景,我们的测试固件可以这样写,setUp()里写打开浏览器,浏览器最大化,和打开百度首页等脚本代码;在tearDown()里写结束搜索后,退出并关闭浏览器的代码。)
2.测试用例(test case):
什么是测试用例呢?就是一个完整的测试流程,包括测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)。
一个测试用例中,包括测试固件,但测试固件可以不写,但是至少有一个已test开头的函数。unittest会自动化识别test开头的函数是测试代码,如果你写的函数不是test开头,unittest是不会执行这个函数里面的脚本的,这个千万要记住,所有的测试函数都要test开头,记住是小写的哦
3.测试套件 (test suite):
多个测试用例集合在一起,就是TestSuite,而且TestSuite也可以嵌套TestSuite。
如果测试用例比作单个学生,测试套件就是好像是班级的概念。
4.测试执行器 (test runner):
test runner是一个用来执行加载测试用例,并执行用例,且提供测试输出的一个组建。test runner可以加载test case或者test suite进行执行测试任务。其中的run(test)会执行TestSuite/TestCase中的run(result)方法
5.TestLoader:
TestLoader是用来加载TestCase到TestSuite中的,其中有几个loadTestsFrom__()方法,就是从各个地方寻找TestCase,创建它们的实例,然后add到TestSuite中,再返回一个TestSuite实例。
6.TextTestResult:
测试的结果会保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息。
unittest的流程:
1.写好TestCase
2.由TestLoader加载TestCase到TestSuite
3.由TextTestRunner来运行TestSuite
(我们通过命令行或者unittest.main()执行时,main会调用TextTestRunner中的run来执行,或者我们可以直接通过TextTestRunner来执行用例。)
4.运行的结果保存在TextTestResult中
注:
verbosity参数可以控制执行结果的输出,0 是简单报告、1 是一般报告、2 是详细报告。
用 setUp()、tearDown()、setUpClass()以及 tearDownClass()可以在用例执行前布置环境,以及在用例执行后清理环境
我们可以通过skip,skipIf,skipUnless装饰器跳过某个case,或者用TestCase.skipTest方法。
使用unittest编写用例,必须遵守以下规则:
1.测试文件必须先import unittest
2.测试类必须继承unittest.TestCase
3.测试方法必须以“test_”开头
4.测试类必须要有unittest.main()方法
先写了一个待测试文件mathfunc.py内容如下:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
def add(a,b):
return a+b
def minus(a,b):
return a-b
def multi(a,b):
return a*b
def divide(a,b):
return a/b
接下来写了一个它的测试用例,新建了一个test_mathfunc.py,内容如下:(注意四个规则)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import unittest
from mathfunc import *
class TestMathFunc(unittest.TestCase):
def test_add(self):
self.assertEqual(3,add(1,2))
self.assertNotEqual(3,add(2,2))
def test_minus(self):
self.assertEqual(1,minus(3,2))
def test_multi(self):
self.assertEqual(6,multi(2,3))
def test_divide(self):
self.assertEqual(2,divide(6,3))
self.assertEqual(2.5,divide(6,3))
if __name__== '__main__':
unittest.main(verbosity=2)
另一个测试用例test_mathfuna.py
前边没有用到,后边调用两个用例的时候才用到了
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import unittest
from mathfunc import *
class TestMathFuna(unittest.TestCase):
def test_multi(self):
self.assertEqual(6,multi(2,3))
def test_minus(self):
self.assertEqual(1,minus(3,2))
def test_divide(self):
self.assertEqual(2,divide(6,3))
@unittest.skip("i don't want to run this case.")
def test_minus(self):
self.assertEqual(1, minus(3, 2))
if __name__== '__main__':
unittest.main(verbosity=2)
执行单个测试方法:
调用test_mathfunc.py的测试方法,能执行test_mathfunc.py里的test_minus、test_add和test_divide
test_suit.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import unittest
from test_mathfunc import TestMathFunc#导入test_mathfunc里的TestMathFunc类
if __name__=='__main__':
suite=unittest.TestSuite()
tests=[TestMathFunc("test_minus"),TestMathFunc("test_add"),TestMathFunc("test_divide")]
suite.addTests(tests)
runner=unittest.TextTestRunner(verbosity=2)
runner.run(suite)
执行单个测试方法或整个测试类
1.直接用addTest方法添加单个TestCase
2.用addTests + TestLoader添加整个测试类
TestLoader:
loadTestsFromName()
loadTestsFromTestCase()
test_suit1.py
import unittest
from test_mathfunc import TestMathFunc
if __name__=='__main__':
suite = unittest.TestSuite()
# 直接用addTest方法添加单个TestCase
suite.addTest(TestMathFunc("test_multi"))
# 用addTests + TestLoader
# loadTestsFromName(),传入'模块名.TestCase名'
suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfunc.TestMathFunc'))
suite.addTests(unittest.TestLoader().loadTestsFromNames(['test_mathfunc.TestMathFunc'])) # loadTestsFromNames(),类似,传入列表
# loadTestsFromTestCase(),传入TestCase
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc))
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)
在项目中生成一个文本的测试报告
test_suit2.py
# -*- coding: utf-8 -*-
import unittest
from test_mathfunc import TestMathFunc
if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc))
with open('UnittestTextReport.txt', 'a') as f:
runner = unittest.TextTestRunner(stream=f, verbosity=2)
runner.run(suite)
又写了一个test_mathfuna来测试两个用例的调用
test_suittwo.py
import unittest
from test_mathfunc import TestMathFunc
from test_mathfuna import TestMathFuna
if __name__=='__main__':
suite = unittest.TestSuite()
# 用addTests + TestLoader
# loadTestsFromName(),传入'模块名.TestCase名'
suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfunc.TestMathFunc'))
suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfuna.TestMathFuna'))
with open('UnittestTextReporttwo.txt', 'a') as f:
runner = unittest.TextTestRunner(stream=f, verbosity=2)
runner.run(suite)
test_suittwo1.py
# -*- coding:utf-8 -*-
import unittest
from test_mathfunc import TestMathFunc
from test_mathfuna import TestMathFuna
if __name__=='__main__':
suite=unittest.TestSuite()
tests=[TestMathFunc("test_minus"),TestMathFunc("test_add"),TestMathFunc("test_divide")]
tests1=[TestMathFuna("test_divide")]
suite.addTests(tests)
suite.addTests(tests1)
with open('UnittestTextReporttwo2.txt', 'a') as f:
runner = unittest.TextTestRunner(stream=f, verbosity=2)
runner.run(suite)
生成html格式的测试报告
test_suit Open Html.py
# coding=utf-8
import unittest
from test_mathfunc import TestMathFunc
from HTMLTestRunner import HTMLTestRunner
if __name__ == '__main__':
suite = unittest.TestSuite()
tests = [TestMathFunc("test_add"), TestMathFunc("test_minus"), TestMathFunc("test_divide")]
suite.addTests(tests)
with open('HTMLReport1.html', 'wb+') as f:
runner = HTMLTestRunner(stream=f,
title='MathFunc Test Report',
description='generated by HTMLTestRunner.',
verbosity=2
)
runner.run(suite)
这里遇到了一个问题:python3 引入HTMLTestRunner运行 报错 ImportError: No module named ‘StringIO’
这个我在个人分类的使用appium中遇到的问题中有写:
https://blog.csdn.net/weixin_40412060/article/details/82841473