pytest文档14-函数传参和fixture传参数request

前言

为了提高代码的复用性,我们在写用例的时候,会用到函数,然后不同的用例去调用这个函数。 比如登录操作,大部分的用例都会先登录,那就需要把登录单独抽出来写个函数,其它用例全部的调用这个登陆函数就行。 但是登录的账号不能写死,有时候我想用账号1去登录,执行用例1,用账号2去登录执行用例2,所以需要对函数传参。

登录函数传参

把登录单独成立,写一个函数,传2个参数user和psw,写用例的时候调用登录函数,输入几组user,psw参数化登录用例

测试用例传参需要用装饰器@pytest.mark.parametrize,里面写两个参数

  • 第一个参数是字符串,多个参数中间用逗号隔开
  • 第二个参数是list,多组数据用元祖类型
# test_01.py

# coding:utf-8
import pytest

# ** 作者:上海-悠悠 QQ交流群:588402570**

# 测试登录数据
test_login_data = [("admin", "111111"),  ("admin", "")]

def login(user, psw):
    '''普通登录函数'''
    print("登录账户:%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, "失败原因:密码为空"

if __name__ == "__main__":
    pytest.main(["-s", "test_01.py"])

运行结果

============================= test session starts =============================
platform win32 -- Python 3.6.0, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
rootdir: D:\, inifile:
plugins: metadata-1.7.0, html-1.19.0, allure-adaptor-1.7.10
collected 2 items

..\..\..\..\..\..\YOYO\marktest\test_01.py 登录账户:admin
登录密码:111111
.登录账户:admin
登录密码:
F
user = 'admin', psw = ''

    @pytest.mark.parametrize("user, psw", [("admin", "111111"), ("admin", "")])
    def test_01(user, psw):
        result = login(user, psw)
>       assert result == True
E       assert False == True

D:\YOYO\marktest\test_01.py:18: AssertionError

================================== FAILURES ===================================
_______________________________ test_01[admin-] _______________________________

user = 'admin', psw = ''

    @pytest.mark.parametrize("user, psw", [("admin", "111111"), ("admin", "")])
    def test_01(user, psw):
        result = login(user, psw)
>       assert result == True
E       assert False == True

D:\YOYO\marktest\test_01.py:18: AssertionError
===================== 1 failed, 1 passed in 0.05 seconds ======================

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

request参数

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

# test_02.py
# coding:utf-8
import pytest

#** 作者:上海-悠悠 QQ交流群:588402570**

# 测试账号数据
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):
    '''登录用例'''
    a = login
    print("测试用例中login的返回值:%s" % a)
    assert a != ""

if __name__ == "__main__":
    pytest.main(["-s", "test_02.py"])

运行结果:

============================= test session starts =============================
platform win32 -- Python 3.6.0, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
rootdir: D:\, inifile:
plugins: metadata-1.7.0, html-1.19.0, allure-adaptor-1.7.10
collected 2 items

..\..\..\..\..\..\YOYO\marktest\test_02.py 登录账户:admin1
测试用例中login的返回值:admin1
.登录账户:admin2
测试用例中login的返回值:admin2
.

========================== 2 passed in 0.01 seconds ===========================

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

request传2个参数

如果用到@pytest.fixture,里面用2个参数情况,可以把多个参数用一个字典去存储,这样最终还是只传一个参数 不同的参数再从字典里面取对应key值就行,如: user = request.param[“user”]

# test_03.py
# coding:utf-8
import pytest

# ** 作者:上海-悠悠 QQ交流群:588402570**

# 测试账号数据
test_user_data = [{"user": "admin1", "psw": "111111"},
                  {"user": "admin1", "psw": ""}]

@pytest.fixture(scope="module")
def login(request):
    user = request.param["user"]
    psw = request.param["psw"]
    print("登录账户:%s" % user)
    print("登录密码:%s" % psw)
    if psw:
        return True
    else:
        return False

# indirect=True 声明login是个函数
@pytest.mark.parametrize("login", test_user_data, indirect=True)
def test_login(login):
    '''登录用例'''
    a = login
    print("测试用例中login的返回值:%s" % a)
    assert a, "失败原因:密码为空"

if __name__ == "__main__":
    pytest.main(["-s", "test_03.py"])

运行结果

============================= test session starts =============================
platform win32 -- Python 3.6.0, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
rootdir: D:\, inifile:
plugins: metadata-1.7.0, html-1.19.0, allure-adaptor-1.7.10
collected 2 items

..\..\..\..\..\..\YOYO\marktest\test_03.py 登录账户:admin1
登录密码:111111
测试用例中login的返回值:True
.登录账户:admin1
登录密码:
测试用例中login的返回值:False
F
login = False

    @pytest.mark.parametrize("login", test_user_data, indirect=True)
    def test_login(login):
        '''登录用例'''
        a = login
        print("测试用例中login的返回值:%s" % a)
>       assert a, "失败原因:密码为空"
E       AssertionError: 失败原因:密码为空
E       assert False

D:\YOYO\marktest\test_03.py:25: AssertionError

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

login = False

    @pytest.mark.parametrize("login", test_user_data, indirect=True)
    def test_login(login):
        '''登录用例'''
        a = login
        print("测试用例中login的返回值:%s" % a)
>       assert a, "失败原因:密码为空"
E       AssertionError: 失败原因:密码为空
E       assert False

D:\YOYO\marktest\test_03.py:25: AssertionError
===================== 1 failed, 1 passed in 0.05 seconds ======================

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

多个fixtrue

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

# test_04.py
# ** 作者:上海-悠悠 QQ交流群:588402570**
# coding:utf-8
import pytest

# 测试账号数据
test_user = ["admin1", "admin2"]
test_psw = ["11111", "22222"]

@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):
    '''登录用例'''
    a = input_user
    b = input_psw
    print("测试数据a-> %s, b-> %s" % (a,b))
    assert b

if __name__ == "__main__":
    pytest.main(["-s", "test_04.py"])

运行结果

============================= test session starts =============================
platform win32 -- Python 3.6.0, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
rootdir: E:\YOYO\par, inifile:
plugins: metadata-1.7.0, html-1.19.0
collected 4 items

test_04.py 登录账户:admin1
登录密码:11111
测试数据a-> admin1, b-> 11111
.登录账户:admin2
测试数据a-> admin2, b-> 11111
.登录密码:22222
测试数据a-> admin2, b-> 22222
.登录账户:admin1
测试数据a-> admin1, b-> 22222
.

========================== 4 passed in 0.05 seconds ===========================

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

作者:上海-悠悠

原文发布于微信公众号 - 从零开始学自动化测试(yoyoketang)

原文发表时间:2018-08-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏GreenLeaves

JS模块加载系统设计V1

一、require模块 +function() { var path = location.protocol + "//" + loca...

2055
来自专栏行者常至

008.多线程-synchronized锁

为了解决线程安全问题, 我们的做法是:不要让多个线程同时对一个全局变量作写的操作。

1012
来自专栏Python

django:DateTimeField如何自动设置为当前时间并且能被修改 ——django日期时间字段的使用

创建django的model时,有DateTimeField、DateField和TimeField三种类型可以用来创建日期字段,其值分别对应着datetime...

5668
来自专栏Vamei实验室

Python补充02 Python小技巧

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢! 在这里列举一些我使用Python时积累的小...

2027
来自专栏大壮

iOS 内存管理的理解分享(理论篇)

1807
来自专栏xcywt

关于 getsockname、getpeername和gethostname、gethostbyname

一、gethostname,gethostbyname的用法 这两个函数可以用来获取主机的信息。 gethostname:获取主机的名字 gethostbyna...

2025
来自专栏余林丰

虚拟机类加载机制(2)——类加载器

《深入理解Java虚拟机》一书中将类的加载过程放到了类加载器前面一节,但在这里我想先讲“类加载器”。在上一篇类加载时机中我们用大量篇幅来讲解了类加载过程中的5个...

2156
来自专栏Java编程技术

一个有关定时生产与消费的问题

按照上面的逻辑看的话,每个队列里面最多有一个元素。其实不然,因为在多线程模型中每个线程占用cpu执行的时间是按照时间片来划分的,每个线程执行完自己的时间片后会被...

821
来自专栏Java帮帮-微信公众号-技术文章全总结

hibernate延迟加载详解

hibernate延迟加载详解 Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认也会被延迟加载。hiber...

3123
来自专栏Python攻城狮

Python系统编程-进程1.进程1.多任务的引入2.多任务的概念

有很多的场景中的事情是同时进行的,比如开车的时候手和脚共同来驾驶汽车,再比如唱歌跳舞也是同时进行的;

923

扫码关注云+社区

领取腾讯云代金券