Pytest中内置fixture(七)

      在Pytest的测试框架中,也是内置了fixture的功能,这些内置的fixture在特定的测试场景下能够提高测试的效率,另外

一个好处是它是内置的fixture,就不需要单独再写fixture了。就像Python语言中内置的函数一样,直接拿来调用实现想要

实现的功能就可以了。下面具体来看这些内置的fixture它的含义以及在测试场景下的案例应用。

一、tmpdir

    内置的fixture负责在测试开始前创建文件,和测试结束后删除临时文件。这样的测试场景也是比较常见的,比如测试过程

中需要存放一个临时数据,那么既然是存放临时数据就需要临时目录,测试结束后临时文件也删除。就以一个登录的token为

案例来演示它的应用,熟悉接口测试的同学都知道,token是登录成功后服务端返回给客户端随机的一个密钥,那么客户端下

次请求服务端的时候,给服务端的token与服务端返回给客户端的一致,如果不一致,客户端就会返回到登录的页面,要起登

录,见如下的案例测试代码:

#!/usr/bin/python3
#coding:utf-8

import  pytest

def login(username,password):
    if username=='wuya' and password =='admin':
        return 'dfghjkerty45fdsgudf'

def order(token):
    if token=='dfghjkerty45fdsgudf':
        return True
    else:
        print('请登录系统')


def test_order_tmpdir(tmpdir):
    token=tmpdir.join('token.txt')
    token.write(login('wuya','admin'))
    assert  order(token.read())==True

 

具体看测试的函数test_order_tmpdir(),首先创建一个临时文件,往临时文件写入token,然后断言验证,order()函数请求

,它的参数与login()函数返回的参数一致,所以结果是True,当然这地方还可以来一个失败的测试场景,也就是order()的

token与login()的token不一致情况,见完善后的源码:

#!/usr/bin/python3
#coding:utf-8

import  pytest

def login(username,password):
    if username=='wuya' and password =='admin':
        return 'dfghjkerty45fdsgudf'

def order(token):
    if token=='dfghjkerty45fdsgudf':
        return True
    else:
        return ('请登录系统')


def test_order_success(tmpdir):
    token=tmpdir.join('token.txt')
    token.write(login('wuya','admin'))
    assert  order(token.read())==True

def test_order_failing(tmpdir):
    token=tmpdir.join('token.txt')
    token.write(login('admin','admin'))
    assert  order(token.read())=='请登录系统'

 二、tmpdir_factory

        tmpdir主要是针对文件的,而tmpdir_factory是针对目录的,另外tmpdir只可以针对一个测试点,而针对多个测试点就需要

tmpdir_factory,对如上的案例代码进行修改,存储文件我们就需要目录,在一个临时目录下存储临时文件,和临时文件里面存储

临时数据,这样使用内置fixture来处理,而我们这中间就不需要单独的处理了。还是接着上面的案例修改测试代码,见完善后的案例

代码:

#!/usr/bin/python3
#coding:utf-8

import  pytest

def login(username,password):
    if username=='wuya' and password =='admin':
        return 'dfghjkerty45fdsgudf'

def order(token):
    if token=='dfghjkerty45fdsgudf':
        return True
    else:
        return ('请登录系统')

def test_order_success(tmpdir_factory):
    #创建临时目录
    token_direct=tmpdir_factory.mktemp('data')
    token=token_direct.join('token.txt')
    token.write(login('wuya','admin'))
    assert  order(token.read())==True

def test_order_failing(tmpdir_factory):
    #创建临时目录
    token_direct=tmpdir_factory.mktemp('data')
    token=token_direct.join('token.txt')
    token.write(login('admin','admin'))
    assert  order(token.read())=='请登录系统'

 

见tmpdir_factory的案例应用,当然这样的测试代码是需要重构的,特别是创建临时目录目录就写的有点重复,那么就把它单独的

分离出来,我们的原则不是让代码多么复杂,而是追求让代码多么简单,见完善后的代码:

#!/usr/bin/python3
#coding:utf-8

import  pytest

def login(username,password):
    if username=='wuya' and password =='admin':
        return 'dfghjkerty45fdsgudf'

def order(token):
    if token=='dfghjkerty45fdsgudf':
        return True
    else:
        return ('请登录系统')

@pytest.fixture()
def dataTemp(tmpdir_factory):
    return tmpdir_factory.mktemp('data')

def test_order_success(dataTemp):
    token_direct=dataTemp
    token=token_direct.join('token.txt')
    token.write(login('wuya','admin'))
    assert  order(token.read())==True

def test_order_failing(dataTemp):
    token_direct=dataTemp
    token=token_direct.join('token.txt')
    token.write(login('admin','admin'))
    assert  order(token.read())=='请登录系统'

 

见完善后的代码,我们把创建临时的目录单独的分离了出来,这样就达到了tmpdir_factory使用多个测试点的复用。

当然还有另外一种测试场景就是一个json文件多个测试点使用到,它的具体源码和测试代码为:

#!/usr/bin/python3
#coding:utf-8


import  pytest
import  json


@pytest.fixture(scope='function')
def getJsonFile(tmpdir_factory):
    '''一个测试模块,多个测试点使用到json文件'''
    datas={
        1:{'name':'wuya','age':18,'done':True},
        2:{'name':'weike','age':20,'done':False}
    }
    file=tmpdir_factory.mktemp('data').join('data.json')
    with file.open('w') as f:
        json.dump(datas,f)
    return file


def test_json_share(getJsonFile):
    with getJsonFile.open() as f:
        datas=json.load(f)
    assert datas['1']['name']=='wuya'

def test_json_share_len(getJsonFile):
    with getJsonFile.open() as f:
        datas=json.load(f)
    assert len(datas)==2

 如上的代码案例输出的信息在这里我就不展示了,内置的tmpdir和tmpdir_factory在操作目录和文件场景是特别有用的。

三、cache

     在UI的自动化测试中还是API的自动化测试中,特别是在UI的自动化测试中,我们尽量保持每个testcase的独立性,以及

互相之间没有依赖性,这样的思考是有原因的。但是在API的测试中,特别是基于业务的API的测试,经常涉及到参数的传递,

也就是说上一个函数返回的参数需要传递给下一个测试的接口中,这样的案例是非常多的。在Pytest的测试框架中,内置fixture

的catch可以实现每个会话可以重复,而不会因为上一段会话的运行影响这一段的测试行为。它的作用是:存储一段测试会话,

在下一段测试会话中使用。当然使用--last-failed和--failed-first。还是看案例的测试代码:

#!/usr/bin/python3
#coding:utf-8


import  pytest



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

def test_add_success():
    assert add(2,3)==5

def test_add_fail():
    assert  add('hi','wuya')=='hi wuya'

 

执行如上的代码后,见执行结果的输出:

Test session starts (platform: darwin, Python 3.7.4, pytest 4.0.2, pytest-sugar 0.9.2)
rootdir: /Applications/code/stack/pyUnit/内置fixture, inifile:
plugins: xdist-1.29.0, forked-1.0.2, sugar-0.9.2, html-1.22.0, cov-2.7.1, allure-adaptor-1.7.10, metadata-1.8.0
collecting ... 
 test_catch_fixture.py ✓                                          50% █████     

 test_catch_fixture.py ⨯                                         100% ██████████

Results (0.08s):
       1 passed
       1 failed
         - test_catch_fixture.py:15 test_add_fail

 

然后再次执行pytest --last-failed,就会单独的只执行上次执行失败的testcase,再次执行见执行后的输出信息:

plugins: xdist-1.29.0, forked-1.0.2, sugar-0.9.2, html-1.22.0, cov-2.7.1, allure-adaptor-1.7.10, metadata-1.8.0
collecting ... run-last-failure: rerun previous 1 failure


―――――――――――――――――――――――――――――――― test_add_fail ―――――――――――――――――――――――――――――――――

    def test_add_fail():
>       assert  add('hi','wuya')=='hi wuya'
E    AssertionError: assert 'hiwuya' == 'hi wuya'
E      - hiwuya
E      + hi wuya
E      ?   +

test_catch_fixture.py:16: AssertionError

 test_catch_fixture.py ⨯                                         100% ██████████

Results (0.05s):
       1 failed
         - test_catch_fixture.py:15 test_add_fail
       1 deselected

 

为了记住上次失败的信息,Pytest使用catch存储了上次会话失败的信息,当然查看的命令为:--catch-show ,执行的步骤为:

1、先执行所有的测试点,最好里面有失败的

2、执行pytest -cache-show,显示会话存储的失败的信息,见如下的输出信息:

Test session starts (platform: darwin, Python 3.7.4, pytest 4.0.2, pytest-sugar 0.9.2)
rootdir: /Applications/code/stack/pyUnit/内置fixture, inifile:
plugins: xdist-1.29.0, forked-1.0.2, sugar-0.9.2, html-1.22.0, cov-2.7.1, allure-adaptor-1.7.10, metadata-1.8.0
collecting ... 
 test_cache.py ✓                                                  50% █████     

―――――――――――――――――――――――――――――――― test_add_fail ―――――――――――――――――――――――――――――――――

    def test_add_fail():
>       assert  add('hi','wuya')=='hi wuya'
E    AssertionError: assert 'hiwuya' == 'hi wuya'
E      - hiwuya
E      + hi wuya
E      ?   +

test_cache.py:16: AssertionError

 test_cache.py ⨯                                                 100% ██████████

Results (0.08s):
       1 passed
       1 failed
         - test_cache.py:15 test_add_fail

#执行查看失败的存储信息
pytest --cache-show Test session starts (platform: darwin, Python 3.7.4, pytest 4.0.2, pytest-sugar 0.9.2) rootdir: /Applications/code/stack/pyUnit/内置fixture, inifile: plugins: xdist-1.29.0, forked-1.0.2, sugar-0.9.2, html-1.22.0, cov-2.7.1, allure-adaptor-1.7.10, metadata-1.8.0 cachedir: /Applications/code/stack/pyUnit/内置fixture/.pytest_cache --------------------------------- cache values --------------------------------- cache/lastfailed contains: {'test_cache.py::test_add_fail': True, 'test_catch_fixture.py::test_add_fail': True, 'test_catch_fixture.py::test_catch_failing': True} cache/nodeids contains: ['test_cache.py::test_add_success', 'test_cache.py::test_add_fail'] cache/stepwise contains: [] Results (0.02s):

 

在如上的信息中,可以看到执行--cache-show的命令后,输出的是会话中储存的失败的信息。

 

posted @ 2019-09-22 16:54  无涯(WuYa)  阅读(530)  评论(0编辑  收藏  举报