测试功能我需要传递参数并查看输出与预期输出匹配.
当函数的响应只是一个小数组或可以在测试函数中定义的单行字符串时很容易,但假设我测试的函数修改了一个可能很大的配置文件.或者,如果我明确定义它,结果数组就会长4行.我在哪里存储,以便我的测试保持干净,易于维护?
现在如果那是字符串我只是在.py测试附近放一个文件并open()在测试中进行:
def test_if_it_works():
with open('expected_asnwer_from_some_function.txt') as res_file:
expected_data = res_file.read()
input_data = ... # Maybe loaded from a file as well
assert expected_data == if_it_works(input_data)
Run Code Online (Sandbox Code Playgroud)
我发现这种方法存在许多问题,比如维护此文件的最新问题.它看起来也很糟糕.我可以把事情变得更好:
@pytest.fixture
def expected_data()
with open('expected_asnwer_from_some_function.txt') as res_file:
expected_data = res_file.read()
return expected_data
@pytest.fixture
def input_data()
return '1,2,3,4'
def test_if_it_works(input_data, expected_data):
assert expected_data == if_it_works(input_data)
Run Code Online (Sandbox Code Playgroud)
这只是将问题移到另一个地方,通常我需要测试函数是否在空输入,输入单个项目或多个项目的情况下工作,所以我应该创建一个大的夹具,包括所有三个案例或多个灯具.最后代码变得相当混乱.
如果一个函数需要一个复杂的字典作为输入或者给出相同大小的字典测试代码变得丑陋:
@pytest.fixture
def input_data():
# It's just an example
return {['one_value': 3, 'one_value': 3, 'one_value': 3,
'anotherky': 3, 'somedata': 'somestring'],
['login': 3, 'ip_address': 32, 'value': 53,
'one_value': 3], ['one_vae': 3, 'password': 13, 'lue': 3]}
Run Code Online (Sandbox Code Playgroud)
用这样的装置读取测试并让它们保持最新是很困难的.
经过一段时间的搜索,我找到了一个解决了部分问题的库,而不是大配置文件,我有大量的HTML响应.这是betamax.
为了便于使用,我创建了一个夹具:
from betamax import Betamax
@pytest.fixture
def session(request):
session = requests.Session()
recorder = Betamax(session)
recorder.use_cassette(os.path.join(os.path.dirname(__file__), 'fixtures', request.function.__name__)
recorder.start()
request.addfinalizer(recorder.stop)
return session
Run Code Online (Sandbox Code Playgroud)
所以现在在我的测试中我只使用sessionfixture,我所做的每个请求都被自动序列化到fixtures/test_name.json文件中,所以下次我执行测试而不是做一个真正的HTTP请求库从文件系统加载它:
def test_if_response_is_ok(session):
r = session.get("http://google.com")
Run Code Online (Sandbox Code Playgroud)
它非常方便,因为为了使这些灯具保持最新,我只需要清理fixtures文件夹并重新运行我的测试.
Fab*_*zzo 32
我有一个类似的问题,我必须针对预期的文件测试配置文件.这就是我修复它的方式:
创建一个与测试模块名称相同且位于同一位置的文件夹.将所有预期的文件放在该文件夹中.
test_foo/
expected_config_1.ini
expected_config_2.ini
test_foo.py
Run Code Online (Sandbox Code Playgroud)创建一个夹具,负责将此文件夹的内容移动到临时文件.我确实使用了tmpdir夹具来解决这个问题.
from __future__ import unicode_literals
from distutils import dir_util
from pytest import fixture
import os
@fixture
def datadir(tmpdir, request):
'''
Fixture responsible for searching a folder with the same name of test
module and, if available, moving all contents to a temporary directory so
tests can use them freely.
'''
filename = request.module.__file__
test_dir, _ = os.path.splitext(filename)
if os.path.isdir(test_dir):
dir_util.copy_tree(test_dir, bytes(tmpdir))
return tmpdir
Run Code Online (Sandbox Code Playgroud)使用你的新夹具.
def test_foo(datadir):
expected_config_1 = datadir.join('expected_config_1.ini')
expected_config_2 = datadir.join('expected_config_2.ini')
Run Code Online (Sandbox Code Playgroud)请记住:datadir与tmpdir夹具相同,加上能够将预期文件放入具有测试模块名称的文件夹中.
我相信pytest-datafiles会有很大的帮助。不幸的是,它似乎不再被维护了。就目前而言,它运行良好。
这是来自文档的一个简单示例:
import os
import pytest
@pytest.mark.datafiles('/opt/big_files/film1.mp4')
def test_fast_forward(datafiles):
path = str(datafiles) # Convert from py.path object to path (str)
assert len(os.listdir(path)) == 1
assert os.path.isfile(os.path.join(path, 'film1.mp4'))
#assert some_operation(os.path.join(path, 'film1.mp4')) == expected_result
# Using py.path syntax
assert len(datafiles.listdir()) == 1
assert (datafiles / 'film1.mp4').check(file=1)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14769 次 |
| 最近记录: |