淘先锋技术网

首页 1 2 3 4 5 6 7
选对一款好用的框架,实现自动化的时候会事半功倍,当然每一款框架都有其优势和不足,适合自己的才是最好的,在前文中已经写过Unittest框架使用的文章,感觉整体风格统一、结构完整,对于初学者更容易理解;本文所讲的pytest框架也是python的一种单元测试框架,使用起来更简洁,效率更高,感觉更有python的风格。

一、pytest简介

pytest是python的一种单元测试框架,与python自带的unittest测试框架类似,非常容易上手,入门简单,文档丰富,文档中有很多实例可以参考:

【视频教程:https://www.bilibili.com/video/BV1hT411U7sC/?spm_id_from=333.999.0.0

支持单元测试

支持功能测试

支持参数化

支持跳过用例

支持标记失败用例

支持重复执行失败的用例

兼容nose, unittest编写的测试用例

具有很多第三方插件,方便扩展

支持持续集成工具集成

等等

二、pytest安装

1、pip安装

在python中一般默认安装了pip工具,如果没有,可以通过easy_install命令来安装。

easy_install pip

为了保证后面模块的正常安装,如果不是最新的版本可以使用如下命令把pip升级一下:

pip install --upgrade pip

然后使用pip命令去安装第三方的模块就非常方便了。

安裝:pip install PackageName
指定版本安裝:pip install PackageName==xx.xx
更新:pip install -U PackageName
移除:pip uninstall PackageName

2、使用requirements.txt安装

提前准备一个requirements.txt文件,里面填写需要的依赖包及其精确版本号,然后统一进行一次性安装。

1)创建一个requirements.txt文件,并填入如下数据

pytest==7.1.2
selenium==4.1.3
PyMySQL==1.0.2

2)运行该txt文件并完成三个模块的安装

pip install -r e:\requirements.txt

三、使用pytest设计单元测试用例

使用pytest设计单元测试用例,有三个基本的要求。

文件名必须以test_开头

测试类必须以Test开头,并且不能有 init 方法

测试方法必须以test_开头

1、创建单元测试用例文件

在vscode、pycharm等IDE工具中创建一个以test_开头的py文件。

2、创建单元测试用例

'''
@功能 : pytest单元测试用例
@作者 : 北凡老师 
@csdn : 测试架构师北凡
'''
# 导入pytest模块
import pytest

#  单独的测试用例方法创建
def  test_case1():
    print("aaaa")

# 以类的形式创建单元测试用例,类名Test_开头
class Test_demo2():
    # 测试用例方法以test_开头
    def test_case02(self):
        print("bbbbb")

    def test_case03(self):
        print("bbbbb")
        assert 12==12

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

3、添加断言

assert关键字后面可以接一个表达式,只要表达式的最终结果为True,那么断言通过,用例执行成功,否则用例执行失败。

assert xx:判断xx为真
assert not xx:判断xx不为真
assert a in b:判断b包含a
assert a == b:判断a等于b
assert a !=b:判断a不等于b

如果是预期要抛出异常的情况,pytest也有专门的断言方式pytest.raises(),比如预期除数为0会抛出异常。

pytest.raises 作为上下文管理器,当其管理的执行代码抛出我们指定类型的异常时,可以异常捕获为一个异常对象,不会报错,继续执行后续代码

pytest.raises只会捕获指定的异常类型,遇到其他类型异常或者没有报错,都会直接报错造成用例执行失败。

def  test_division(self):
    with pytest.raises(ZeroDivisionError) as z:
        a = 1/0
    assert z.type == ZeroDivisionError

四、单元测试用例执行

最基本的pytest单元测试用例的执行方式是pytest.main(),main()函数是单元测试用例的执行入口,它的参数是可以放在一个列表中的。

if __name__ == "__main__":
    # 默认加载配置文件中的参数
    pytest.main(["-s"])

1、main()方法的常见参数

-s: 显示程序中的print/logging等内容,输出到控制台

-v: 丰富信息模式, 输出更详细的用例执行信息

-q: 安静模式, 不输出环境信息

-x: 出现一条测试用例失败就退出测试

-k:可以使用and、not、or等逻辑运算符,匹配范围(文件名、类名、函数名)

使用格式为:pytest.main(["-s","-v","-q","-x","-k xxx"]),其含义等同于下面的语法。

# 执行具体的某一测试文件
pytest 脚本名称.py

# 执行所有的测试文件
pytest -sv

# 执行指定包或者文件夹下面的所有文件
pytest -sv 包名或文件夹名

# 执行测试用例名称包含phone的所有用例
pytest -k phone test_demo.py

# 执行测试用例名称 不包含phone的所有用例
pytest -s -k "not phone" test_demo.py

# 执行测试用例名称包含 phone 或 login 的所有用例
pytest -s -k "phone or login" test_demo.py

# 运行.py模块里面,测试类里面的某个方法
pytest test_demo.py::TestClass::test_one

2、常见的案例

1)运行所有用例,以test_开始的用例

import pytest
def test_one():
	pass
	
if __name__ == '__main__':
    pytest.main()

2)运行指定目录的用例

import pytest
def test_one():
	pass
	
if __name__ == '__main__':
    pytest.main(["./testcase/product"])

3)运行指定py的用例

import pytest
def test_one():
	pass
	
if __name__ == '__main__':
    pytest.main(["./testcase/product/test_add_product.py"])

4)运行指定py的测试类用例

python
import pytest
def test_one():
	pass
	
if __name__ == '__main__':
    pytest.main(["./testcase/product/test_add_product.py::TestProduct"])

5)运行指定py的测试类中的用例

import pytest
def test_one():
	pass
	
if __name__ == '__main__':
    pytest.main(["./testcase/product/test_add_product.py::TestProduct::test_add_01"])

3、用例执行状态

用例执行完成后,每条用例都有自己的状态,常见的状态有:

passed:测试通过,一般使用 . 来表示

failed:断言失败,一般使用 F 来表示

error:代码错误,一般使用 E 来表示

4、测试用例执行的其他用法

pytest xx.py::test_min:::字符后提供器名称来运行特定功能(参数化的类名、函数名、参数,需要一级一级的获取)

pytest -m smoke:标记可用于测试进行分组,然后使用pytest -m运行一组标记@pytest.mark.smoke的测试

pytest --pyargs pkg.testing:从包里面运行,将导入pkg.testing并使用其文件系统位置来查找和运行测试

- -maxfail=num:用例错误个数达到指定数量时,停止测试

pytest -h:帮助

- -junit-xml=path:输出xml文件格式,在与jenkins做集成时使用

- -pastebin=all:all , failed, passed 筛选某一部分

五、pytest的其他用法

1、pytest常用的Fixture方法

setup():每个测试方法执行之前会执行

teardown():每个测试方法执行之后会执行

setup_class():在每个类执行之前会执行

teardown_class():在每个类执行后会执行

class TestFixture():
    @staticmethod
    def setup_class():
        print("整个测试类开始前只执行一次setup_class")

    @staticmethod
    def teardown_class():
        print("整个测试类结束后只执行一次teardown_class")

    def setup():
        print("类里面的每个用例执行前都会执行setup")

    def teardown():
        print("类里面的每个用例执行后都会执行teardown")

    def test_login_success(self):
        print("登录成功")
        assert True

    def test_login_error(self):
        print("登录失败")
        assert False

if __name__=="__main__":
     pytest.main(["-s","-k Fixture"])

执行结果如下:

2、忽略测试用例执行

@pytest.mark.skip(reason="")无条件跳过执行测试用例,reason表示跳过的原因,会在执行结果中打印

@pytest.mark.skipif(condition, reason=""):希望有条件地跳过某些测试用例, condition为True时才会跳过用例

import random
from tkinter.tix import MAIN
from black import main
import pytest


class TestSkip():
    def test_one(self):
        print("第一个测试用例!")

    @pytest.mark.skip(reason="无条件跳过")
    def test_two(self):
        print("第二个测试用例!")

    @pytest.mark.skipif(1 == random.randint(0, 1), reason="当随机数等于1时跳过")
    def test_three(self):
        print("第三个测试用例!")

    def test_four(self):
        print("第四个测试用例!")


if __name__=="__main__":
    pytest.main(["-s","-k Skip"])

执行结果为:

3、参数化的用法

编写测试用例时,多个测试用例操作步骤一样,只有测试数据及期望结果可能不一样时,此时使用参数化的方式,可以大大减少冗余代码。

语法如下:

@pytest.mark.parametrize(参数1,参数2,[[参数1值1,参数2值1],[参数1值2,参数2值2]..])deftest_xx(self,参数1,参数2)

data:用于参数化的测试用例数据,值为列表,数据可以是列表或元组

import pytest
class TestParameters():
    data = [
        {"username": "张三", "password": "123", "expect_code": 200},
        {"username": "李四", "password": "321", "expect_code": 400},
        {"username": "王五", "password": "123456", "expect_code": 400}
    ]

    @pytest.mark.parametrize("account", data)
    def test_login(self, account):
        #print(account)
        assert 200 == account["expect_code"]


if __name__=="__main__":
    pytest.main(["-s","-k Para"])

执行结果为:

六、测试报告输出

执行单元测试或者自动化测试,都希望能输出一个可视化的html格式报告,下面我们就介绍与pytest兼容性比较好、而且非常方便使用的模块pytest-html和allure,非常方便生成html格式的报告。

1、pytest-html模块的使用

pytest-html是pytest的一个插件,可以生成html格式报告。

1)安装pytest-html

安装指令:pip install pytest-html

默认安装的pytest-html的版本是3.1.1,据说有兼容性问题。

我们可以指定版本安装:pip install pytest-html==2.1.1

2)使用pytest-html运行测试单元测试用例并生成报告

# test_demo5.py为符合pytest单元测试用例的文件
py.test test_demo5.py --html=./aaaaa.html

3)查看生成的报告

在vscode中执行后的控制台输出为:

找到当前工程目录下的aaaa.html文件,并使用chrome浏览器打开:

2、allure的使用

Allure是一款轻量级并且非常灵活的开源测试报告框架,它支持pytest等很多测试框架,并且简单易用,易于与其他工具集成,是帮助我们快速生成炫酷的自动化测试报告的不二之选。

1)下载、安装

可以从Github上下载:

地址:https://github.com/allure-framework/allure2/releases

下载后其中allure-2.18.1.zip,直接解压到本地某盘符下即可。

将上图的bin目录,设置到系统环境变量path中。

在cmd下运行:allue --version,出现下图,即为安装成功。、

2)安装Allure Pytest Plugin

allure-pytest是Pytest的一个插件,通过它我们可以生成Allure所需要的用于生成测试报告的数据。

安装allure-pytest插件,在cmd下操作输入命令:

pip install -U allure-pytest

3) pytest集合allure生成测试报告

在vscode/pycharm中,使用pytest规则设计单元测试用例。

执行方式1:在执行文件中

if __name__ == "__main__":
    pytest.main(["--alluredir","./test_result"])
    os.system("allure generate ./test_result -o ./test_report --clean")

执行方式2:测试用例文件所在的目录下命令行分别运行

pytest --alluredir  ./test_resul
allure generate ./test_result -o ./test_report --clean

–alluredir参数的作用是指出生成的报告文件夹, result下放着生成报告的基础数据文件

通过第二条命令将./result/目录下的测试数据生成测试报告到./test_report目录下

4) 查看该index.html文件

在pycharm中,是可以直接打开该文件的,可以正常显示报告内容。

但是在vscode和资源管理器中,打开该文件后是显示Loading和404页面的。

这主要是因为该index.html文件需要allure命令渲染之后打开才能展示效果。

我们可以使用 allure open来渲染打开测试报告文件。

在test_report和test_result同级目录下,执行cmd命令或者vscode的控制台命令行:

allure open test_report/

会自动打开Chrome浏览器,并渲染打开index.html文件,展示测试结果报告。

【软件测试到测试开发全测试生涯学习路线】:【以下路线图太详细了只能展开部分,具体的可以在文章末尾扫描小卡片备注000领取哦】

1:自动化测试进阶系列:

2:全栈性能测试,监控以及调优

3:全栈测试开发平台实战

4:全栈安全测试渗透测试

5:devops持续集成部署

6:全栈接口测试工具进阶

7:跨平台自动化测试工具

8:大厂简历,真题,录音

9:全栈系列课企业项目实战

学完这整套教程,拿下大厂30k到50k不是问题

总结:下方是作者从功能测试到自动化测试拿到年薪34w,花费三年打造的软件测试到测试开发全职业生涯资料包,有需要的话可以点击文章末尾的小卡片备注000领取哈