pytest学习14--函数传参和fixture传参request
前言:
为了提高代码的复用性,我们在写测试用例的时候,会用到函数,然后把不同的用例去调用这个函数。
比如登录操作,大部分的用例都会先登录,那就需要把登录单独抽出来写个函数,其他用例全部调用这个函数就行,但是登录账号不能写死,有时候我想用账号A登录,执行用例1,用账号B登录执行用例2,所以需要对函数传参。
1、登录函数传参
把登录单独成立,写一个函数,传2个参数user和psw,写用例的时候调用登录函数,输入几组user,psw参数化登录。
测试用例传参需要使用装饰器pytest.mark.parameterize(),里面写两个参数
--第一个参数是字符串,多个参数中间用逗号隔开
--第二个参数是list,多组数据用 元组类型
例子:
# !/usr/bin/env python # -*-coding:utf-8 -*- """ # File : test_login.py # Time :2021/11/22 20:36 # Author :author Kong_hua_sheng_25304 # version :python 3.8 # Description: """ import pytest test_login_data = [('admin','1111'),('admin','')] def login(user,psw): """ 普通的登录函数 :type psw: String :type user: String :param user: :param psw: :return: """ print("\n登录账号:%s"%user) print("登录密码:%s"%psw) if psw: return True else: return False @pytest.mark.parametrize('user,psw',test_login_data) def test_login(user,psw): result = login(user,psw) assert result == True,"失败原因,密码为空" pass if __name__ == '__main__': pytest.main(['-s','-q','test_login.py'])
运行结果:
2、request参数
如果想把登录操作放在前置的操作里,也就是使用到@pytest.fixture()装饰器,传参就用默认的request参数,user = request.param这一步是接受传入的参数,本案例是传入一个参数的情况。
# !/usr/bin/env python # -*-coding:utf-8 -*- """ # File : test_login_request.py # Time :2021/11/22 20:51 # Author :author Kong_hua_sheng_25304 # version :python 3.8 # Description: request传参 """ import pytest test_user_data = ['admin1','admin2'] @pytest.fixture(scope='module') def login(request): user = request.param print("登陆的账户:%s "%user) return user @pytest.mark.parametrize('login',test_user_data,indirect=True) def test_login(login): """ 登录用例 :param login: :return: """ a = login print("测试用例中login的返回值:%s"%a) assert a != "" if __name__ == '__main__': pytest.main(['-s','-q','test_login_request.py'])
执行结果:
这里对indirect做一个解释:
添加indirect=True参数是为了把pytest.mark.para,eterize('login',test_user_data,indirect=True)中的login当成一个函数去执行,而不是一个参数。
1: @pytest.mark.parameterize('login',test_user_data)
2: @pytest.mark.parameterize('login',test_user_data,indirect=True)
当使用第一个装饰器的时候,login就是一个变量,执行后的结果就是 login = ['admin1','admin2']
当使用第二个装饰器的时候,login就变为一个可执行函数,再将params当参数传入login函数中去执行,当其他变量被赋值为login的时候。
上个代码例子中:
a = login 就是讲login函数的执行结果返回给a
总结:
当indirect为True的时候,参数为固件函数名称的,执行的时候会当做函数来执行。
当indirect为False的时候,参数为固件函数名称的,执行的时候会当做一个参数来执行。
3、request传递2个参数的时候
如果用到@pytest.fixture,传递2个参数的情况,可以吧多个参数用一个字典去存储,这样最终还是只传递一个参数。
不同的参数再从字典里取对应的key'值就行。
# !/usr/bin/env python # -*-coding:utf-8 -*- """ # File : test_request_login2.py # Time :2021/11/22 21:18 # Author :author Kong_hua_sheng_25304 # version :python 3.8 # Description:使用request传递2个参数的情况 """ import pytest test_user_data = [{'user':'admin1','psw':"1111"}, {'user':'admin2','psw':""}] @pytest.fixture(scope='module') def login(request): """ 普通的登录函数,写在fixture中,在执行module之前执行次函数 :param request: :return: """ user = request.param['user'] psw = request.param['psw'] print('登录的账户为:%s 登录的密码为:%s'%(user,psw)) if psw: return True else: return False # indirect = True 的含义为 声明login为可执行的函数,而不是一个参数 @pytest.mark.parametrize('login',test_user_data,indirect=True) def test_login(login): """ 测试函数 使用request传递2个参数 :param login: :return: """ a = login print("测试用例中login的返回值:%s "%a) assert a !="" , "失败原因 密码为空" if __name__ == '__main__': pytest.main(['-s','-q','test_request_login2.py'])
运行结果:
4、多个fixture
用例上面是可以用多个fixture的,也就是多个前置操作,可以支持装饰器的叠加,使用parameterize装饰器叠加时,用例组合是2个参数个数相乘。
# !/usr/bin/env python # -*-coding:utf-8 -*- """ # File : test_request_login3.py # Time :2021/11/22 21:33 # Author :author Kong_hua_sheng_25304 # version :python 3.8 # Description:使用parameterize装饰器叠加,参数的两个装饰器的参数组合 """ import pytest test_user = ['admin1','admin2'] test_psw = ['1111','2222'] @pytest.fixture(scope='module') def input_user(request): user = request.param print("登录账户:%s "%user) return user @pytest.fixture(scope='module') def input_psw(request): psw = request.param print("登录的密码:%s"%psw) return psw # 这个会组成参数组合 @pytest.mark.parametrize("input_user",test_user,indirect=True) @pytest.mark.parametrize("input_psw",test_psw,indirect=True) def test_login(input_user,input_psw): user = input_user psw = input_psw print("user = %s psw = %s"%(user,psw)) assert psw if __name__ == '__main__': pytest.main(['-s','-q','test_request_login3.py'])
运行结果:2*2=4共4种组合