Unittest框架

一、插件安装及部署

谷歌驱动:chromedriver.storage.googleapis.com/index.html

                    谷歌版本112以上Chrome for Testing availability (googlechromelabs.github.io)icon-default.png?t=N7T8https://googlechromelabs.github.io/chrome-for-testing/

1.安装导入unittest模块

pip install unittest

安装完成后可能调用时会存在调用报错的情况,解决方法如下:

file ---> setting ---> Project: ---> Python Interpreter ---> 右边小齿轮 ---> show all ---> 点击加号 ---> Virtualenv Environment ---> 选择New environment ---> Base interpreter选择安装的python.exe

报错是因为cmd安装的在安装python的目录中,新建的项目的vanv中无法使用,可单独在对应项目中的Terminal中采用相同的安装命令安装即可,  是单独拥有的,不会影响cmd已安装的

二、命名规则

1.新建类

必须要继承unittest模块的 unittest.TestCase

class TestCrm(unittest.TestCase):

2.方法测试用例必须以 test_开头

def test_case1(self):

具体示例(Unittest_test.py):

import unittest


class TestCrm(unittest.TestCase):  # 新建类,必须继承unittest.TestCase
    
    def test_case1(self):
        print('第一个测试用例')

 三、运行

1.命令行的形式及对应运行参数

命令行的形式需在下方打印台下选择Terminal

进入对应文件夹 如:cd UnitTest_demo

主要命令为:

python -m unittest

对应参数有:1.接.py文件  2.接类名  3.接方法测试用例   4.添加参数

1.接.py文件

python -m unittest Unittest_test.py

运行文件(Unittest_test.py)下所有方法测试用例

2.接类名

python -m unittest Unittest_test.TestCrm

运行类(TestCrm)下所有方法测试用例

3.接方法测试用例 

python -m unittest Unittest_test.TestCrm.test_case1

运行指定方法测试用例

运行结果:

第一个测试用例
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

4.1.添加参数    -v

python -m unittest -v unittest_test.py

打印详细的结果,展示是在哪个类哪个方法里的运行结果

运行结果:
test_case1 (Unittest_test.TestCrm) ... 第一个测试用例

更多参数配置参考: unittest --- 单元测试框架 — Python 3.11.8 文档 的命令行接口

2.main方法:unittest.main()

import unittest


class TestCrm(unittest.TestCase):  # 新建类,必须继承unittest.TestCase
    
    def test_case1(self):
        print('第一个测试用例')


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

运行结果:

Ran 1 test in 0.008s

OK

Process finished with exit code 0

第一个测试用例

3.main方法存在的缺点

在使用main方法运行时,除了unittest.main() 被执行,其余语句未被执行

import unittest


class TestCrm(unittest.TestCase):  # 新建类,必须继承unittest.TestCase

    def test_case1(self):
        print('第一个测试用例')


if __name__ == '__main__':
    a = 10
    print(a)
    unittest.main()

运行结果:

Ran 1 test in 0.008s

OK

Process finished with exit code 0

第一个测试用例

由以上例子可知,除了unittest.main() 被执行,其余语句均未被执行

3.1.缺点产生原因

unittest是单元测试框架,__name__ == '__main__'自己运行自己,所以程序自己运行时,会调用当前程序中名字以“test”开头的函数

3.2.解决main时无法运行其他语句方法

因为程序自己运行时,会调用当前程序中名字以“test”开头的函数,所以只需要程序被调用运行即可。

具体解决方法:

1、pycharm--->右上角选择文件下拉框--->点击选择Edit Configurations--->点击加号选择python--->右边Script path:选择要与运行的.py --->点击ok

2、回到对应的.py,点击右上角选择文件下拉框旁边的运行,即可解决

选择文件后点击右上角选择文件下拉框旁边的运行后的结果为

.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
10
第一个测试用例

 3.3.unittest.main()中main的TestProgram的剖析

        (ctrl+鼠标左键可查看封装信息)

def __init__(self, module='__main__', defaultTest=None, argv=None,
                    testRunner=None, testLoader=loader.defaultTestLoader,
                    exit=True, verbosity=1, failfast=None, catchbreak=None,
                    buffer=None, warnings=None, *, tb_locals=False):

 module:需要执行的方法用例的路径 默认__main__为当前所在.py的方法用例

defaultTest:测试套件  如12.2中指定的  默认为None
argv:接收外部参数
testRunner:测试运行器
testLoader:测试加载器  如:12.3中指定的   默认为None
exit:程序运行完毕后是否退出  默认为true
verbosity:1:默认,显示执行用例的总数以及全局的执行结果,显示对应标记
          <0:显示执行用例的总数以及全局的执行结果
          >1:显示执行用例的总数以及全局的执行结果,显示对应详细结果  如:第二条4.1加-V的详细信息一致

4.运行顺序

会根据方法参数用例名由前至后的每个字符的ASCII码的顺序执行(ASCII码越前的先执行)

ord('x')可看每个字符的ASCII码

5.运行结果状态

“.” 成功

“F” 失败

“E”报错,异常被抛出

“S”用例未被执行

“OK”成功

class TestCrm(unittest.TestCase):  # 新建类,必须继承unittest.TestCase

    def test_case1(self):
        raise Exception('代码应无法定位中断')
        print('第一个测试用例')

    运行结果:

Ran 1 test in 0.002s

FAILED (errors=1)

Exception: 代码应无法定位中断

file--tools--python integrated tools -- testing -- Default test runner -- 可以选择是unittest运行还是pytest运行

6.多个unittest测试类或方法测试用例组合运行

6.1.新建多个类多个方法测试用例(Unittest_test.py,Unittest_test2.py)

Unittest_test.py

import unittest


class TestCrm(unittest.TestCase):  # 新建类,必须继承unittest.TestCase

    def test_case1(self):
        print('第一个测试用例')

    def test_case2(self):
        print('第二个测试用例')

    def test_case3(self):
        print('第三个测试用例')

 Unittest_test2.py

import unittest


class TestCrm2(unittest.TestCase):  # 新建类,必须继承unittest.TestCase

    def test_case4(self):
        print('第四个测试用例')

    def test_case5(self):
        print('第五个测试用例')

    def test_case6(self):
        print('第六个测试用例')

6.2.将运行程序封装于新的  unittest_run.py

        6.2.1.使用 TestSuite 测试套件:整理测试用例,形成集合
import unittest
from UnitTest_demo.Unittest_test import TestCrm
from UnitTest_demo.Unittest_test2 import TestCrm2

if __name__ == '__main__':
    # (用套件的方式)
    # 创建一个测试套件
    tj = unittest.TestSuite()
    # 将方法用例添加到套件(注意导入)                      
    tj.addTest(TestCrm('test_case1'))              
    tj.addTest(TestCrm('test_case3'))              
    tj.addTest(TestCrm2('test_case5'))
    # 执行(注意要指定套件)
    unittest.main(defaultTest='tj')

运行结果:

...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK
第一个测试用例
第二个测试用例
第五个测试用例

        还可以一次添加多个方法测试用例  (addTests)

import unittest
from UnitTest_demo.Unittest_test import TestCrm
from UnitTest_demo.Unittest_test2 import TestCrm2

if __name__ == '__main__':
    # (用套件的方式)
    # 方法二
    # addTests可增加多个
    # 创建一个测试套件
    tj = unittest.TestSuite()
    # 将方法用例添加到套件(注意导入)
    List = [TestCrm('test_case1'), TestCrm2('test_case5')]
    tj.addTests(List)
    # 执行(注意要指定套件)
    unittest.main(defaultTest='tj')

运行结果:

..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK
第一个测试用例
第五个测试用例

Process finished with exit code 0

        6.2.2.使用TestLoader 测试加载器:加载测试用例或测试用例套件
import unittest

if __name__ == '__main__':
    # (用测试加载器的方式)
    # zdhtest文件夹下所有前缀带有Unittest_的py
    tj = unittest.defaultTestLoader.discover('UnitTest_demo', pattern='Unittest_*.py')
    unittest.main(defaultTest='tj')

运行结果:

......
----------------------------------------------------------------------
Ran 6 tests in 0.001s

OK
第一个测试用例
第二个测试用例
第三个测试用例
第四个测试用例
第五个测试用例
第六个测试用例

Process finished with exit code 0

四、夹具

1.测试用例夹具:

每个用例执行前后先执行(不需要每个用例都加,一个类加一次即可)

setUp/tearDown

import unittest


class TestCrm(unittest.TestCase):  # 新建类,必须继承unittest.TestCase
    def setUp(self) -> None:
        print('方法用例运行前我先运行')

    def tearDown(self) -> None:
        print('方法用例运行后我会运行')

    def test_case1(self):
        print('第一个测试用例')

    def test_case2(self):
        print('第二个测试用例')


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

运行结果:

Ran 2 tests in 0.002s

OK
方法用例运行前我先运行
第一个测试用例
方法用例运行后我会运行
方法用例运行前我先运行
第二个测试用例
方法用例运行后我会运行

Process finished with exit code 0

2.类夹具:

每个类执行前后先执行(一个class中添加一次)

注意:前后需要加注解@classmethod

setUpClass/tearDownClass

import unittest


class TestCrm(unittest.TestCase):  # 新建类,必须继承unittest.TestCase

    @classmethod
    def setUpClass(cls) -> None:
        print('类运行前我先运行')

    @classmethod
    def tearDownClass(cls) -> None:
        print('类运行后我会运行')

    def setUp(self) -> None:
        print('方法用例运行前我先运行')

    def tearDown(self) -> None:
        print('方法用例运行后我会运行')

    def test_case1(self):
        print('第一个测试用例')

    def test_case2(self):
        print('第二个测试用例')


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

运行结果:

类运行前我先运行
Ran 2 tests in 0.002s

OK
方法用例运行前我先运行
第一个测试用例
方法用例运行后我会运行
方法用例运行前我先运行
第二个测试用例
方法用例运行后我会运行
类运行后我会运行

3.模块夹具

每个模块执行前后先执行(一个模块需要添加一次即可)

setUpModule/tearDownModule

4.将夹具封装

为了解决多个py或类中需要添加夹具造成代码冗余,可将夹具单独封装,并在测试用例类中进行调用,对此  新增 JiaJv.py

JiaJv.py

import unittest


class Jiajv(unittest.TestCase):

    def setUp(self) -> None:
        print('每个方法用例执行前都会运行一次')

    def tearDown(self) -> None:
        print('每个方法用例执行后都会运行一次')

    # 注意:class夹具前要加注解@classmethod
    @classmethod
    def setUpClass(cls) -> None:
        print('每个class类执行前都会运行一次')

    @classmethod
    def tearDownClass(cls) -> None:
        print('每个class类执行后都会运行一次')

封装好了以后,每个测试用例的类直接调用即可。 示例如下:

import unittest
from UnitTest_demo.JiaJv import Jiajv


class TestCrm(Jiajv):  # 新建类,必须继承unittest.TestCase

    def test_case1(self):
        print('第一个测试用例')

    def test_case2(self):
        print('第二个测试用例')

    def test_case3(self):
        print('第三个测试用例')


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

 运行结果:

每个class类执行前都会运行一次
每个方法用例执行前都会运行一次
第一个测试用例
每个方法用例执行后都会运行一次
每个方法用例执行前都会运行一次
第二个测试用例
每个方法用例执行后都会运行一次
每个方法用例执行前都会运行一次
第三个测试用例
每个方法用例执行后都会运行一次
每个class类执行后都会运行一次


Ran 3 tests in 0.014s

OK

Process finished with exit code 0

注意事项:

1.注意要导入封装文件

from UnitTest_demo.JiaJv import Jiajv

2.原本继承 unittest.TestCase 的类改为继承 Jiajv

class TestCrm(Jiajv):

可能会有疑问:那 unittest.TestCase 咋继承?  

解答:因为JiaJv.py的 Jiajv 已继承了 unittest.TestCase ,所以在测试用例类继承了 Jiajv 后,将映射的间接继承了 unittest.TestCase,所以只需要继承Jiajv即可

五、跳过方法测试用例

由于部分场景的需要,可能会出现需要跳过部分测试用例的情况。对此可采用以下方法

1、@unittest.skip(reason="")        无任何判断,直接跳过

2、@unittest.skipIf(a==10,reason="")        判断“a==10”如果为 true 则跳过

3、@unittest.skipUnless(a==10,reason="")        判断“a==10”如果为 flase 则跳过

                reason为跳过的原因,原因会打印于控制台

示例如下:

import unittest


class TestCrm(unittest.TestCase):  # 新建类,必须继承unittest.TestCase
    a = 100

    @unittest.skip(reason="这个用例需保持跳过")
    def test_case1(self):
        print('第一个测试用例')

    @unittest.skipUnless(a == 10, reason="当程序未运行到第十次的时候均需要跳过")  # a == 10为false  所以会跳过此用例
    def test_case2(self):
        print('第二个测试用例')

    @unittest.skipIf(a == 10, reason="当程序运行第十次的时候需要跳过")  # a == 10不为true  所以不会跳过此用例
    def test_case3(self):
        print('第三个测试用例')


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

 运行结果:

Ran 3 tests in 0.002s

OK (skipped=2)


Skipped: 这个用例需保持跳过

Skipped: 当程序运行第十次的时候需要跳过
第三个测试用例

Process finished with exit code 0

六、断言

unittest常用断言如下:(断言函数是内嵌于unittest框架)

1、assertEqual(a, b)                判断a==b是否为true

2、assertNotEqual(a, b)           判断a==b是否为flase

3、assertIn(a, b)                       判断a的字段在b中存在为true

4、assertNotIn(a, b)                 判断a的字段在b中存在为flase

5、assertTrue(a==b)                判断a==b为true

6、assertFlase(a==b)               判断a==b为flase

7、assertIsNone(a)                   判断a为None是true

8、assertIsNotNone(a)              判断a为None是flase

具体示例:

def test_case5(self):
    print('第五个测试用例')
    self.assertEqual(a, b)

七、测试报告

1.text形式

采用 unittest.TextTestRunner() 可添加 verbosity=  如:unittest.TextTestRunner(verbosity=2)

verbosity可以设置不同的级别

import unittest

if __name__ == '__main__':

    # UnitTest_demo文件夹下所有前缀带有Unittest_的py
    tj = unittest.defaultTestLoader.discover('UnitTest_demo', pattern='Unittest_*.py')

    # 输出报告
    yx = unittest.TextTestRunner()
    yx.run(tj)  # tj可以使用套件也可使用加载

报告会以第二条第5点的形式展示

添加verbosity级别后会以第二条第1点的4.1的形式展示

2.html形式

先pip或者下载HTMLTestRunner.py 放到python路径的Lib文件夹下

import unittest
from HTMLTestRunner import HTMLTestRunner

if __name__ == '__main__':

    # UnitTest_demo文件夹下所有前缀带有Unittest_的py
    tj = unittest.defaultTestLoader.discover('UnitTest_demo', pattern='Unittest_*.py')

    # 报告存放位置
    file = open('./zdhtest/report.html', 'wb')  # wb可读写
    # 输出报告(stream:生成的文件存放位置 title:测试报告标题  description:报告的描述 )
    yx = HTMLTestRunner(stream=file, title='测试报告', description='执行情况如下:')
    yx.run(tj)  # tj可以使用套件也可使用加载

  • 19
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值