• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

pytest–函数传参和fixture传参数request

开发技术 开发技术 6小时前 4次浏览

前言

为了提高代码的复用性,我们在写用例的时候,会用到函数,然后不同的用例去调用这个函数。

比如登录操作,大部分的用例都会先登录,那就需要把登录单独抽出来写个函数,其它用例全部的调用这个登录函数就行。但是登录的账号不能写死,有时候我想用账号1去登录,执行用例1,用账号2去登录执行用例2,所以需要对函数传参。

登录函数传参

把登录单独出来,写一个函数,传2个参数user和pwd,写用例的时候调用登录函数,输入几组user,pwd参数化登录用例测试用例传参需要用装饰器@pytest.mark.parametrize,里面写两个参数

  第一个参数是字符串,多个参数中间用逗号隔开

  第二个参数list,多组数据用元组类型

#test_fix1.py
#coding:utf-8
import pytest
test_user_data=[("admin","123456"),("test","")]
def login(user,pwd):
    print("登录账号:{}".format(user))
    print("登录密码:%s"%pwd)
    if pwd:
        return True
    else:
        return False
@pytest.mark.parametrize("user,pwd",test_user_data)
def test_login(user,pwd):
    result=login(user,pwd)
    assert result==True,"失败原因:密码为空"
if __name__=="__main__":
    pytest.main(["-s","test_fix1.py"]) 

运行结果

============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-6.1.2, py-1.9.0, pluggy-0.13.1
rootdir: D:studyxyautotest
plugins: allure-pytest-2.8.19, Faker-4.18.0, hypothesis-6.14.6, assume-2.4.3, forked-1.3.0, html-2.1.1, metadata-1.10.0, ordering-0.6, rerunfailures-9.1.1, xdist-2.3.0, tep-0.8.9collected 2 items

test_f1.py .登录账号:admin
登录密码:123456
F登录账号:test
登录密码:

AssertionError: 失败原因:密码为空
False != True

Expected :True
Actual   :False
<Click to see difference>

user = 'test', pwd = ''

    @pytest.mark.parametrize("user,pwd",test_user_data)
    def test_login(user,pwd):
        result=login(user,pwd)
>       assert result==True,"失败原因:密码为空"
E       AssertionError: 失败原因:密码为空
E       assert False == True

test_f1.py:13: AssertionError

Assertion failed
                                                            [100%]

================================== FAILURES ===================================
______________________________ test_login[test-] ______________________________

user = 'test', pwd = ''

    @pytest.mark.parametrize("user,pwd",test_user_data)
    def test_login(user,pwd):
        result=login(user,pwd)
>       assert result==True,"失败原因:密码为空"
E       AssertionError: 失败原因:密码为空
E       assert False == True

test_f1.py:13: AssertionError
---------------------------- Captured stdout call -----------------------------
登录账号:test
登录密码:
=========================== short test summary info ===========================
FAILED test_f1.py::test_login[test-] - AssertionError: 失败原因:密码为空
========================= 1 failed, 1 passed in 0.27s =========================

Process finished with exit code 0

从结果可以看出,有2个用例,一个测试通过,一个测试失败了,互不影响。

request参数

如果想把登录操作放到前置操作里,也可以用到@pytest.fixture装饰器,传参就用默认的request参数user=request.param这一步是接收传入的参数,如下传入一个参数情况。

添加indirect=True参数是为了把login当成一个函数去执行,而不是一个参数.

indirect=True是指用test_users数据对”login”这个fixture进行参数化,虽然装饰器写在测试用例上,但是却是对测试用例使用的fixture进行传递数据,这正是indirect单词的意思。

#coding:utf-8
import pytest
test_users=["admin","test",""]
@pytest.fixture(scope="module")
def login(request):
    user=request.param
    print(f"登录账户:{user}")
    return user
@pytest.mark.parametrize("login",test_users,indirect=True)
def test_login(login):
    a=login
    print(f"测试用例中login的返回值{a}")
    assert a !="","账户为空"
if __name__=="__main__":
    pytest.main(["-s","test_fix1.py"])

运行结果

============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-6.1.2, py-1.9.0, pluggy-0.13.1
rootdir: D:studyxyautotest
plugins: allure-pytest-2.8.19, Faker-4.18.0, hypothesis-6.14.6, assume-2.4.3, forked-1.3.0, html-2.1.1, metadata-1.10.0, ordering-0.6, rerunfailures-9.1.1, xdist-2.3.0, tep-0.8.9collected 3 items

test_f1.py 登录账户:admin
.测试用例中login的返回值admin
登录账户:test
.测试用例中login的返回值test
登录账户:
F测试用例中login的返回值

test_f1.py:8 (test_login[])
login = ''

   @pytest.mark.parametrize("login",test_users,indirect=True)
   def test_login(login):
       a=login
       print(f"测试用例中login的返回值{a}")
>       assert a !="","账户为空"
E       AssertionError: 账户为空
E       assert '' != ''

test_f1.py:13: AssertionError
                                                          [100%]

================================== FAILURES ===================================
________________________________ test_login[] _________________________________

login = ''

   @pytest.mark.parametrize("login",test_users,indirect=True)
   def test_login(login):
       a=login
       print(f"测试用例中login的返回值{a}")
>       assert a !="","账户为空"
E       AssertionError: 账户为空
E       assert '' != ''

test_f1.py:13: AssertionError
---------------------------- Captured stdout setup ----------------------------
登录账户:
---------------------------- Captured stdout call -----------------------------
测试用例中login的返回值
=========================== short test summary info ===========================
FAILED test_f1.py::test_login[] - AssertionError: 账户为空
========================= 1 failed, 2 passed in 0.27s =========================

Process finished with exit code 0

request传2个参数

如果用到@pytest.fixture,里面用2个参数情况,可以把多个参数用一个字典去存储,这样最终还是只传一个参数。

不同的参数再从字典里面取对应key值就行,如:user=request.param[“user”]

#test_fix1.py
#coding:utf-8
import pytest
test_users=[{"user":"admin","pwd":"123456"},{"user":"test","pwd":""}]
@pytest.fixture(scope="module")
def login(request):
    user=request.param["user"]
    pwd=request.param["pwd"]
    print(f"登录账户:{user}")
    print(f"登录密码:{pwd}")
    return pwd
@pytest.mark.parametrize("login",test_users,indirect=True)
def test_login(login):
    a=login
    print("测试用例中login的返回值{}".format(a))
    assert a !="","密码为空"
if __name__=="__main__":
    pytest.main(["-s","test_fix1.py"])

运行结果

============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-6.1.2, py-1.9.0, pluggy-0.13.1
rootdir: D:studyxyautotest
plugins: allure-pytest-2.8.19, Faker-4.18.0, hypothesis-6.14.6, assume-2.4.3, forked-1.3.0, html-2.1.1, metadata-1.10.0, ordering-0.6, rerunfailures-9.1.1, xdist-2.3.0, tep-0.8.9collected 2 items

test_f1.py 登录账户:admin
登录密码:123456
.测试用例中login的返回值123456
登录账户:test
登录密码:
F测试用例中login的返回值

test_f1.py:11 (test_login[login1])
login = ''

    @pytest.mark.parametrize("login",test_users,indirect=True)
    def test_login(login):
        a=login
        print("测试用例中login的返回值{}".format(a))
>       assert a !="","密码为空"
E       AssertionError: 密码为空
E       assert '' != ''

test_f1.py:16: AssertionError

Assertion failed
                                                            [100%]

================================== FAILURES ===================================
_____________________________ test_login[login1] ______________________________

login = ''

    @pytest.mark.parametrize("login",test_users,indirect=True)
    def test_login(login):
        a=login
        print("测试用例中login的返回值{}".format(a))
>       assert a !="","密码为空"
E       AssertionError: 密码为空
E       assert '' != ''

test_f1.py:16: AssertionError
---------------------------- Captured stdout setup ----------------------------
登录账户:test
登录密码:
---------------------------- Captured stdout call -----------------------------
测试用例中login的返回值
=========================== short test summary info ===========================
FAILED test_f1.py::test_login[login1] - AssertionError: 密码为空
========================= 1 failed, 1 passed in 0.27s =========================

Process finished with exit code 0

Assertion failed

Assertion failed

如果要用到login里面的返回值,def test_login(login)时,传入login参数,函数返回值就是login了。

多个fixtrue

用例上面是可以同时放多个fixture的,也就是多个前置操作,可以支持装饰器叠加,使用parametrize装饰器叠加时,用例组合是2个参数个数相乘。

#test_fix1.py
#coding:utf-8
import pytest
test_users=["admin","test"]
test_pwd=["123456","888888"]
@pytest.fixture(scope="module")
def in_user(request):
    user=request.param
    print("登录账号:{}".format(user))
    return user
 
@pytest.fixture(scope="module")
def in_pwd(request):
    pwd=request.param
    print("登录密码:{}".format(pwd))
    return pwd
 
@pytest.mark.parametrize("in_user",test_users,indirect=True)
@pytest.mark.parametrize("in_pwd",test_pwd,indirect=True)
def test_login(in_user,in_pwd):
    a=in_user
    b=in_pwd
    print("账号,密码:{},{}".format(a,b))
    assert b
if __name__=="__main__":
    pytest.main(["-s","test_fix1.py"])

运行结果:

============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-6.1.2, py-1.9.0, pluggy-0.13.1
rootdir: D:studyxyautotest
plugins: allure-pytest-2.8.19, Faker-4.18.0, hypothesis-6.14.6, assume-2.4.3, forked-1.3.0, html-2.1.1, metadata-1.10.0, ordering-0.6, rerunfailures-9.1.1, xdist-2.3.0, tep-0.8.9collected 4 items

test_f1.py                                                           [100%]

============================== 4 passed in 0.12s ==============================

Process finished with exit code 0
登录账号:admin
登录密码:123456
.账号,密码:admin,123456
登录账号:test
.账号,密码:test,123456
登录密码:888888
.账号,密码:test,888888
登录账号:admin
.账号,密码:admin,888888

如果参数users有2个数据,参数pwd有2个数据,那么组合起来的案例是两个相乘,也就是2*2=4个用例


程序员灯塔
转载请注明原文链接:pytest–函数传参和fixture传参数request
喜欢 (0)