python-pytest使用(1)

python-pytest使用(1)

原创:George555     公众号: 测试江湖路  

(扫码加公众号,看更多相关内容)

一、安装:

    1、基础包安装:pip install pytest

    2、引用:import pytest #pip安装后,会在python安装目录的\Lib\site-packages下安装pytest.py文件,这样在使用时直接import pytest就行了

 

二、案例引入,先看个示例:

"""文件名:test_001.py"""def fun(a):    return a+1def test_001():    assert fun(2)==3def test_002():    assert fun(2)==4

运行:在cmd命令框中输入:pytest test_001.py

执行结果:1个成功,1个失败

python-pytest使用(1)_第1张图片

    说明:测试文件后边的字母代表含义汇总:

        “.” 代表测试通过,

        F(Fail):失败

        E(error):错误

        s(skip):跳过

        X(xpass):预期失败但是成功x,

        xfail:预期失败执行也失败了.

三、理论部分

    1、文件、包、类、函数编写规则:

        文件或(包):必须以test_开头 或以_test结尾

        类:必须以Test开头,且不含init方法

        函数/方法:必须以test_开头

    2.断言方法:assert

        assert aa :判断aa为真

        assert not aa :判断aa不为真

        assert a in b :判断b包含a

        assert a == b :判断a等于b

        assert a != b :判断a不等于b

        另外:如果断言后有错误的,想给出友好提示可以用下面方式:

    assert 5 == add(4,4),"add()方法结果不等于5,而等于{0}".format(add(4,4))

    3.相关使用

        3.1 重复执行失败用例:pip install pytest-rerunfailures

            使用示例:pytest test.py --reruns 3

        3.2 测试报告: pip install pytest-html

            使用示例:pytest test.py --html=./testreport.html

            执行后生成如下报告:

python-pytest使用(1)_第2张图片

 

        3.3 顺序随机测试:pip install pytest-randomly

        3.4 分布式并发测试用例集:

            pip install pytest-xdist 或  pip install pytest-parallel  

       备注:pytest-parallel支持python3.6及以上版本,如果是想做多进程并发的需要在linux平台或mac上做,如果是做多线程的可以再windows平台做

    –workers (optional)  * :多进程运行需要加此参数,  *是进程数。默认为1。

    –tests-per-worker (optional)  * :多线程运行, *是每个worker运行的最大并发线程数。默认为1

    使用示例:

pytest test.py --workers 3:3个进程运行pytest test.py --tests-per-worker 4:4个线程运行pytest test.py --workers 2 --tests-per-worker 4:2个进程并行,且每个进程最多4个线程运行,即总共最多8个线程运行。

     见官方文档:https://pypi.org/project/pytest-parallel/

        3.5 出错立即返回:pip install pytest-instafail

        3.6 集成jenkins的junit报告: 不用安装pytest已经集成了

            使用命令:pytest --junitxml=path

            使用示例:

pytest test.py --reruns 3 --html=./testreport.html --junitxml=xmlreport.xml

        此时则执行完用例后,在本地目录生成testreport.html的测试报告,和xmlreport.xml的junit格式报告在jenkins中可调用展示。

        3.7 参数化:

            A.fixture中无参数,使用示例:

            @pytest.fixture()

            代码示例:

import pytestdef fun():    return "hello world"@pytest.fixture()   #添加fixture后,执行inty方法就是执行fun()方法def inty():    return "connect to "+fun()class TestCase():    #inty参数名必须同fixture的inty方法名相同才能传递inty的值    def test_open_baidu(self, inty):            print("============{}".format(inty))

执行后部分测试报告如下:

        B.fixture中带有参数,使用示例:

        @pytest.fixture(params=[{key11:value1,key12:value2} , {key21:value21,key22:value22}])

            代码示例:

import pytest@pytest.fixture(params=[{'userID':'00001','username':'jack'},                        {'userID':'00002','username':'mike'}])    def getdata(request): #这里的request是固定参数名    #分别打印params的字典项:{'userID': '00001', 'username': 'jack'}     #和{'userID':'00002','username':'mike'}    print("request.param======",request.param)       return request.param    #这里的request.param也是固定的class TestCase():    def test_case1(self, getdata):            print("第1个用例输出:{}".format(getdata))    def test_case2(self, getdata):        print("第2个用例输出:{}".format(getdata))

        执行后测试报告如下: 报告中用例都执行了2次,使用了params中的两个测试数据

python-pytest使用(1)_第3张图片

        备注:根据这样的例子,如果在测试中需要处理很多重复测试数据时,则这些数据就可以传入params里(可以另外写个方法读取txt/excel等文件测试数据值,以多字典列表形式返回所有测试数据),类似于unittest的DDT数据驱动方法。然后就会逐一去带入testcase里执行了

            C.测试用例方法前直接加测试数据

import pytestclass TestCase():    @pytest.mark.parametrize("getdataA",                        [{'userID':'00001','username':'jack'},                        {'userID':'00002','username':'mike'}])    def test_case1(self, getdataA):            print("第1个用例输出:{}".format(getdataA))    @pytest.mark.parametrize("getdataB",                        [{'userID':'00003','username':'tina'},                        {'userID':'00004','username':'book'}])    def test_case2(self, getdataB):        print("第2个用例输出:{}".format(getdataB))

执行后测试报告如下:

python-pytest使用(1)_第4张图片

D.测试用例方法前直接调用外部文件实现数据驱动

# -*- coding:utf-8 -*-import pytest,csvdef getCsvContents(csvFileUrl):    '''把csv格式文件转换为字典列表方法'''    with open(csvFileUrl,'r') as csv_f:        reader = csv.reader(csv_f)        fieldnames = next(reader)        csv_reader = csv.DictReader(csv_f,fieldnames=fieldnames)        kwList=[]        for row in csv_reader:            d = {}            for k, v in row.items():                d[k] = v            kwList.append(d)    return kwListclass TestCase():    @pytest.mark.parametrize("getdataA",getCsvContents('test.txt'))    def test_case1(self, getdataA):            print("第1个用例输出:{}".format(getdataA))    @pytest.mark.parametrize("getdataB",getCsvContents('test.txt'))    def test_case2(self, getdataB):        print("第2个用例输出:{}".format(getdataB))

python-pytest使用(1)_第5张图片

 

四、命令行运行

1.运行某个目录下全部用例

    pytest -q ..\pytestAllure #运行当前文件所在目录的下所有case

    即运行pytestAllure目录下所有test_*.py 或者*_test.py文件里的以Test开头的类(无__init__方法)下以test开头的方法

2.运行某py文件里的所有用例(即以Test开头的类下以test开头的方法)

    pytest test_demo1.py

3.运行包含关键词的类或方法

pytest -k Test_pytestClass1 ..\pytestAllure   #执行pytestAllure目录下Test_pytestClass1 类下的所有test开头的case​​​​​​
pytest -k Test_pytestClass1 && case11 ..\pytestAllure    #执行pytestAllure目录下Test_pytestClass1 类下的所有case名包含case11的

4.用节点id来运行  用::来标识节点追踪方式​​​​​​​

pytest test_demo1.py::Test_pytestClass1    #执行test_demo1.py文件中的Test_pytestClass1类下所有test开头的方法

    执行后提示:

====1 failed, 1 passed, 1 warnings in 0.11 seconds ====​​​​​​​

pytest test_demo1.py::Test_pytestClass1::test_case12  #执行test_demo1.py文件中的Test_pytestClass1类下的test_case12方法

执行后提示:

========== 1 failed, 1 warnings in 0.10 seconds ==========

5.怎么从包下运行所有用例

    pytest --pyargs pkg.testing

    这将导入pkg.testing并使用其文件系统位置来查找和运行测试。

6.怎么执行带@pytest.mark.errorcase的类或方法

  pytest test_demo1.py -m errorcase  #执行test_demo1.py文件中的标记为errorcase的test用例或类下全部test用例

代码:​​​​​​​

@pytest.mark.errorcasedef test_case12(self):assert 4==3,"两个数不相等"

执行后提示:

======1 failed, 1 deselected, 1 warnings in 0.10 seconds ======

7.怎么执行多个mark标记的类或方法​​​​​​​

pytest test_demo1.py -m "case12 or case13"    #执行标记为case12和case13 的
pytest test_demo1.py -m "not case13"  #不执行标记为case13的

代码:​​​​​​​

def test_case11(self):assert 3==3,"两个数相等"@pytest.mark.case12def test_case12(self):assert 4==3,"两个数不相等"@pytest.mark.case13def test_case13(self):assert 5==3,"两个数不相等"

执行后提示:

====== 2 failed, 1 deselected, 2 warnings in 0.12 seconds =====

8.怎么跳过指定类或方法

    pytest test_demo1.py

代码如下:​​​​​​​

@pytest.mark.skip  #skip可以放在类前(跳过类),也可以放在方法前(跳过方法)def test_case14(self):assert 11==3,"两个数不相等"

执行后:

==== 0 failed, 0 passed, 1 skipped, 2 warnings in 0.11 seconds ====

9.怎么重复执行失败用例​​​​​​​

pytest test_demo1.py --reruns 3 --reruns-delay 5#重复执行失败用例,且每次执行器等待5秒后再继续执行示例:pytest ..\pytestAllure --reruns 3 --reruns-delay 4

    执行后:

==== 4 failed, 2 passed, 1 skipped, 4 warnings, 12 rerun in 48.41 seconds =====

10.怎么生成html测试报告?

    pytest ..\pytestAllure   --html="testreport.html"  #执行完pytestAllure下所有用例后,当前目录下生成testreport.html的测试报告

11.怎么生成jenkins集成后可用的junit测试报告文件

pytest test_demo1.py --junitxml=junitxml.xml#执行后生成junit可用的xml报告文件

执行示例:

pytest ..\pytestAllure --reruns 3 --reruns-delay 4 --html="testreport.html" --junitxml="junitxmlreport.xml"

 

执行后:

--generated xml file: D:\workspace\pytestAllure\junitxmlreport.xml ---

--generated html file: file://D:\workspace\pytestAllure\testreport.html --

==4 failed, 2 passed, 1 skipped, 4 warnings, 12 rerun in 48.41 seconds ==

12.怎么使用python命令运行pytest

    执行:python -m pytest testdemo.py

    备注:使用python执行的,可以顺便把当前目录加入到sys.path中,即环境变量

13.pytest的退出码汇总

    根据官方说法,提供了6种,分别如下:

    Exit code 0: 所有用例执行成功后则返回0

    Exit code 1: 所有用例执行后,有部分失败则返回1

    Exit code 2: 测试执行时被用户中断

    Exit code 3: 执行测试时发生内部错误

    Exit code 4: pytest 命令行使用错误

    Exit code 5: 没有收集到测试结果

    备注:如果是要自定义退出码,则需要配合插件:pytest-custom_exit_code

14.运行用例遇到失败就停止

    pytest -X testModu.py       #遇到用例失败就停止,后面的不执行

    pytest --maxfail=2 testModu.py #遇到第2个用例失败就停止,后面的不执行

###########一个比较全面的执行命令案例:#################

pytest -v test_demo1.py -k Test_pytestClass1 -m "case12 or case13" --reruns 3 --reruns-delay 3 --html=./report.html

以最详细的信息执行test_demo1.py文件中类名Test_pytestClass1 且用例名标记为case12或case13,如果有失败则重复运行3次且每次重复运行前等待3秒再继续,最后生成report.html报告

五、测试用例前置后置处理​​​​​​

# -*- coding:utf-8 -*-'''Created on 2019年8月6日@author: George前置、后置处理所有方法归纳如下:模块预处理:setup_module        teardown_module类预处理:setup_class          teardown_class函数预处理:setup_function      teardown_function方法预处理:setup_method        teardown_method用例预处理:setup              teardown备注:pytest包会识别这些方法名文件名:test_demo7.py'''import pytestdef setup_module():    print("\n 这里是setup_module")def teardown_module():    print("这里是teardown_module")  
def setup_function():       print("这里是setup_function")def teardown_function():       print("这里是teardown_function")
def test_case1():      print("这里是test_case1")def test_case2():      print("这里是test_case2")        class Testclass():    def setup_class(self):  #类似于unittest里的@classmethod        print("这里是setup_class")    def teardown_class(self):        print("这里是teardown_class")
    def setup(self):        print("这里是setup")    def teardown(self):        print("这里是teardown")    def setup_method(self):    #这里同setup方法作用其实一样           print("这里是setup_method")    def teardown_method(self):        print("这里是teardown_method")    def test_ClassCase1(self):        print("这里是test_testClassCase1")    def test_ClassCase2(self):        print("这里是test_testClassCase1")    if __name__=="__main__":    pytest.main(["-s", "test_demo7.py"])        #备注:-s:显示用例执行结果信息;-q :只显示结果,不显示过程

备注说明:

1.这几种方法全部使用优先级顺序如下:

setup_module->setup_function->setup_class->setup_method->setup->

teardown->teardown_method->teardown_class->teardown_function->teardown_module

2.其中setup_method/teardown_method 和setup/teardown 用在一起作用是一样的

3.setup_function/teardown_function是用在类以外,而setup_method/teardown_method 用在类之内

    好了,pytest基本使用已经介绍完了,开始写测试脚本用例吧,后面会再更新一些高级使用(如:数据共享和数据作用域)


#####欢迎大家加群交流####

QQ:464314378

微信群请先加群主微信,群主会拉各位小伙伴进群,注意添加备注。


如果这些内容对你有帮助,也可以打开微信扫一扫,加关注:

你可能感兴趣的:(Pytest)