python- Unittest测试框架.md
Unittest 框架学习
Unittest = PyUnit ,是 Python 标准库中自带的单元测试框架。适用于单元测试、接口测试、Web 自动化测试,特性:通过类的方式,将测试用例组织在一起。
一、核心要素
- test case 测试案例
 - test suite 测试套件
 - test runner 测试部件
 - text fixture 测试装置
 
二、常见属性
import unittest
dir(unittest) # 查询包下面的所有属性
dir(unittest.TestCase) # 查询其中所有函数
- unittest.TestCase():所有测试用例类继承的基本类
 - unittest.TestSuite():用来创建测试套件的
 - unittest.main():将单元测试模块变为可直接运行的测试脚本,main()方法使用 TestLoader 类执行所有 test 开头的测试方法,且执行顺序根据 ASCII 码:0-9\A-Z\a-z。
 - unittest.TextTestRunner():通过下面的 run() 方法来运行 cuite 组装的测试用例,入参为测试套件。
 
三、Unittest常见用法:基本用法小结
- 导入 unittest 模块、被测文件或者其中的类。
 - 创建测试类,并继承 unittest.TestCase。
 - 重写 setUp 和 tearDown 方法,该两种方法在父类中已经存在。
 - 定义测试函数,用 test 开头。
 - 在函数体内使用断言。
 - 调用 unittest.main() 方法来运行测试用例。
 
演练-计算器
计算器类
1  | class Calculator(object):  | 
实际应用
1  | # 导入unittest模块  | 
四、用例执行顺序,组装测试用例
unittest 默认根据 ASCII 码,0-9,A-Z,a-z。
修改用例执行顺序,添加执行集
修改测试用例方法名,前标序号
test_001_***
引用测试集,按引入顺序执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26# 测试套件的使用
if __name__=='__main__':
# 构造测试集
suite = unittest.TestSuite()
# 将测试用例加入测试集
# 方法一:
suite.addTest(TestCalculator('test_add'))
# 方法二:将用例编入列表,逐一添加
tests = [
TestCalculator('test_add'),
TestCalculator('test_minus'),
TestCalculator('test_multip'),
TestCalculator('test_divide')
]
suite.addTest(tests)
# 执行测试集合
runner=unittest.TextTestRunner(verbosity=2)
runner.run(suite)
```
3. TestLoader.loadTestsFromTestCase 加载多个类
使用最多,可以一次加载某个类下面的所有测试用例,也支持加载多个类。import unittest
from test_24_02 import TestCalculator
from test_24_02_02 import TestCalculator2
if name == ‘main‘:
    suite1 = unittest.TestLoader().loadTestsFromTestCase(TestCalculator)
    suite2 = unittest.TestLoader().loadTestsFromTestCase(TestCalculator2)
suite = unittest.TestSuite([suite1, suite2])
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)
1  | 
  | 
import os
import unittest
if _name == ‘main‘:
    # 实例化测试套件
    suite = unittest.TestSuite()
    # 1.实例化 TestLoader 对象
    # 2.使用discover 去找一个目录下的所有测试用例
    loader = unittest.TestLoader()
    # 3.使用 addTests 将找到的测试用例放在测试套件下
    # os.getcwd()=获取当前目录
    # 默认搜索路径,当前目录下,以 test 开头的测试文件
    suite.addTests(loader.discover(os.getcwd()))
# 方法二:指定目录
test_dir = './test'
suite = unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')
   runner=unittest.TextTestRunner()
   runner.run(suite)
1  | 
  | 
with open('unittest_report.txt', 'w') as f:
    runner = unittest.TextTestRunner(stream=f, verbosity=2)
    runner.run(suite)
1  | 
  | 
@classmethod
def setUpClass(cls) :
    print('仅测试套件前执行一次')
@classmethod
def tearDownClass(cls) :
    print('仅测试套件结束后执行一次')
1  | 
  | 
@unittest.skip('不执行')
def test_add(self):
    # 加断言
    self.assertEqual(self.result.add(),12,'加法错误!')
Skipped: 不执行
1  | 
  | 
@unittest.skipIf(3 > 2, '3>2 不执行')
def test_add(self):
    # 加断言
    self.assertEqual(self.result.add(), 12, '加法错误!')
Skipped: 3>2 不执行
1  | 
  | 
@unittest.skipUnless(sys.platform.startswith('linux'),'require Linux')
def test_add(self):
    # 加断言
    self.assertEqual(self.result.add(), 12, '加法错误!')
Skipped: require Linux
1  | 4. @unittest.expectedFailure():测试标记失败。  | 
def test_add(self):
    # 加断言
    self.skipTest('无需执行')
    self.assertEqual(self.result.add(), 12, '加法错误!')
Skipped: 无需执行
1  | 
  | 
python -m unittest
python -m unittest discover
1  | 
  | 
python -m unittest discover -s project_directory -p “test_*.py”
1  | 
  | 
python -m unittest discover project_directory “test_*.py”
1  | 
  | 
python -m unnittest test_module1 test_module2
1  | 
  | 
python -m unittest test_module.TestClass
1  | 
  | 
python -m unittest 模块名.类名.方法名(用例)
1  | 
  | 
python -m unittest tests/test_something.py
1  | 
  | 
import unittest
from ddt import ddt, data, unpack
加装饰器,与以下的装饰器,写法固定
@ddt
class MyTest(unittest.TestCase):
    # 声明参数,以元祖或列表的形式,每条数据对应一条用例
    @data((3, 1), (1, 0), (1.2, 1.0))
    @unpack
    def test_values(self, first, second):
        print(first, second)
        self.assertTrue(first > second)
1  | 
  | 
import ddt
import unittest
@ddt.ddt
class MyTest(unittest.TestCase):
    #列表或元祖
    @ddt.data([1, 2, 3, 6])
    @ddt.unpack
    def test_add(self, t1, t2, t3, excp):
        sum = t1 + t2 + t3
        self.assertEqual(sum, excp)
1  | 
  | 
——–data_003.json——–
[
  “1||2||3”,
  “3||2||5”,
  “3||8||11”
]
———test_003.py———-
@ddt.ddt
class MyTest(unittest.TestCase):
# 数据以外部文件形式存储
@ddt.file_data('data_003.json')
@ddt.unpack
def test_sum(self, value):
    # 数据读取,分离
    a, b, sum = value.split('||')
    print(a, b, sum)
    result = int(a) + int(b)
    self.assertEqual(result, int(sum))
1  | 
  | 
import unittest
from parameterized import parameterized
class MyTest(unittest.TestCase):
    @parameterized.expand([(3, 1), (1, 10)])
    def test_values(self, first, second):
        print(first,second)
        self.assertTrue(first > second)
1  | 
  | 
import unittest
from parameterized import parameterized
class MyTest(unittest.TestCase):
@parameterized.expand([('plumrx', '123'), ('miumiu', '321')])
def test_params(self, name, pwd):
    print('name=%s,pwd=%s' % (name, pwd))
1  | 
  | 
class Test(object):
    def test_login(self):
        payload={‘username’:’plumrx’,’password’:’plumrx’}
        response=TestBattal.http.post(‘login’,params=payload)
    globals()["text"]=response.text.split('\n')[1:]
    
    
def test_select(self):
    global()["equipment"]=random.choice(globals()["text"]).split('')[0]
```