Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

539
Visualizações
How to make pytest wait for (manual) user action?

We are sucessfully using pytest (Python 3) to run a test suite testing some hardware devices (electronics). For a subset of these tests, we need the tester to change the hardware arrangement, and afterwards change it back. My approach was to use a module-level fixture attached to the tests in question (which are all in a separate module), with two input calls:

@pytest.fixture(scope="module")
def disconnect_component():
    input('Disconnect component, then press enter')
    yield  # At this point all the tests with this fixture are run
    input('Connect component again, then press enter')

When running this, I get OSError: reading from stdin while output is captured. I can avoid this by calling pytest with --capture=no, and have confirmed that my approach works, meaning I get the first query before the test subset in question, and the second one after they have run.

The big drawback is that this deactivates capturing stdin/stderr for the whole test suite, which some of the other test rely on.

I also tried to use capsys.disabled (docs) like this

@pytest.fixture(scope="module")
def disconnect_component(capsys):
    with capsys.disabled():
        input('Disconnect component, then press enter')
        yield  # At this point all the tests with this fixture are run
        input('Connect component again, then press enter')

but when running this I get ScopeMismatch: You tried to access the 'function' scoped fixture 'capsys' with a 'module' scoped request object, involved factories.

Can I make pytest wait for user action in some other way than input? If not, can I disable capturing just for the tests using above fixture?

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

So, I found a hint by a pytest dev, based on which I basically do what the capsys.disable() function does:

@pytest.fixture(scope="module")
def disconnect_component(pytestconfig):
    capmanager = pytestconfig.pluginmanager.getplugin('capturemanager')

    capmanager.suspend_global_capture(in_=True)
    input('Disconnect component, then press enter')
    capmanager.resume_global_capture()

    yield  # At this point all the tests with this fixture are run

    capmanager.suspend_global_capture(in_=True)
    input('Connect component again, then press enter')
    capmanager.resume_global_capture()

This works flawlessly as far as I can see. Don't forget the in_=True bit.

Edit: From pytest 3.3.0 (I think), capmanager.suspendcapture and capmanager.resumecapture were renamed to capmanager.suspend_global_capture and capmanager.resume_global_capture, respectively.

over 4 years ago · Santiago Trujillo Relatório

0

As of pytest 5, as a fixture, you can use this:

@pytest.fixture
def suspend_capture(pytestconfig):
    class suspend_guard:
        def __init__(self):
            self.capmanager = pytestconfig.pluginmanager.getplugin('capturemanager')
        def __enter__(self):
            self.capmanager.suspend_global_capture(in_=True)
        def __exit__(self, _1, _2, _3):
            self.capmanager.resume_global_capture()

    yield suspend_guard()

Example usage:

def test_input(suspend_capture):
    with suspend_capture:
        input("hello")
over 4 years ago · Santiago Trujillo Relatório

0

Maybe it's worth noting that above solution doesn't have to be in a fixture. I've made a helper function for that:

import pytest

def ask_user_input(msg=''):
    """ Asks user to check something manually and answer a question
    """
    notification = "\n\n???\tANSWER NEEDED\t???\n\n{}".format(msg)

    # suspend input capture by py.test so user input can be recorded here
    capture_manager = pytest.config.pluginmanager.getplugin('capturemanager')
    capture_manager.suspendcapture(in_=True)

    answer = raw_input(notification)

    # resume capture after question have been asked
    capture_manager.resumecapture()

    logging.debug("Answer: {}".format(answer))
    return answer
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda