Pytest-xdist: 所有工作进程完成后的 tearDown

huangapple go评论69阅读模式
英文:

Pytest-xdist: tearDown after all workers finish

问题

当我正常运行pytest时,它运行得非常好(在第一个测试之前升级迁移,在最后一个测试之后降级迁移)。不使用xdist时,我只需将fixture范围设置为'session',它就可以正常工作。但是当我运行pytest-xdist(并行测试)时,它在每个测试之前升级迁移,并在每个测试之后降级迁移(我希望在第一个测试之前进行setUp - 第一个worker,并在最后一个测试之后进行tearDown - 当最后一个worker完成时)。
我认为在第一个worker之前进行setUp,我可以使用文件锁来处理(而且我不太需要它,因为在迁移升级中,我只是在需要时创建一些表,因此如果已经升级,它就不会执行任何操作)。
我特别关注最后一个worker完成后的tearDown。

import pytest
import os
import subprocess

@pytest.fixture(autouse=True, scope='session')
def handle_database():
    """在数据库中创建必要的表(使用迁移),并在测试后删除它们"""

    # 切换到 test/api_simulator 目录
    os.chdir('test/api_simulator')

    # 执行迁移升级
    subprocess.run(['flask', 'db', 'upgrade'])
    print('\n\n升级迁移\n\n')

    # 切换回原始目录
    os.chdir('../..')

    yield

    # 切换到 test/api_simulator 目录
    os.chdir('test/api_simulator')

    # 执行迁移降级
    subprocess.run(['flask', 'db', 'downgrade'])
    print('\n\n降级迁移\n\n')

    # 切换回原始目录
    os.chdir('../..')

我在网上搜索了这个问题,但在使用xdist的情况下找不到什么有关tearDown的好解决方案。

英文:

When I'm running pytest normally it works perfectly fine (before first test it's upgrading migration and after last test it's downgrading migration). Without using xdist I can just set fixture scope='session' and its work that way. But when I run pytest-xdist (tests in parallel) it's upgrading migration before each test and downgrading migration after each test (I want to setUp before first test - first worker, and tearDown after last test - when last worker finishes).
I think that setUp before first worker I can handle with File Lock (and also I don't need it that much because in migration upgrade I'm just creating some tables if not exist so if it was already upgraded it just won't do anything).
I'm interested especially in tearDown after last worker finshes.

import pytest
import os
import subprocess


@pytest.fixture(autouse=True, scope='session')
def handle_database():
    """Create necesarry tables in db (using migration) and drop them after tests"""

    # Change directory to test/api_simulator
    os.chdir('test/api_simulator')

    # Perform migration upgrade
    subprocess.run(['flask', 'db', 'upgrade'])
    print('\n\nUpgrade migration\n\n')

    # Change directory back to the original directory
    os.chdir('../..')

    yield

    # Change directory to test/api_simulator
    os.chdir('test/api_simulator')

    # Perform migration downgrade
    subprocess.run(['flask', 'db', 'downgrade'])
    print('\n\nDowngrade migration\n\n')

    # Change directory back to the original directory
    os.chdir('../..')

I was searching about this issue in web but I found nothing good about tearDown with xdist.

答案1

得分: 1

fixture 是作为测试的一部分运行的,即使它只在会话范围内运行一次。这意味着它在 xdist 打开的进程中运行。

要仅运行一次,请将代码移到 conftest.py 中的 pytest_sessionstartpytest_sessionfinish。这些方法将在 "常规" 范围内在 xdist 启动之前/之后执行一次。请注意,pytest_session 函数将再次作为测试周期的一部分运行,因此您需要检查它。

def __handle_database(config, command):
    if not hasattr(config, 'workerinput'):
        os.chdir('test/api_simulator')
    
        # 执行迁移升级
        subprocess.run(['flask', 'db', command])
        print('\n\n升级迁移\n\n')
    
        # 切换回原始目录
        os.chdir('../..')

def pytest_sessionstart(session):
    __handle_database(session.config, 'upgrade')

def pytest_sessionfinish(session, exitstatus):
    __handle_database(session.config, 'downgrade')
英文:

The fixture is running as part of a test, even if it's only once in session scope. This means it's running in the process xdist opened.

To run this only once you move the code to pytest_sessionstart and pytest_sessionfinish in conftest.py. Those methods will be executed once in
"regular" scope before/after xdist kicks in. Note that the pytest_session functions will run again as part of the tests cycle so you need to check it

def __handle_database(config, command):
    if not hasattr(config, 'workerinput'):
        os.chdir('test/api_simulator')
    
        # Perform migration upgrade
        subprocess.run(['flask', 'db', command])
        print('\n\nUpgrade migration\n\n')
    
        # Change directory back to the original directory
        os.chdir('../..')


def pytest_sessionstart(session):
    __handle_database(session.config, 'upgrade')


def pytest_sessionfinish(session, exitstatus):
    __handle_database(session.config, 'downgrade')

huangapple
  • 本文由 发表于 2023年7月10日 17:26:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76652410.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定