使用特定设置启动Flask应用,运行查询并存储测试的响应

时间:2019-03-20 10:59:02

标签: python pytest

我已经为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标志或其他东西?

1 个答案:

答案 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 levelso 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