1.测试类主函数模式

pytest.main("-s  test_abc.py")
# file_name: test_abc.py
 import pytest # 引入pytest包
 def test_a(): # test开头的测试函数
     print("------->test_a")
     assert 1 # 断言成功
 def test_b():
     print("------->test_b")
     assert 0 # 断言失败
 if __name__ == '__main__':
        pytest.main("-s  test_abc.py") # 调用pytest的main函数执行测试

2.命令行模式

pytest 文件路径/测试文件名
  例如:pytest ./test_abc.py

3. 在第N个用例失败后,结束测试执行

pytest -x                    # 第01次失败,就停止测试
pytest --maxfail=2     # 出现2个失败就终止测试

4.指定测试模块

pytest test_mod.py

5.指定测试目录

pytest testing/

6.-k 匹配用例名称

通过关键字表达式过滤执行;匹配:可全名,也可以模糊

pytest -k "MyClass and not method"

这条命令会匹配文件名、类名、方法名匹配表达式的用例,这里这条命令会运行 TestMyClass.test_something, 不会执行 TestMyClass.test_method_simple

7. -m 选择对应的标签(mark标签)

标签没有注册,pytest不能识别

PytestUnknownMarkWarning: Unknown pytest.mark.shop - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/latest/mark.html
    @pytest.mark.shop

pyetst.ini配置文件内容:

[pytest]
markers =
    login: Run login case
    myShop: Run myShop case
一个:
 '-m','lesson_add'
多个:
 '-m','lesson_add or lesson_list'
排除法:
   '-m','not lesson_add '
排除法 多个:
   '-m','not (lesson_add or lesson_list)'

8.-v 节点–多层化

示例: test_lesson.py::TesLesson::test_lesson_add # 测试文件::测试类::测试方法

pytest -v  test_lesson.py::TesLesson::test_lesson_add

9.-s :显示标准输出,例如print()的语句;

10.-q :显示简洁报告;

11. 多进程运行cases

当cases量很多时,运行时间也会变的很长,如果想缩短脚本运行的时长,就可以用多进程来运行。

安装pytest-xdist:

pip install -U pytest-xdist

运行模式:其中NUM填写并发的进程数。

pytest test_se.py -n NUM

12.重试运行cases

在做接口测试时,有事会遇到503或短时的网络波动,导致case运行失败,而这并非是我们期望的结果,此时可以就可以通过重试运行cases的方式来解决。

安装pytest-rerunfailures:

pip install -U pytest-rerunfailures

运行模式:NUM填写重试的次数。

pytest test_se.py --reruns NUM

13.高阶用法

13.1.跳过测试函数

在我们自动化测试过程中,经常会遇到功能阻塞、功能未实现、环境等一系列外部因素问题导致的一些用例执行不了,这时我们就可以用到跳过skip用例,如果我们注释掉或删除掉,后面还要进行恢复操作。
跳过–skip-------相当于注释的效果
有条件的跳过–skipif–-在执行过程中会对项目的一些前置条件进行判断**
如果您希望有条件地跳过某些内容,则可以使用skipif代替。 if条件为真,跳过

根据特定的条件,不执行标识的测试函数.
 方法:
     skipif(condition, reason=None)
 参数:
     condition:跳过的条件,必传参数
     reason:标注原因,必传参数
 使用方法:
     @pytest.mark.skipif(condition, reason="xxx")
import pytest
class Test_ABC:
    def setup_class(self):
        print("------->setup_class")
    def teardown_class(self):
        print("------->teardown_class")
    def test_a(self):
        print("------->test_a")
        assert 1
    @pytest.mark.skipif(condition=2>1,reason = "跳过该函数") # 跳过测试函数test_b
    def test_b(self):
        print("------->test_b")
            assert 0
执行结果:
   test_abc.py 
   ------->setup_class
   ------->test_a #只执行了函数test_a
   .
   ------->teardown_class
       s # 跳过函数```

代码实际应用:

@pytest.mark.shop#增加标签 mark
@allure.epic('外卖项目-接口测试')
@allure.feature('店铺模块')#测试类
class TestShop:
    def setup_class(self):#使用这个类就一定会调用这个方法,只能运行一次
        #1- 登录
        self.token = Login().login({'username':'sq0777','password':'xintian'},getToken=True)
        #2- 创建一个店铺的实例
        self.shop = Shop(self.token)
    #1- 列出店铺
    #没有返回返回值的fixture
    # @pytest.mark.usefixtures('shop_xt')

    #@pytest.mark.skip(reason='下面接口后端存在问题,先跳过不执行!')#无条件跳过下面的用例执行--相当于注释--报告会显示
    @allure.story('店铺列出')#接口的名称
    @allure.title('店铺列出用例')  # 用例的标题
    @pytest.mark.shop_list# 增加标签 mark
    @pytest.mark.parametrize('inData,respData',get_excelData('我的商铺','listshopping'))
    def test_shop_list(self,inData,respData):
        #1- 调用店铺列出接口
        #店铺实例的创建必须要登录--需要一个店铺的实例---才能使用对应的方法
        #调用对应的方法
        res = self.shop.shop_list(inData)
        '''
        如果断言不是一个属性,需要多个组合判断?
        原理:assert   布尔表达式       多个条件使用and  or   
        '''
        if 'code' in respData:
            assert res['code'] == respData['code']
        else:
            assert res['error'] == respData['error']

    #2- 店铺更新
    # @pytest.mark.skipif(Login().login({'username':'sq0777','password':'123456'})['msg']!='成功',
    reason='登录失败,先跳过不执行下面的接口!')  # 条件为真,跳过下面的用例执行
    @allure.story('店铺更新')  # 接口的名称
    @allure.title('店铺更新用例')#用例的标题
    @pytest.mark.shop_update  # 增加标签 mark
    @pytest.mark.parametrize('inData,respData', get_excelData('我的商铺', 'updateshopping'))
    def test_shop_update(self,inData,respData,shop_update_init):#引入初始化方法名字
        #1- 调用店铺更新的接口
        #shop_update_init[0],shop_update_init[1]  返回值0  返回值1
        #res = self.shop.shop_update(inData,shop_update_init[0],shop_update_init[1])
        #excel测试用例数据,店铺的id,图片信息
        #用例执行步骤
        with allure.step('第1步:登录'):
            print('登录')
        with allure.step('第2步:店铺更新操作'):#计算这一步的时间--执行时间
            res = self.shop.shop_update(inData,shop_update_init[0],shop_update_init[1])
        #2- 断言
        assert res['code'] == respData['code']

13.2标记为预期失败函数

标记测试函数为失败函数
 方法:
     xfail(condition=None, reason=None, raises=None, run=True, strict=False)
 常用参数:
     condition:预期失败的条件,必传参数
     reason:失败的原因,必传参数
 使用方法:
     @pytest.mark.xfail(condition, reason="xx")
import pytest
class Test_ABC:
    def setup_class(self):
        print("------->setup_class")
    def teardown_class(self):
        print("------->teardown_class")
    def test_a(self):
        print("------->test_a")
        assert 1
    @pytest.mark.xfail(2 > 1, reason="标注为预期失败") # 标记为预期失败函数test_b
       def test_b(self):
           print("------->test_b")
          assert 0
   执行结果:
       test_abc.py 
       ------->setup_class
       ------->test_a
       .
       ------->test_b
       ------->teardown_class
       x  # 失败标记