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的命令后,输出的是会话中储存的失败的信息。