pytest用例的执行顺序_涉及多个fixtures

Pytest执行的顺序

当pytest运行测试函数时,它会查看该测试函数中的参数,然后搜索与这些参数具有相同名称的fixture。一旦pytest找到这些对象,它就会运行这些fixture

影响执行顺序的因素

       1. fixture方法的scope:fixture的使用范围

       2. dependencies:可能会存在fixture请求了别的fixture,所以产生了依赖关系

       3. autouse:如果多个fixture,其中一个autouse=True,那么这个fixture先执行

执行顺序:

单个fixture,先执行这个fixture,再执行测试用例

多个fixture,就要确定fixture的执行顺序

       1. fixture设置了autouse=True,这个autouse的fixture函数会比请求的其他fixture都要先执行。

       2. Scope使用范围大的fixture先执行:"session"> "package"> "module"> "class">"function"

       3. 相同顺序的fixture基于依赖项执行:当一个fixture函数请另一个fixture函数,另一个会先执行,参考:https://www.cnblogs.com/pingguo-softwaretesting/p/14698711.html

 

fixture引用方式

       1. 一个fixture函数:A  请求另一个fixture:B,另一个B会先执行

       2. 为了控制B的fixture先执行,也可以通过autouse设置,将autouse设置成True

       3. 第三种方法,给先执行的fixture通过参数化,传入参数,

       调用方式

              1.  通过将fixture声明为参数来请求fixture,注意fixture名字不能写错

              2.  通过pytest.mark.usefixtures,将fixture声明作为参数传入测试用例

!!!pytest收集到测试用例的执行顺序

       1.  判断一下当前测试函数,是否有使用参数化,参数化里面有几组的测试数据,有几组的数据,决定了这条测试用例执行多少次

       2.  有使用参数化,参数化有两组的数据,分别执行两次的测试用例

       3.  测试用例执行前,会先查看该测试函数中的参数,然后搜索与函数名称一样的fixture,找到了这些fixture,先执行fixture,然后回到测试用例,继续执行

       运行 》 查找测试用例 》 找到测试用例 》 判断当前有几组参数化数据 》 开始执行 》 查看测试函数中的参数,与conftest中的fixture的名称是否有一样的 》 执行fixture 》 回到测试用例,开始执行测试用例

实际项目:

传入测试用例的数据:

sucess_data_bak = [{"user_id": "${user_id}", "username": "${login_user}", "password": "123", "sku_code": "vivo00100015",

                   "check": "第二个用户登录"},

                   {"user_id": "${user_id}", "username": "${login_user}", "password": "123", "case": "正常登录",

                   "check": "第一个用户登录"}]

测试用例

@pytest.mark.usefixtures("open_erp_url")    # 使用fixture方法:open_erp_url

@pytest.mark.usefixtures("preset_users_conditions")  # 使用fixture方法:preset_users_conditions

# 将参数传递给fixtures,命名为test_data,要使用这个参数的fixture的方法,传入的参数名称要和test_data一样

@pytest.mark.parametrize("test_data", login_data.sucess_data)

@pytest.mark.testlogin

# open_erp_url,用到几个fixtures、给fixtures传参:就要传几个fixtures进来测试用例

def test_login(self, open_erp_url, preset_users_conditions, test_data):

    '''
    :param open_erp_url: 前置条件打开浏览器,返回driver

    :param preset_users_conditions: 用户前置条件,包含查询用户的数据,和更新用户的数据

    :param sucess_data: 参数化的测试用例的数据

    :return:

    '''

    # 调试fixtures的登录方法

    data = preset_users_conditions

    print("开始执行登录成功的前置条件")

    loginpage(open_erp_url).Login(preset_users_conditions["username"], preset_users_conditions["password"])

    time.sleep(2)

测试用例使用了参数化

@pytest.mark.parametrize("test_data", login_data.sucess_data),两组数据,测试用例要执行两遍,将这个参数传到了fixture里面,根据参数化,先执行带参数化的fixture

测试用例执行前,查看测试函数中的参数,与conftest中的fixture的名称是否有一样,一样的先执行fixture

@pytest.mark.parametrize("test_data", login_data.sucess_data)

@pytest.mark.testlogin

# open_erp_url,用到几个fixtures、给fixtures传参:就要传几个fixtures进来测试用例

def test_login(self, open_erp_url, preset_users_conditions, test_data):
    loginpage(open_erp_url).Login(preset_users_conditions["username"], preset_users_conditions["password"])
 
 
 
@pytest.fixture(scope="function") def preset_users_conditions(test_data): ''' 用户的前置条件,包含传进来的test_case的数据,判断查询什么样的用户登录、以及根据user_id更新用户登录的密码、已经用户的角色,分配给某个角色 :param test_data: test_login.py测试类中测试用例,通过参数化,命名的参数化的数据,名称要和参数名声明的保持一致, 如:@pytest.mark.parametrize("test_data", login_data.sucess_data) :return: ''' # 根据测试用例的数据,判断要查询的是什么用户,用于登录中台 res_data = datamanage.dynamic_replace_data(testdata=test_data) # 更新用户的密码为123 update_user_pwd(res_data["user_id"]) yield res_data

执行完fixture:preset_users_conditions,接着执行open_erp_url

@pytest.fixture(scope="function")

def open_erp_url():

    '''

    执行登录操作前,先做打开浏览器,设置成最大化,然后再做登录操作

    :return:  driver:将当前打开浏览器的driver,传递给后面使用

    '''

    MyLog().info("执行前置方法_open_erp_url,打开浏览器")

    driver = webdriver.Chrome()

    driver.maximize_window()

    MyLog().info("open_erp_url_打开登录页面")

    driver.get(DoInfo.host)   # url登录的地址

    yield driver   # 返回driver给后面的其他操作使用

    driver.quit()  # 后置条件:测试用例执行完毕,关闭浏览器

Fixture执行完毕之后,回到测试用例, 执行测试用例

loginpage(open_erp_url).Login(preset_users_conditions["username"], preset_users_conditions["password"])

 

测试用例引用多个(包含不同级别) fixture

实现场景:打开浏览器,输入账号密码登录成功

方法一、

Confest.py定义fixtures,scope=“function”,方法级别, 每个测试用例都要执行一次

 

方法二、

Confest.py定义fixtures,scope=“session”,全局级别,只执行一次

 

方法一、二的区别:全部就执行一次,和每次用例执行都要执行

1、 不同模块,需要不同权限的用户,使用方法一

2、 相同模块,同一个功能,只是传入数据不同,使用方法二

 

在相同模块,同一个功能,将前置方法设置成session,可以减少代码运行时间和提高脚本的成功率

 

一个测试用例,即想使用全局的fixtures方法,也想使用function级别的fixtures方法,可以通过@pytest.usefixtures(“方法”) 和 将fixtures方法当成参数,传给测试用例

 

@pytest.fixture(scope="session")
def open_one_url(pytestconfig):
    MyLog().info("执行_全局前置方法_只打开一次浏览器")
    browser_name = pytestconfig.getoption('browser')
    if browser_name not in browsers:
        raise ValueError(f" browser {browser_name} not supported")
    try:
        driver = browsers.get(browser_name)()
        driver.maximize_window()
        driver.get("https://xxxxx")
    except Exception as e:
        mylog.exception("打开浏览器出错{0}".format(e))
        driver = None
    yield driver
    driver.quit()

 

@pytest.fixture(scope="function")   # 方法级别,即每个测试用例都要执行
def Create_sale_order(testdata):
    mylog.info("=== 执行{0}条_{1}_用例".format(testdata["id"], testdata["title"]))
    HttpRequest().get_token_username(username=DoInfo.login_name, pwd="xxxxx")

执行指定的测试用例,先指定open_one_url,然后每个测试用例执行前,都会执行Create_sale_order

 

@pytest.mark.usefixtures("open_one_url")           # 只执行一次
    @pytest.mark.parametrize("testdata", test_data)    # 测试数据
    # Create_sale_order:每个测试用例都会执行
    def test_sale_order(self, open_one_url, Create_sale_order, testdata):
        # ==== 菜单切换 ====
        测试用例执行的步骤

posted on 2021-07-01 15:09  刚刚好1  阅读(1879)  评论(0编辑  收藏  举报

导航