Pytest在哪里存储预期的数据

Glu*_*eon 24 python pytest

测试功能我需要传递参数并查看输出与预期输出匹配.

当函数的响应只是一个小数组或可以在测试函数中定义的单行字符串时很容易,但假设我测试的函数修改了一个可能很大的配置文件.或者,如果我明确定义它,结果数组就会长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

我有一个类似的问题,我必须针对预期的文件测试配置文件.这就是我修复它的方式:

  1. 创建一个与测试模块名称相同且位于同一位置的文件夹.将所有预期的文件放在该文件夹中.

    test_foo/
        expected_config_1.ini
        expected_config_2.ini
    test_foo.py
    
    Run Code Online (Sandbox Code Playgroud)
  2. 创建一个夹具,负责将此文件夹的内容移动到临时文件.我确实使用了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)
  3. 使用你的新夹具.

    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)

请记住:datadirtmpdir夹具相同,加上能够将预期文件放入具有测试模块名称的文件夹中.

  • 在python 3上,`dir_util.copy_tree(test_dir,str(tmpdir))`是必需的. (5认同)
  • 这具有额外的好处,即测试不会相互干扰,因为每个测试都将具有数据文件的副本. (2认同)
  • 这是正确的。这样您就可以使用多个内核运行测试,而不必担心资源(在本例中为预期文件)的并发性。 (2认同)
  • 是的,也许我会这样做,但我认为那可能太笨拙了。顺便说一句,我没有得到资源并发的东西。文件是只读的,可能会出错吗? (2认同)
  • 你是对的。对于只读文件,一切都应该正常工作,除非此类文件由于某种原因被锁定。创建或更改多个测试使用的文件时,并发问题经常发生。 (2认同)

Dro*_*ror 5

我相信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)

  • 来自链接的 PyPi 条目:关于维护的注意事项:该项目得到维护,错误报告或拉取请求将得到解决。几乎没有什么活动,因为它只是工作并且不需要任何更改。 (12认同)
  • 还有[pytest-datadir](https://github.com/gabrielcnr/pytest-datadir) (2认同)