2015-11-03 8 views
24

DomandaCreare e importare aiutante funzioni nei test senza creare pacchetti nella directory di prova utilizzando py.test

Come posso importare le funzioni di supporto a file di test senza creare pacchetti nella directory test?


Contesto

Mi piacerebbe creare una funzione di test di supporto che posso importare in diversi test. Di ', qualcosa di simile:

# In common_file.py 

def assert_a_general_property_between(x, y): 
    # test a specific relationship between x and y 
    assert ... 


# In test/my_test.py 

def test_something_with(x): 
    some_value = some_function_of_(x) 
    assert_a_general_property_between(x, some_value) 

Usare Python 3.5, con py.test 2.8.2


"soluzione" Current

Attualmente sto facendo questo tramite l'importazione di un modulo all'interno della directory test del mio progetto (che ora è un pacchetto), ma mi piacerebbe farlo con qualche altro meccanismo se possibile (in modo che la mia directory test non abbia pacchetti ma solo test e i test possano essere eseguiti su una versione installata del pacchetto, come raccomandato here in the py.test documentation on good practices).

+1

Sembra pazzesco che pytest scoragga i file '__init __. Py', ma allo stesso tempo non fornisce alternative alla condivisione delle funzioni di supporto tra i test. I miei capelli stanno diventando grigi su questo. – qff

risposta

18

la mia opzione è creare una dir aggiuntiva nella directory tests e aggiungerla a pythonpath nel conftest in modo tale.

tests/ 
    helpers/ 
     utils.py 
     ... 
    conftest.py 
setup.cfg 

nel conftest.py

import sys 
import os 
sys.path.append(os.path.join(os.path.dirname(__file__), 'helpers')) 

in setup.cfg

[pytest] 
norecursedirs=tests/helpers 

questo modulo sarà disponibile con `utils all'importazione, solo fare attenzione a nome contrastanti.

+1

Questa soluzione mi è piaciuta molto, soprattutto perché mantiene la configurazione del percorso di importazione del codice con i test ", il che, per me, rende più semplice la progettazione. Grazie! –

+1

Penso che 'norecursdirs = tests/utils' avrebbe dovuto essere' norecursedirs = test/helper' (notare l'aggiunta della e in recurse). È corretto? –

+0

@Eliza hai ragione. aggiorna semplicemente la mia risposta. – sax

9

Durante la ricerca di una soluzione per questo problema mi sono imbattuto in questa domanda SO e ho finito per adottare lo stesso approccio. Creazione di un pacchetto di aiutanti, munging sys.path per renderlo importabile e quindi solo importarlo ...

Questo non sembrava l'approccio migliore, quindi, ho creato pytest-helpers-namespace. Questo plugin permette di registrare le funzioni di supporto sul tuo conftest.py:

import pytest 

pytest_plugins = ['helpers_namespace'] 

@pytest.helpers.register 
def my_custom_assert_helper(blah): 
    assert blah 

# One can even specify a custom name for the helper 
@pytest.helpers.register(name='assertme') 
def my_custom_assert_helper_2(blah): 
    assert blah 

# And even namespace helpers 
@pytest.helpers.asserts.register(name='me') 
def my_custom_assert_helper_3(blah): 
    assert blah 

E poi, all'interno di un corpo di una funzione di test case semplicemente utilizzarlo come

def test_this(): 
    assert pytest.helpers.my_custom_assert_helper(blah) 

def test_this_2(): 
    assert pytest.helpers.assertme(blah) 

def test_this_3(): 
    assert pytest.helpers.asserts.me(blah) 

sua piuttosto semplice e la documentazione piuttosto piccola. Dai un'occhiata e dimmi se risponde anche al tuo problema.

+0

Fantastico, darò un'occhiata. Grazie! –

+0

Ho provato questo, ma ottengo sempre errori 'RuntimeError: l'helper chiamato non è stato registrato'. –

+0

Per favore, puoi presentare un ticket contro il plugin con un esempio di come attivare il tuo RuntimeError. https://github.com/saltstack/pytest-helpers-namespace – s0undt3ch

-1

Come ulteriore opzione, questa struttura di directory ha lavorato per me:

mypkg/ 
    ... 
test_helpers/ 
    __init__.py 
    utils.py 
    ... 
tests/ 
    my_test.py 
    ... 

E poi nel my_test.py importazione delle utilità utilizzando: from test_helpers import utils

+0

Credo che questa sia la stessa situazione che descrivo nella domanda, in cui codice e test non sono chiaramente separati. Per le versioni e simili, dovresti pensare ad escludere anche 'test_helpers', ad esempio. –

5

è possibile definire una classe di supporto in conftest.py, quindi creare una fixture che restituisce quella classe (o un'istanza di essa, a seconda di ciò che ti serve).

import pytest 


class Helpers: 
    @staticmethod 
    def help_me(): 
     return "no" 


@pytest.fixture 
def helpers(): 
    return Helpers 

Poi nei test, è possibile utilizzare l'apparecchio:

def test_with_help(helpers): 
    helpers.help_me() 
0

Creare un pacchetto di aiutanti nella cartella test: tests/ helpers/ __init__.py utils.py ... # make sure no __init__.py in here! setup.cfg

in setup.cfg: [pytest] norecursedirs=tests/helpers

gli helper saranno disponibili con import helpers.