我已经为Flask应用实施了单元测试。我用pytest。我的目标是确保许多预定义查询始终返回相同的输出(某些json)。
为此,我使用夹具来启动具有测试设置的应用程序:
# Session for scope, otherwise server is reloaded everytime
@pytest.fixture(scope="session")
def app():
os.environ["FLASK_ENV"] = "development"
os.environ["TEST_SETTINGS"] = os.path.join(
ds.WORK_DIR, "..", "tests", "settings.py"
)
app = create_app()
# http://flask.pocoo.org/docs/1.0/api/#flask.Flask.test_client
app.testing = True
return app
然后我用pytest运行一个测试函数,它实际上不是一个测试函数:
# Freeze time for consistent output
@pytest.mark.usefixtures("live_server")
@pytest.mark.freeze_time("2018-01-01")
class TestLiveServer:
@pytest.mark.skip(reason="should only be used to update the test data")
def test_export(self):
"""Not a test function.
Used to export questions outputs in json file to freeze the expected output
"""
for q in TESTED_QUESTIONS:
r = requests.post(
url_for("query_direct", _external=True), json={"query": q}
)
print(r.text)
filename = (
"".join(filter(lambda c: str.isalnum(c) or c == " ", q))
.lower()
.replace(" ", "_")
+ ".json"
)
export_path = os.path.join("tests", "fake_responses", filename)
data = {"query": q, "response": r.json()}
with open(export_path, "w") as outfile:
json.dump(data, outfile, indent=4, sort_keys=True)
outfile.write("\n")
要生成冻结的输出,请取消注释pytest标记,然后运行此特定测试。如您所见,它不是很优雅并且容易出错。有时我忘记重新启用标记,并且如果我一次运行所有测试,它会先重新生成假输出,然后再对它们进行单元测试。如果发生这种情况,我的测试不会失败,我也不会发现潜在的错误(这会扼杀这些测试的重点)。
是否有一种方法可以单独运行此特定功能,也许带有一些pytest标志或其他东西?
答案 0 :(得分:1)
这可能应该是一个独立的东西,而不是pytest测试套件的一部分(因为它不是测试),但是您可以利用pytest的skipping facilities来解决它。
# redefine test_export to feature a conditional skip
@pytest.mark.skipif(not os.getenv('FREEZE_OUTPUTS'), reason='')
def test_export(self):
除非设置了FREEZE_OUTPUTS
环境变量,否则我们将跳过此测试。
然后您可以通过在命令行中调用以下命令来运行此测试(仅为此调用定义环境变量):
$ FREEZE_OUTPUTS=1 py.test <your_test_file>::TestLiveServer::test_export
将仅运行该测试。在所有其他情况下,它将被跳过。
您甚至可以遵循上述方法,并将其声明为包含在autouse=True
session level的so it's always included上的灯具,然后在灯具本身中添加一些逻辑来检查您是否已经定义了FREEZE_OUTPUTS
,如果已定义,请运行有问题的逻辑。像这样:
@pytest.fixture(scope='session', autouse=True)
def frozen_outputs():
if os.getenv('FREEZE_OUTPUTS'):
# logic for generating the outputs goes here
return # do nothing otherwise