ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

unittest框架基本使用

2022-07-03 19:00:26  阅读:180  来源: 互联网

标签:基本 框架 unittest ddt print test data def


一.命名要求

unittest对.py文件类没有命名要求,只需要函数是以test为开头的就可以

二.运行顺序

不同于pytest(从上往下)的是,unittest运行顺序是按照从0-9,A-Z,a-z的先后顺序运行的

三.五大组件

1.testcase(测试用例)

(1)运行时可点击类/函数左侧绿色(当前类继承unittest.TestCase才会出现)的开关。点击函

         数左侧的表示运行当前函数,点击类左侧的表示运行当前类下的所有case

(2)运行时可将光标停留在类/函数冒号右侧,鼠标右击点击run运行。光标停留在类名右侧表示

         运行当前类下所有case,停留在具体函数名右侧,表示运行当前函数

(3)运行时可在main方法中unittest.main()来运行,运行顺序按照:0-9,A-Z,a-z先后运行

class unittest_demo(unittest.TestCase):
    def test_one(self):
        print("我是one")

    def test_two(self):
        print("我是two")

2.testfixture(测试固件)

unittest中固件有两种。setup和teardown每个函数运行前后会各运行一次。setupclass和teardownclass

表示每个类运行前后会各运行一次。

(1)setup和teardown

这里set_tear继承了TestCase,然后又重写了setup和teardown两个前后置方法。我们在做自动化的时候

可用做前置准备工作和后置结束阶段

class set_tear(unittest.TestCase):

    def setUp(self) -> None:
        print("进入www.baidu.com页面")

    def tearDown(self) -> None:
        print("操作完毕,关闭浏览器页面")

(2)setup_class和teardown_class

这个用法和上面相同,重写时需要加上@classmethod,因为setupclass,和tearDownClass在testcase类

中为类方法

class set_tear(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        print("进入www.baidu.com页面")

    @classmethod
    def tearDownClass(cls) -> None:
        print("操作完毕,关闭浏览器页面")

3.testsuite(测试套件)

测试套件的作用简单理解就是把你想要运行的case加到套件里面去,然后通过运行器去运行。这样可以选择性

的运行case,可以改变case运行的顺序。

(1)指定函数运行

运行的顺序是按照你加入套件的先后顺序来运行的

import unittest


class unittest_suite(unittest.TestCase):
    def test_01(self):
        print("test_01")

    def test_02(self):
        print("test_02")

    def test_03(self):
        print("test_03")


suite = unittest.TestSuite()  # 创建一个套件
suite.addTest(unittest_suite("test_01"))  # 添加case到套件中
suite.addTest(unittest_suite("test_02"))
suite.addTest(unittest_suite("test_03"))

这里也可以使用addtests方法添加一个数组到套件中

suite = unittest.TestSuite()  # 创建一个套件
caseList = [unittest_suite("test_01"), unittest_suite("test_01"), unittest_suite("test_01")]
suite.addTests(caseList)

(2)指定类运行

import unittest


class unittest_suite(unittest.TestCase):
    def test_01(self):
        print("test_01")

    def test_02(self):
        print("test_02")

    def test_03(self):
        print("test_03")


suite = unittest.TestSuite()  # 创建一个套件
load = unittest.TestLoader()  # 创建一个加载器
loadClass = load.loadTestsFromTestCase(unittest_suite)  # 调用加载类的方法并传入一个类
suite.addTest(loadClass)  # 添加到套件中

运行顺序按照原有类里面的顺序进行运行

(3)指定模块(.py)运行

import testcase.demo_02   #导入要运行的.py


suite = unittest.TestSuite()  # 创建一个套件
load = unittest.TestLoader()  # 创建一个加载器
loadClass = load.loadTestsFromModule(testcase.demo_02)  #调用加载模块的方法
suite.addTest(loadClass)
suite.countTestCases()#统计case个数

(4)指定路径运行

suite = unittest.TestSuite()  # 创建一个套件
load = unittest.TestLoader()  # 创建一个加载器
suite.addTest(load.discover("./testcase", pattern="*02.py")) #调用discover方法指定路径运行

pattern中匹配符*表示通配符,可写成test*.py表示以test为开头,*xx.py表示以xx为结尾的都满足。

需要注意的是这里的路径不能具体到某个.py模块,模块的匹配规则必须写在pattern中

4.testrunner(运行器)

一般与testsuite一起用,来运行套件的

if __name__ == '__main__':
    runner = unittest.TextTestRunner()  # 创建个运行器
    runner.run(suite)  # suite为套件集

5.testreport(测试报告)

这里不多介绍了,感兴趣的可以学习allure:https://www.cnblogs.com/lihongtaoya/p/15778263.html

四.spik用法

1.spik

表示跳过该条case不执行

class unittest_suite(unittest.TestCase):
    def test_01(self):
        print("test_01")

    @unittest.skip
    def test_02(self):
        print("test_02")

    def test_03(self):
        print("test_03")

2.spikif()

判断条件4>2,为true时不运行,打印标签reason。为false运行该条case

class unittest_suite(unittest.TestCase):
    def test_01(self):
        print("test_01")

    @unittest.skipIf(4 > 2, reason="猪头")
    def test_02(self):
        print("test_02")

    def test_03(self):
        print("test_03")

3.skipUnless()

和skipif()效果相反,判断条件为true运行,为false不运行

class unittest_suite(unittest.TestCase):
    def test_01(self):
        print("test_01")

    @unittest.skipUnless(4 > 2, reason="猪头")
    def test_02(self):
        print("test_02")

    def test_03(self):
        print("test_03")

五.ddt数据驱动(第三方的需要pip install ddt下载)

python装饰器可参考:https://www.cnblogs.com/lihongtaoya/p/16368111.html

unittest中@ddt为类装饰器,其它三个都是函数装饰器。ddt

1.@ddt

import unittest

from ddt import ddt


@ddt
class unittest_ddt(unittest.TestCase):
    def testOne(self):
        pass

@ddt作用于类,表示当前类使用ddt框架

2.@data()

@data()主要用来传值的(可传int,str,list,set,dict,tuple)

(1)传单个int/str值和多个int/str值

import unittest

from ddt import ddt, data


@ddt
class unittest_ddt(unittest.TestCase):
    #@data(1, 2, 3)
    @data("1","2","3")
    def testOne(self, a):
        print(a)

这里的a是用于接收传递过来的参数,打印结果为1,2,3

(2)传单个set/list/tuple/

import unittest

from ddt import ddt, data


@ddt
class unittest_ddt(unittest.TestCase):
    # @data((1,2,3))
   # @data({1,2,3}) @data([1, 2, 3]) # 传递单个list def testOne(self, a): print(a)



运行结果:[1, 2, 3]||(1, 2, 3)

以上可以看出的是传参时会把[1, 2, 3]和(1, 2, 3)当作一个整体传给a,那么如果我们想要单个值分别

传递给a。只需要在[1,2,3]前加上一个*号即可

@ddt
class unittest_ddt(unittest.TestCase):
    # @data((1,2,3))
    @data(*[1, 2, 3])  # 传递单个list
    def testOne(self, a):
        print(a)

运行结果:1 2 3

这里*的作用就是去掉最外层的壳,既:[ ]和()

 

3.@unpack()

当传递的参数含有多个值的时候,需要用的unpack来进行解包

@unpack()主要用来解包(去外壳)

(1)传递多个list/set/tuple

@ddt
class unittest_ddt(unittest.TestCase):
    # @data((1,2,3))
    # @data(*[1, 2, 3])  # 传递单个list
    @data((1,2,3),(4,5,6))
    @unpack
    def testOne(self, a,b,c):
        print(a)

打印结果:1 4

这里需要注意的是接收数据的参数个数(a,b,c)要和list/set/tuple中的数量相等

(2)dict类型

@ddt
class unittest_ddt(unittest.TestCase):
    # @data((1,2,3))
    # @data(*[1, 2, 3])  # 传递单个list
    @data({"name": "liming", "age": 123}, {"name": "lihua", "age": 123})
    @unpack
    def testOne(self, name, age):
        print(name)


打印结果:liming lihua

传递dict数据类型的时候要保证接收数据的变量(name,age)要和dict中的key值一模一样(数量和key值)

(3)传递嵌套的类型结构

import unittest

from ddt import ddt, data, unpack

datalist = [
    {
        "name": "liming",
        "age": 12
    }, {
        "name": "lihua",
        "age": 13
    },{
        "name": "lisan",
        "age": 18
    }
]


@ddt
class unittest_ddt(unittest.TestCase):
    @data(*datalist)  # 加*后数据结构变成:{},{}
    @unpack  # 解包去外壳
    def testOne(self, name, age):
        print(name)

4.@file_data()

当yaml和json中的数据结构为[{},{},{}]时,@file_data()的作用就相当于@data()+@unpack()

@file_data()可直接读取yaml和json文件

(1)首先我们先创建一个yaml文件

-
      username: liming
      password: 123456
-
      username: lifei
      password: 2

(2)在@file_data()中直接引用yaml文件即可

from ddt import ddt, data, unpack, file_data


@ddt
class unittest_ddt(unittest.TestCase):
    @file_data("../params/demo_01.yaml")
    def testOne(self,username,password):
        print(username)

这里username和password也是要和yaml中的key值(数量)相等。json用法也是一样,这里不多介绍了。

5.csv做数据驱动

创建一个csv文件

liming,123
lifei,1234

导入csv,reader()方法读取后加入list里

with open("../params/demo_01.csv", mode="r", encoding="utf8")as a:
    da=csv.reader(a)
    data_list=[]
    for i in da:
        data_list.append(i)

当前data_list打印结果:[['liming', '123'], ['lifei', '1234']],然后再用data和unpack装饰器即可

 

六.实例

下一章再写吧,

 

 

 

 

 

 

 

 

注:网上已经一大堆教程了,不要转载

标签:基本,框架,unittest,ddt,print,test,data,def
来源: https://www.cnblogs.com/lihongtaoya/p/16391001.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有