其他分享
首页 > 其他分享> > 测试框架pytest(四)

测试框架pytest(四)

作者:互联网

接上一篇,本章讲pytest的fixture

很多测试框架里的setup、teardown可以实现在执行用例前或结束后加入一些操作,但这种都是针对整个脚本全局生效的。
如果有以下场景:用例 1 需要先登录,用例 2 不需要登录,用例 3 需要先登录。很显然无法用 setup 和 teardown 来实现。fixture可以让我们自定义测试用例的前置条件以及结束后的后置处理动作,并且可以跨文件使用。

另外conftest.py 配置里可以实现数据共享,不需要 import 就能自动找到fixture,还可以自定义fixture的作用域

语法如下:

fixture(callable_or_scope=None, *args, scope="function", params=None, autouse=False, ids=None, name=None)

如下是无参使用例子


#!/usr/bin/env python
# -*-coding:utf-8 -*-
import pytest
from get_data import get_data


def add_demo(a, b):
return a+b


@pytest.fixture()
def login():
print('execute before')


@pytest.mark.smoke
class TestDemo:
@pytest.mark.parametrize("a,b,expected", get_data(),
ids=["level1", "level2", "level3"])
def test_one(self, a, b, expected):
assert add_demo(a, b) == expected

def test_two(self, login):
assert 2 != 3

@pytest.mark.usefixtures("login")
def test_three(self):
assert 4 != 3


if __name__ == "__main__":
pytest.main(['test_demo.py', '-v', '-s', '-m', 'smoke'])
 

上述代码中我们通过2种方式来演示fixture的使用,看个人喜好灵活运用。

出于可维护性方面考虑,我们把fixture放在conftest.py文件里进行维护,文件名称是固定的,这样不用引入就可以使用,然后使用范围根据conftest.py的存放位置以及fixture的作用域来确定,改造的conftest.py代码如下:

import pytest


@pytest.fixture()
def login_se():
    print('just another login')

然后原代码改造如下:

#!/usr/bin/env python
# -*-coding:utf-8 -*-
import pytest
from get_data import get_data


def add_demo(a, b):
    return a+b


@pytest.fixture()
def login():
    print('execute before')


@pytest.mark.smoke
class TestDemo:
    @pytest.mark.parametrize("a,b,expected", get_data(),
                             ids=["level1", "level2", "level3"])
    def test_one(self, a, b, expected):
        assert add_demo(a, b) == expected

    def test_two(self, login):
        assert 2 != 3

    @pytest.mark.usefixtures("login")
    def test_three(self):
        assert 4 != 3

    @pytest.mark.usefixtures("login_se")
    def test_four(self):
        assert 6 != 9

    def test_five(self, login_se):
        assert 9 != 0


if __name__ == "__main__":
    pytest.main(['test_demo.py', '-v', '-s', '-m', 'smoke'])

然后我们有时候需要在fixture里传入参数,现在演示这种情况,conftest.py代码如下:

 

#!/usr/bin/env python
# -*-coding:utf-8 -*-
import pytest


@pytest.fixture()
def login_se():
    print('just another login')


@pytest.fixture(scope='module')
def login_with_param(request):
    return request.param

改造后的test_demo.py代码如下:

#!/usr/bin/env python
# -*-coding:utf-8 -*-
import pytest
from get_data import get_data


def add_demo(a, b):
    return a+b


@pytest.fixture()
def login():
    print('execute before')


@pytest.mark.smoke
class TestDemo:
    @pytest.mark.parametrize("a,b,expected", get_data(),
                             ids=["level1", "level2", "level3"])
    def test_add_demo(self, a, b, expected):
        assert add_demo(a, b) == expected

    def test_two(self, login):
        assert 2 != 3

    @pytest.mark.usefixtures("login")
    def test_three(self):
        assert 4 != 3

    @pytest.mark.usefixtures("login_se")
    def test_four(self):
        assert 6 != 9

    def test_five(self, login_se):
        assert 9 != 0

    @pytest.mark.parametrize("login_with_param", [{"user": "lucy", "password": "123456"}],
                             ids=["level1"], indirect=True)
    def test_add_demo(self, login_with_param):
        username = login_with_param['user']
        password = login_with_param['password']
        assert username == 'lucy'
        assert password == '123456'


if __name__ == "__main__":
    pytest.main(['test_demo.py', '-v', '-s', '-m', 'smoke'])

到这里后,我们就已经实现了fixture有参的方式,但是目前为止还没有实现teardown的功能,可以用yield来实现,conftest.py代码如下:

#!/usr/bin/env python
# -*-coding:utf-8 -*-
import pytest


@pytest.fixture()
def login_se():
    print('just another login')


@pytest.fixture(scope='module')
def login_with_param(request):
    return request.param


@pytest.fixture(scope='module')
def login_with_params(request):
    print('开始前运行')
    yield request.param
    print('结束后运行')

改造后的test_demo.py的test_seven 代码如下:

#!/usr/bin/env python
# -*-coding:utf-8 -*-
import pytest
from get_data import get_data


def add_demo(a, b):
    return a+b


@pytest.fixture()
def login():
    print('execute before')


@pytest.mark.smoke
class TestDemo:
    @pytest.mark.parametrize("a,b,expected", get_data(),
                             ids=["level1", "level2", "level3"])
    def test_add_demo(self, a, b, expected):
        assert add_demo(a, b) == expected

    def test_two(self, login):
        assert 2 != 3

    @pytest.mark.usefixtures("login")
    def test_three(self):
        assert 4 != 3

    @pytest.mark.usefixtures("login_se")
    def test_four(self):
        assert 6 != 9

    def test_five(self, login_se):
        assert 9 != 0

    @pytest.mark.parametrize("login_with_param", [{"user": "lucy", "password": "123456"}],
                             ids=["level1"], indirect=True)
    def test_six(self, login_with_param):
        username = login_with_param['user']
        password = login_with_param['password']
        assert username == 'lucy'
        assert password == '123456'

    @pytest.mark.parametrize("login_with_params", [{"user": "lucy", "password": "123456"}],
                             ids=["level1"], indirect=True)
    def test_seven(self, login_with_params):
        username = login_with_params['user']
        password = login_with_params['password']
        assert username == 'lucy'
        assert password == '123456'


if __name__ == "__main__":
    pytest.main(['test_demo.py', '-v', '-s', '-m', 'smoke'])

上述方式是将fixture和parametrize结合起来使用,这样子会看起来比较不友好,所以把参数给到conftest.py里,改造如下:

#!/usr/bin/env python
# -*-coding:utf-8 -*-
import pytest


@pytest.fixture()
def login_se():
    print('just another login')


@pytest.fixture(scope='module')
def login_with_param(request):
    return request.param


@pytest.fixture(scope='module')
def login_with_params(request):
    print('开始前运行')
    yield request.param
    print('结束后运行')


@pytest.fixture(params=[{'user': 'lucy', 'password': '123456'}])
def login_and_logout(request):
    print('开始前运行的前置处理代码')
    yield request.param
    print('结束后运行的收尾处理代码')

然后测试类的test_eight改造如下:

#!/usr/bin/env python
# -*-coding:utf-8 -*-
import pytest
from get_data import get_data


def add_demo(a, b):
    return a+b


@pytest.fixture()
def login():
    print('execute before')


@pytest.mark.smoke
class TestDemo:
    @pytest.mark.parametrize("a,b,expected", get_data(),
                             ids=["level1", "level2", "level3"])
    def test_add_demo(self, a, b, expected):
        assert add_demo(a, b) == expected

    def test_two(self, login):
        assert 2 != 3

    @pytest.mark.usefixtures("login")
    def test_three(self):
        assert 4 != 3

    @pytest.mark.usefixtures("login_se")
    def test_four(self):
        assert 6 != 9

    def test_five(self, login_se):
        assert 9 != 0

    @pytest.mark.parametrize("login_with_param", [{"user": "lucy", "password": "123456"}],
                             ids=["level1"], indirect=True)
    def test_six(self, login_with_param):
        username = login_with_param['user']
        password = login_with_param['password']
        assert username == 'lucy'
        assert password == '123456'

    @pytest.mark.parametrize("login_with_params", [{"user": "lucy", "password": "123456"}],
                             ids=["level1"], indirect=True)
    def test_seven(self, login_with_params):
        username = login_with_params['user']
        password = login_with_params['password']
        assert username == 'lucy'
        assert password == '123456'

    def test_eight(self, login_and_logout):
        username = login_and_logout['user']
        password = login_and_logout['password']
        assert username == 'lucy'
        assert password == '123456'


if __name__ == "__main__":
    pytest.main(['test_demo.py', '-v', '-s', '-m', 'smoke'])

至此,fixture就讲解完毕,上述代码比较简陋,还应该做较好的封装,提高代码的可读性

标签:框架,fixture,assert,pytest,测试,test,login,def
来源: https://www.cnblogs.com/doumayi/p/16194767.html