2013-05-06 14 views
32

Per Jedi vogliamo generare la nostra test coverage. C'è uno related question nello stackoverflow, ma non è stato d'aiuto.Utilizzando py.test con una copertura non include le importazioni

Stiamo usando py.test come test runner. Tuttavia, non siamo in grado di aggiungere le importazioni e altre cose "importate" al rapporto. Ad esempio __init__.py è sempre riportato come essendo coperto:

Name       Stmts Miss Cover 
-------------------------------------------------- 
jedi/__init__      5  5  0% 
[..] 

Chiaramente questo file viene importato e deve pertanto essere segnalato come esaminato.

Iniziamo test come questo [*]:

py.test --cov jedi 

Come si può vedere che stiamo usando pytest-coverage.

Così come è possibile contare correttamente la copertura di file come __init__.py?

[*] Abbiamo anche provato a iniziare il test senza --doctest-modules (rimosso da pytest.ini) e attivare il modulo di copertura in precedenza da py.test -p pytest_cov --cov jedi. Nessuno di loro funziona.

Ho offerto una taglia. Si prega di provare a risolvere il problema all'interno di Jedi. È pubblicamente disponibile.

+0

hai un file conftest.py che importa "jedi" per caso? Suppongo che dopo l'inizializzazione di pytest (che include la lettura dei file conftest.py in CWD e test */se esiste) il tuo jedi è già stato importato. – hpk42

+0

Sì. Abbiamo un 'conftest.py'. Importa indirettamente 'jedi'. Tuttavia, spostare queste importazioni indirette nelle funzioni, anche non ha aiutato (o è anche un problema ???). Il file è qui: https://github.com/davidhalter/jedi/blob/master/test/conftest.py –

+0

Che cosa è * in * '__init __. Py'? Per esempio, importando una funzione non è come eseguirla. –

risposta

51

@hynekcer mi ha dato l'idea giusta. Ma fondamentalmente la soluzione più semplice si trova altrove:

Sbarazzarsi di pytest-cov!

Usa

coverage run --source jedi -m py.test 
coverage report 

invece !!! In questo modo stai solo eseguendo una copertura sulla tua attuale configurazione py.test, che funziona perfettamente! È anche filosoficamente la strada giusta da fare: fare in modo che ogni programma faccia una cosa bene - py.test esegue test e coverage controlla la copertura del codice.

Ora questo potrebbe sembrare uno sproloquio, ma davvero. pytest-cov non funziona correttamente da un po 'di tempo. Alcuni test stavano fallendo, solo perché lo abbiamo usato.


A partire dal 2014 , pytest-CoV sembra avere le mani cambiato. py.test --cov jedi test sembra essere di nuovo un comando utile (guarda i commenti). Tuttavia, non è necessario usarlo. Ma in combinazione con xdist può accelerare i rapporti di copertura.

+0

Esiste una versione di sviluppo di pytest-cov che raccoglie correttamente la copertura per conftest: https://github.com/schlamar/pytest-cov/pull/4. Sembra bello correre contro jedi: https://gist.github.com/schlamar/7722c21c3f2f1b97c920. Non esitate a inviare ulteriori problemi (ho appena iniziato a mantenere questo pacchetto). – schlamar

+3

@schlamar: la domanda è: perché avremmo bisogno di un pacchetto 'pytest-cov' se i comandi sopra funzionano perfettamente? –

+1

supporto per xdist che riduce la durata del test di quasi il 50%: https://gist.github.com/schlamar/7722c21c3f2f1b97c920#file-gistfile2-txt + less comandi per digitare e ricordare – schlamar

6

ho fissato la copertura di test al 94% da this patch che semplifica le dipendenze di importazione e dal comando:

py.test --cov jedi test     # or 
py.test --cov jedi test --cov-report=html # + a listing with red uncovered lines 

linee scoperti sono solo in comandi condizionali o in alcune funzioni meno utilizzate, ma tutte le intestazioni siano completamente coperto.

Il problema era che la configurazione dei test test/conftest.py ha importato prematuramente dalle dipendenze quasi tutti i file nel progetto. Il file conftest definisce anche ulteriori opzioni e impostazioni da riga di comando che dovrebbero essere impostate prima di eseguire il test. Quindi penso che il plugin pytest_cov funzioni correttamente se ignora tutto ciò che è stato importato insieme a questo file, anche se è un dolore. Ho escluso anche il rapporto __init__.py e settings.py perché sono semplici e con la copertura completa, ma vengono anche importati prematuramente nella dipendenza di conftest.

+0

Come discusso su github (https: // github.com/davidhalter/jedi/pull/214) otterrai la taglia, perché mi hai dato l'idea giusta. tuttavia, questo non ha funzionato. –

1

Ho avuto questo problema con py.test, la copertura e il plugin django. Apparentemente i file modello vengono importati prima dell'avvio della copertura. Neanche "-p coverage" per il caricamento anticipato del plugin di copertura ha funzionato.

ho riparato rimuovendo il modulo di modelli da sys.modules e ri-importarlo nel file di test che mette alla prova il modello (brutto?):

import sys 
del sys.modules['project.my_app.models'] 
from project.my_app import models 

def test_my_model(): 
    ... 
2

Nel mio caso, eseguire tutti i test, ma la copertura era dello 0%.

La correzione era:

$ export PYTHONPATH="." 

Dopo i risultati sono stati corretti.

Avevo in passato pochi problemi con il comando py.test avente problemi di importare qualcosa e l'impostazione PYTHONPATH env var era la soluzione. Ha funzionato anche per me questa volta.

Il mio vero esempio con awslogs

Prima con PYTHONPATH unset:

$ py.test --cov=awslogs tests/ 
========================================= test session starts ========================================= 
platform linux2 -- Python 2.7.9, pytest-2.8.5, py-1.4.31, pluggy-0.3.1 
rootdir: /home/javl/sandbox/awslogs/github/awslogs, inifile: 
plugins: cov-2.2.0 
collected 11 items 

tests/test_it.py ...........Coverage.py warning: No data was collected. 

--------------------------- coverage: platform linux2, python 2.7.9-final-0 --------------------------- 
Name     Stmts Miss Cover 
------------------------------------------- 
awslogs/__init__.py   2  2  0% 
awslogs/bin.py    85  85  0% 
awslogs/core.py   143 143  0% 
awslogs/exceptions.py  12  12  0% 
------------------------------------------- 
TOTAL      242 242  0% 

====================================== 11 passed in 0.38 seconds ====================================== 

risultante copertura è 0%.

Poi ho impostato il PYTHONPATH:

$ export PYTHONPATH="." 

ed eseguire nuovamente il test:

$ py.test --cov=awslogs tests/ 
========================================= test session starts ========================================= 
platform linux2 -- Python 2.7.9, pytest-2.8.5, py-1.4.31, pluggy-0.3.1 
rootdir: /home/javl/sandbox/awslogs/github/awslogs, inifile: 
plugins: cov-2.2.0 
collected 11 items 

tests/test_it.py ........... 
--------------------------- coverage: platform linux2, python 2.7.9-final-0 --------------------------- 
Name     Stmts Miss Cover 
------------------------------------------- 
awslogs/__init__.py   2  0 100% 
awslogs/bin.py    85  9 89% 
awslogs/core.py   143  12 92% 
awslogs/exceptions.py  12  2 83% 
------------------------------------------- 
TOTAL      242  23 90% 

====================================== 11 passed in 0.44 seconds ====================================== 

Ora è la copertura del 90%.

ATTENZIONE: la manipolazione di PYTHONPATH può avere strani effetti collaterali. Attualmente mi imbatto in un problema, che il pacchetto basato su pbr sta creando la directory egg quando si costruisce distribuibile e se PYTHONPATH è impostato su ".", Considera automaticamente il pacchetto relativo all'uovo come installato. Per questo motivo ho smesso di usare pytest-cov e seguire il consiglio di utilizzare lo strumento coverage.

+1

Conosci 'pip install -e .'? Questo ti permette di installare una versione di sviluppo del tuo software e potrebbe essere il problema che hai qui (non incluso in 'sys.path'). –

+0

@DaveHalter Grazie, buona idea. Sicuramente conosco 'pip install -e .' Tuttavia, quando si installa da' pip install .' (senza l'opzione '-e'), il semplice comando' coverage' gestisce la copertura correttamente ma 'py.test --cov == awslogs -m py.test -sv tests' no. –