测试函数我需要传递参数并查看输出与预期输出匹配。

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

我看到这种方法有很多问题,比如保持这个文件是最新的问题。它看起来也很糟糕。
我可以让事情变得更好,将它移到固定装置上:
@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)

这只是将问题移到另一个地方,通常我需要测试函数在空输入、输入单个项目或多个项目的情况下是否有效,所以我应该创建一个包含所有三个案例或多个夹具的大夹具。最后代码变得相当困惑。

如果一个函数需要一个复杂的字典作为输入或返回相同大小的字典,测试代码就会变得丑陋:
 @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]}

使用此类装置阅读测试并使其保持最新是非常困难的。

更新

搜索了一段时间后,我找到了一个库,它解决了一个问题的一部分,而不是大的配置文件,我有大的 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

所以现在在我的测试中,我只使用 session 固定装置,我发出的每个请求都会自动序列化到 fixtures/test_name.json 文件,因此下次我执行测试而不是执行真正的 HTTP 请求库时,会从文件系统加载它:
def test_if_response_is_ok(session):
   r = session.get("http://google.com")

这非常方便,因为为了使这些装置保持最新状态,我只需要清理 fixtures 文件夹并重新运行我的测试。

最佳答案

我曾经遇到过类似的问题,我必须针对预期文件测试配置文件。这就是我修复它的方式:

  • 在相同位置创建一个与测试模块同名的文件夹。将所有预期的文件放在该文件夹中。
    test_foo/
        expected_config_1.ini
        expected_config_2.ini
    test_foo.py
    
  • 创建一个夹具,负责将这个文件夹的内容移动到一个临时文件中。我确实为此使用了 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
    

    重要提示: 如果您使用的是 Python 3,请将 dir_util.copy_tree(test_dir, bytes(tmpdir)) 替换为 dir_util.copy_tree(test_dir, str(tmpdir))
  • 使用您的新夹具。
    def test_foo(datadir):
        expected_config_1 = datadir.join('expected_config_1.ini')
        expected_config_2 = datadir.join('expected_config_2.ini')
    

  • 请记住:datadirtmpdir 夹具相同,加上处理放置在具有测试模块名称的文件夹中的预期文件的能力。

    关于python - Pytest 存储预期数据的位置,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29627341/

    10-13 08:37