unittest学习记录

运行方式

我们写好的测试脚本可以怎么运行呢?unittest提供以下的方式运行写好的unittestcase

unittest.main()入口运行

.py文件里面添加unittest.main():unittest.main() 提供了一个测试脚本的命令行接口
–测试代码

import unittest

class TestScript(unittest.TestCase):
    '''测试unittest.main()'''
    def setUp(self) -> None:
        print(TestScript.__doc__.strip())
    def test_case1(self):
        print('执行测试1')
        self.assertEqual(3,3)
    def test_case2(self):
        print('执行测试2')
        self.assertTrue('1')
    def test_case3(self):
        print('执行测试3')
        self.assertTrue(1)
if __name__ == "__main__":
    unittest.main()   # 执行test_case1,test_case2,test_case3两条测试用例
    unittest.main(argv=['test.py','TestScript.test_case2']) #执行test_case2单条测试用例
    unittest.main(argv=['test.py','TestScript.test_case2','TestScript.test_case3']) #执行test_case2,test_case3多条测试用例

注意:
-unittest.main()会默认执行该模块下的所有测试用例
-unittest.main(argv=[‘test.py’,‘TestScript.test_case2’])会执行指定的单条测试用例,如只执行test_case2
-unittest.main(argv=[‘test.py’,‘TestScript.test_case2’,‘TestScript.test_case3’])会执行指定的多条测试用例,如执行test_case2和test_case3
-注意此方式在pycharm下应不采用unitest去运行
在这里插入图片描述

命令行运行

1> 运行模块、类、独立测试方法
python -m unittest test_module1 test_module2
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method
2> 通过指定文件方式进行传参
python -m unittest tests/test_something.py
3> 命令行其他常用参数:
在这里插入图片描述
4> 探索式测试:
> 执行方式:探索性测试不传参时python -m unittest 与 python -m unittest discover等价;探索式测试传参时需要使用python -m unittest discover
在这里插入图片描述
5>跳过执行:@unittest.skip()、 @unittest.skipIf()、 @unittest.skipUnless()

批量执行脚本–加入测试套件

写好的unittestcase需要自定义运行的时候,需要将其加入测试套件,再批量运行。那么如何加入测试套件呢?

通过unittest.TestSuite()类构建

1>. 通过unittest.TestSuite()类直接构建,或者通过TestSuite实例的addTests、addTest方法构建
–代码结构:test.py,test1.py,test_all.py位于同一目录下
–test.py代码如下

import unittest

class TestScript(unittest.TestCase):
    '''测试unittest-加入测试套件test'''
    @classmethod
    def setUpClass(cls) -> None:
        print("测试类前置")

    def test_case1(self):
        print("执行test的测试用例1")
    def test_case2(self):
        print("执行test的测试用例2")

if __name__ == "__main__":
    suite = unittest.TestSuite(map(TestScript,["test_case1","test_case2"]))
    # print(list(map(TestScript,["test_case1","test_case2"])))   # [<__main__.TestScript testMethod=test_case1>, <__main__.TestScript testMethod=test_case2>]
    suite1 = unittest.TestSuite()
    suite1.addTests(map(TestScript,["test_case1","test_case2"]))  # 添加多个测试用例
    suite2 = unittest.TestSuite()
    suite2.addTest(TestScript("test_case2"))   # 添加单个测试用例

    result = unittest.TextTestResult(sys.stdout,'test_result',1)
    suite1.run(result)

–test1.py代码如下

import unittest
class TestScript(unittest.TestCase):
    '''测试unittest-加入测试套件test1'''
    @classmethod
    def setUpClass(cls) -> None:
        print("执行测试前置")

    def test_case1(self):
        print("执行test1的测试用例1")
    def test_case2(self):
        print("执行test1的测试用例2")
    def test_case3(self):
        print("执行test1的测试用例3") 

–test_all.py代码如下:

import unittest
import sys

suite3 = unittest.TestSuite()
# __import__ 动态加载类和函数:当 name 变量的形式为 package.module 时,通常将会返回最高层级的包(第一个点号之前的名称),而 不是 以 name 命名的模块。 但是,当给出了非空的 fromlist 参数时,则将返回以 name 命名的模块。
testModule = __import__("test",{},{},"test")
testModule1 = __import__("test1",{},{},"test1") # 在相同目录下可以直接写模块名字进行导入,如果不在相关目录,需要根据项目根目录进行定位
testcases = [testModule1.TestScript("test_case1"),testModule1.TestScript("test_case3"),testModule.TestScript("test_case2")]
suite3.addTests(testcases)
print(suite3)
# <unittest.suite.TestSuite tests=[<test1.TestScript testMethod=test_case1>, <test1.TestScript testMethod=test_case3>, <test.TestScript testMethod=test_case2>]>
result = unittest.TextTestResult(sys.stdout,"test_result",1)
suite3.run(result)

–test.py执行结果:
在这里插入图片描述
–test_all.py执行结果:
在这里插入图片描述

通过unittest.TestLoader类构建

2>. 通过unittest.TestLoader类的discover、loadTestsFromTestCase、loadTestsFromModule、loadTestsFromName、loadTestsFromNames这五个方法去构建
–代码结构:test.py和test_all.py位于同一目录下
–test.py代码如下:

import unittest

class TestScript(unittest.TestCase):
    '''测试unittest-加入测试套件test'''
    @classmethod
    def setUpClass(cls) -> None:
        print("TestScript测试类的前置")

    def test_case1(self):
        print("执行test的测试用例test_case1")
    def test_case2(self):
        print("执行test的测试用例test_case2")
    def test_step1(self):
        print("执行test的测试用例test_step1")
    def test_step2(self):
        print("执行test的测试用例test_step2")
class TestCaseCS(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        print("TestCaseCS测试类的前置")
    def test_step1(self):
        print("执行test的测试类TestCaseCS类的测试用例test_step1")

if __name__ == "__main__":
    '''使用unittest.TestLoader类discover、loadTestsFromTestCase、loadTestsFromModule、loadTestsFromName、loadTestsFromNames'''
    suite = unittest.TestLoader().discover(".","test*")
    suite1 = unittest.TestLoader().discover(".","test_step*")  # 未找到
    suite2 = unittest.TestLoader().loadTestsFromTestCase(TestScript)
    suite3 = unittest.TestLoader().loadTestsFromTestCase(TestCaseCS)
    module = __import__(__name__)
    # print(module) # <module '__main__' from 'D:/pyInfcAutotest/intertestframework-master-20210304/intertestframework-master/test_case/002_unittest_test/test.py'>
    result = unittest.TextTestResult(sys.stdout,'test_result',1)
    suite3.run(result)

–test_all.py代码如下:

import unittest
import sys
testModule = __import__("test",{},{},"test")
print(testModule)
suite = unittest.TestLoader().loadTestsFromModule(testModule)
suite1 = unittest.TestLoader().loadTestsFromNames(["TestCaseCS.test_step1","TestScript.test_case2"],testModule)
suite2 = unittest.TestLoader().loadTestsFromName("TestScript.test_step2",testModule)

result = unittest.TextTestResult(sys.stdout,"test_all_result",1)
suite2.run(result)

–test.py执行结果:(注意在执行test.py的时候还没有创建test_all.py)
–test.py执行suite结果
在这里插入图片描述
–test.py执行suite1结果
未找到测试用例,无结果打印
–test.py执行suite2结果
在这里插入图片描述

–test.py执行suite3结果
在这里插入图片描述

–test_all.py执行suite结果
在这里插入图片描述

–test_all.py执行suite1结果
在这里插入图片描述

–test_all.py执行suite2结果
在这里插入图片描述

通过unittest.makeSuite()、unittest.findTestCases()构建

3>. 通过unittest.makeSuite()、unittest.findTestCases()这两个方法去构建
–代码结构:test.py
–test.py代码如下

import unittest

class TestScript(unittest.TestCase):
    '''测试unittest-加入测试套件test'''
    @classmethod
    def setUpClass(cls) -> None:
        print("TestScript测试类的前置")

    def test_case1(self):
        print("执行test的测试用例test_case1")
    def test_case2(self):
        print("执行test的测试用例test_case2")
    def test_step1(self):
        print("执行test的测试用例test_step1")
    def test_step2(self):
        print("执行test的测试用例test_step2")
    def case_test1(self):
        print("执行test的测试用例case_test1")
class TestCaseCS(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        print("TestCaseCS测试类的前置")
    def test_step1(self):
        print("执行test的测试类TestCaseCS类的测试用例test_step1")
    def case_test1(self):
        print("执行test的测试类TestCaseCS类的测试用例case_test1")

if __name__ == "__main__":
    '''通过unittest.makeSuite()、unittest.findTestCases()这两个方法去构建'''
    module = __import__("test")
    suite = unittest.makeSuite(TestCaseCS,prefix='test')
    suite1 = unittest.makeSuite(TestCaseCS,prefix='case')
    suite2 = unittest.findTestCases(module,prefix="test")
    suite3 = unittest.findTestCases(module,prefix="case")

    result = unittest.TextTestResult(sys.stdout,"test_result",1)
    suite3.run(result)

–test.py执行suite3结果:
在这里插入图片描述

数据驱动/参数化

适用于测试方法不变,但是不同的参数输出不同或者相同的测试结果的场景。接口测试中可以运行的场景是参数校验的测试

ddt方式

1>ddt方式
–代码结构:test.py和test_ddt.json位于同于路径下

import unittest
import ddt
test_data = [
    {"body":{
        "username":"test1",
        "sex":"0",
        "city":"BeiJing"
    },
    "code":"1005",
    "message":"消息格式错误"
    },
    {"body":{
        "username":"test2",
        "sex":"1",
        "city":"ShangHai"
    },
        "code":"1005",
        "message":"消息格式错误"
    }
]
@ddt.ddt
class TestScript(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        print("测试前置")

    # 测试ddt
    @ddt.data(*test_data)
    def test_param(self,data):
        # 方式1:不通过解包方式获取请求body,响应code和响应message
        print(data.get("body"))
        print(data.get("code"))
        print(data.get("message"))
        # print(data)
        
    @ddt.data(*test_data)
    @ddt.unpack
    def test_param1(self,body,code,message):
        print(body)
        print(code)
        print(message)
    @ddt.file_data("test_ddt.json")
    def test_param2(self,body,code,message):
        print(body)
        print(code)
        print(type(message))

if __name__ == "__main__":
    unittest.main()

–执行test.py结果:
在这里插入图片描述

paramunitest方式

2>paramunitest
–目录结构:test.py和test_param.json在同一路径下
–test.py代码

import unittest
import paramunittest
import json
import requests

with open("./test_param.json","r",encoding="utf-8") as fb:
    dictdata = json.load(fb)
# print(dictdata)

@paramunittest.parametrized(*dictdata)
class TestScript(unittest.TestCase):
    '''测试参数化'''
    @classmethod
    def setUpClass(cls) -> None:
        print("测试类前置")

    def setParameters(self,body,code,message):
        self.body = body
        self.code = code
        self.message = message
    def test_param(self):
        # 发起请求
        r = requests.post("http://10.1.70.170:30894/test",json=self.body)
        self.assertEqual(self.code,r.json().get("code"))
        self.assertEqual(self.message,r.json().get("message"))
        # print(self.body)
        # print(self.code)
        # print(self.message)

if __name__ == "__main__":
    unittest.main(verbosity=2)

—test_param.json文件

[
{
  "body": {
    "tel":"151521861981",
    "area_code":"028",
    "expiration":"20",
  },
  "code": "1005",
  "message": "请求消息格式错误"
},
{
  "body": {
    "area_code":"ss",
    "expiration":"20",
    "audio":"256",
  },
  "code": "1005",
  "message": "请求消息格式错误"
}
]

–执行结果
两条测试用例跑通

生成测试结果/报告

生成测试结果/报告的两种方式:unittest自带TextTestRunner和HTMLTestRunner

TextTestRunner输出txt报告

–代码目录结构:test.py和report目录在同一层级目录
–test.py代码如下:

import unittest
import os
import time

class TestScript(unittest.TestCase):
    '''测试unittest-加入测试套件test'''
    @classmethod
    def setUpClass(cls) -> None:
        print("TestScript测试类的前置")

    def test_case1(self):
        print("执行test的测试用例test_case1")
    def test_case2(self):
        print("执行test的测试用例test_case2")
    def test_step1(self):
        print("执行test的测试用例test_step1")
    def test_step2(self):
        print("执行test的测试用例test_step2")
    def case_test1(self):
        print("执行test的测试用例case_test1")
class TestCaseCS(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        print("TestCaseCS测试类的前置")
    def test_step1(self):
        print("执行test的测试类TestCaseCS类的测试用例test_step1")
    def case_test1(self):
        print("执行test的测试类TestCaseCS类的测试用例case_test1")

if __name__ == "__main__":
    module = __import__("test")
    suite3 = unittest.findTestCases(module,prefix="case")
    rootPath = os.path.abspath(".")
    record = time.strftime("%Y-%m-%d_%H-%M-%S")
    spath = os.path.join(rootPath,'report','test_'+record)
    print(spath)
    os.makedirs(spath)
    filename = os.path.join(spath,"Test_Report.txt")
    with open(filename,'w+') as f:
        runner = unittest.TextTestRunner(stream=f,verbosity=2)
        runner.run(suite3)

–运行test.py结果:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

HTMLTestRunner输出HTML报告

–代码目录同上TextTestRunner
–使用的是HTMLTestRunner-rv 1.0.15:pip install HTMLTestRunner-rv
–test.py代码如下

import unittest
import os
import time
from HTMLTestRunner import HTMLTestRunner

class TestScript(unittest.TestCase):
    '''测试unittest-加入测试套件test'''
    @classmethod
    def setUpClass(cls) -> None:
        print("TestScript测试类的前置")

    def test_case1(self):
        print("执行test的测试用例test_case1")
    def test_case2(self):
        print("执行test的测试用例test_case2")
    def test_step1(self):
        print("执行test的测试用例test_step1")
    def test_step2(self):
        print("执行test的测试用例test_step2")
    def case_test1(self):
        print("执行test的测试用例case_test1")
class TestCaseCS(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        print("TestCaseCS测试类的前置")
    def test_step1(self):
        print("执行test的测试类TestCaseCS类的测试用例test_step1")
    def case_test1(self):
        print("执行test的测试类TestCaseCS类的测试用例case_test1")

if __name__ == "__main__":
    module = __import__("test")
    suite3 = unittest.findTestCases(module,prefix="case")
    reportdir = os.path.join('report','test_'+time.strftime("%Y-%m-%d_%H-%M-%S"))
    runner = HTMLTestRunner(log=True,verbosity=2,output=reportdir,title='Test Report',description='htmlTestReport',report_name='Test_Report.html')
    runner.run(suite3)

–test.py执行结果如下:
在这里插入图片描述
在这里插入图片描述

unittest断言

在这里插入图片描述

异常捕捉与错误截图

待完善

unittest组成部分理解

1>整理流程理解:写好的TestCase由TestLoader加载到TestSuite,然后由TextTestRunner来运行TestSuite,运行结果保存在TextTestResult中

参考资料

1.https://blog.csdn.net/qq_41437305/article/details/96368903
2.https://blog.csdn.net/fengguangke/category_7941105.html
3.unittest官方文档:https://docs.python.org/zh-cn/3.9/library/unittest.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值