使用pytest读写文件的模式
Pattern for reading and writing files with pytest
constants.py
import os
BASE_PATH = os.path.abspath(os.path.dirname(__file__))
INPUT_PATH = os.path.join(BASE_PATH, 'input')
FILE_INPUT1_PATH = os.path.join(INPUT_PATH, 'input1.csv')
FILE_INPUT2_PATH = os.path.join(INPUT_PATH, 'input2.csv')
PROCESSED_PATH = os.path.join(BASE_PATH, 'processed')
FILE_PROC1_PATH = os.path.join(PROCESSED_PATH, 'processed1.pkl')
FILE_PROC2_PATH = os.path.join(PROCESSED_PATH, 'processed2.pkl')
结构目录:
root
|__ constant.py
|__ input
|__ input1.csv
|__ input2.csv
|__ process
|__ processed1.pkl
|__ processed2.pkl
data_handling.py
from constants import FILE_INPUT1_PATH, FILE_INPUT2_PATH, FILE_PROC1_PATH, FILE_PROC2_PATH
def foo(*args):
file = FILE_INPUT1_PATH
# Here it is doing staff
# Finally I write data into FILE_PROC1_PATH
def bar(*args):
file = FILE_INPUT2_PATH
# Here it is doing staff
# Finally I write data into FILE_PROC2_PATH
目前我正在尝试使用 pytest 并测试 foo()
和 bar()
但由于输入文件和已处理文件太大且测试过程无效,我不知道如何继续' t 覆盖处理过的文件。
一种方法是将定义 bar()
更改为 bar(path)
然后调用 bar(FILE_INPUT2_PATH)
但这在代码中没有意义,因为 bar
总是需要读取 FILE_INPUT2_PATH
很多地方都这么叫。
foo() 和 bar() 的单元测试将测试是否创建了已处理的文件,因为它取决于 *args
.
所以...问题是我该如何解决?这种情况下是否存在 pattern/good 实践?我应该在我的代码中更改什么?
input files and processed files are too big and test process musn't
override processed files
是的,测试非常适合那种工作。通用方法是创建一个测试数据(可以是原始数据的子集,包括边缘情况)并将其放置在测试附近的某个位置,例如:
├───tests
│ │ test_bar.py
│ │ test_foo.py
│ │
│ └───data
│ input_1.dat
│ input_2.dat
│ expected_1.pkl
│ expected_2.pkl
然后,如果测试函数接受输入作为常量而不是参数,请使用 unittest.mock.patch
to change constant in test run (see this excellent answer 作为快速参考)。可以使用常规文件或临时文件来存储输出。
import tempfile
from pathlib import Path
from unittest.mock import patch
import foo_module
TEST_DATA_DIR = Path(__file__).resolve().parent / 'data'
@patch('foo_module.FILE_INPUT1_PATH', TEST_DATA_DIR / 'input_1.dat')
@patch('foo_module.FILE_PROC1_PATH', tempfile.mktemp())
def test_foo(tmpdir):
"""Process input and check result."""
foo_module.foo()
result = open(foo_module.FILE_PROC1_PATH, 'rb').read()
expected = open(TEST_DATA_DIR / 'expected_1.pkl', 'rb').read()
assert result == expected
注意: tempfile.mktemp()
已弃用,因为文件不是在 mktemp()
调用时创建的,因此可以被另一个进程锁定。欢迎提出替代方法。
constants.py
import os
BASE_PATH = os.path.abspath(os.path.dirname(__file__))
INPUT_PATH = os.path.join(BASE_PATH, 'input')
FILE_INPUT1_PATH = os.path.join(INPUT_PATH, 'input1.csv')
FILE_INPUT2_PATH = os.path.join(INPUT_PATH, 'input2.csv')
PROCESSED_PATH = os.path.join(BASE_PATH, 'processed')
FILE_PROC1_PATH = os.path.join(PROCESSED_PATH, 'processed1.pkl')
FILE_PROC2_PATH = os.path.join(PROCESSED_PATH, 'processed2.pkl')
结构目录:
root
|__ constant.py
|__ input
|__ input1.csv
|__ input2.csv
|__ process
|__ processed1.pkl
|__ processed2.pkl
data_handling.py
from constants import FILE_INPUT1_PATH, FILE_INPUT2_PATH, FILE_PROC1_PATH, FILE_PROC2_PATH
def foo(*args):
file = FILE_INPUT1_PATH
# Here it is doing staff
# Finally I write data into FILE_PROC1_PATH
def bar(*args):
file = FILE_INPUT2_PATH
# Here it is doing staff
# Finally I write data into FILE_PROC2_PATH
目前我正在尝试使用 pytest 并测试 foo()
和 bar()
但由于输入文件和已处理文件太大且测试过程无效,我不知道如何继续' t 覆盖处理过的文件。
一种方法是将定义 bar()
更改为 bar(path)
然后调用 bar(FILE_INPUT2_PATH)
但这在代码中没有意义,因为 bar
总是需要读取 FILE_INPUT2_PATH
很多地方都这么叫。
foo() 和 bar() 的单元测试将测试是否创建了已处理的文件,因为它取决于 *args
.
所以...问题是我该如何解决?这种情况下是否存在 pattern/good 实践?我应该在我的代码中更改什么?
input files and processed files are too big and test process musn't override processed files
是的,测试非常适合那种工作。通用方法是创建一个测试数据(可以是原始数据的子集,包括边缘情况)并将其放置在测试附近的某个位置,例如:
├───tests
│ │ test_bar.py
│ │ test_foo.py
│ │
│ └───data
│ input_1.dat
│ input_2.dat
│ expected_1.pkl
│ expected_2.pkl
然后,如果测试函数接受输入作为常量而不是参数,请使用 unittest.mock.patch
to change constant in test run (see this excellent answer 作为快速参考)。可以使用常规文件或临时文件来存储输出。
import tempfile
from pathlib import Path
from unittest.mock import patch
import foo_module
TEST_DATA_DIR = Path(__file__).resolve().parent / 'data'
@patch('foo_module.FILE_INPUT1_PATH', TEST_DATA_DIR / 'input_1.dat')
@patch('foo_module.FILE_PROC1_PATH', tempfile.mktemp())
def test_foo(tmpdir):
"""Process input and check result."""
foo_module.foo()
result = open(foo_module.FILE_PROC1_PATH, 'rb').read()
expected = open(TEST_DATA_DIR / 'expected_1.pkl', 'rb').read()
assert result == expected
注意: tempfile.mktemp()
已弃用,因为文件不是在 mktemp()
调用时创建的,因此可以被另一个进程锁定。欢迎提出替代方法。