2014-10-18 16 views
5

Używam nosa do testowania kolekcji i również chcę korzystać z jego wtyczki doctest. Mam moduł, który potrzebuje urządzenia, aby można go było importować. Dlatego nie mogę używać modułów nosa, ponieważ są one ładowane z testowanego modułu. Czy istnieje sposób na określenie ustawień modułów dla nosa-doctest poza modułem?Moduł modułu nosa-doctest przed zaimportowaniem modułu

W przypadku niektórych przypadków przydatna byłaby możliwość wykrycia bycia uruchamianym w trybie doctest i zastosowania urządzenia na początku modułu. Byłbym zainteresowany usłyszeniem odpowiedzi na ten przypadek użycia.

Istnieją jednak sytuacje, w których to nie może działać: Gdy import nie powiedzie się z powodu SyntaxError, żaden kod modułu nigdy nie zostanie uruchomiony. W moim przypadku głównie rozwijam kod, który jest kompatybilny z python 2 i python 3 (bez 2to3). Istnieje jednak kilka specyficznych modułów python 3, które po prostu nie powinny być sprawdzane przez nos, kiedy działają pod pytonem 2. Jaka byłaby tu moja najlepsza opcja?

EDIT: MWE (dla sytuacji SyntaxError)

Mam pakiet z wielu małych modułów, niektóre z nich korzysta Python 3 składnię. Oto struktura pakietu:

~/pckg/ 
    __init__.py 
    py3only.py 
    ... (other modules) 
    tests/ 
    test_py3only.py 

Niektóre testy są pisane jako unittest.TestCase, ale chcę również przykłady kodu w badanych docstrings. ~/pckg/__init__.py jest pusty.

~/pckg/py3only.py:

def fancy_py3_func(a:"A function argument annotation (python 3 only syntax)"): 
    """ A function using fancy syntax doubling it's input. 

    >>> fancy_py3_func(4) 
    8 
    """ 
    return a*2 

~/pckg/testy/test_py3only.py:

import sys, unittest 

def setup_module(): 
    if sys.version_info[0] < 3: 
     raise unittest.SkipTest("py3only unavailable on python "+sys.version) 

class TestFancyFunc(unittest.TestCase): 
    def test_bruteforce(self): 
     from pckg.py3only import fancy_py3_func 
     for k in range(10): 
      self.assertEqual(fancy_py3_func(k),2*k) 

Testowanie na Pythonie 3, wszystko zostanie sprawdzone i karnety (biegnie od folder np ~) obejmującą:

~ nosetests3 -v --with-doctest pckg 
Doctest: pckg.py3only.fancy_py3_func ... ok 
test_bruteforce (test_py3only.TestFancyFunc) ... ok 

Na pytona 2, urządzenie moduł ~/pckg/tests/test_py2only.py prawidłowo wykrywa sytuację i pomija test. Jednak otrzymujemy SyntaxError z ~/pckg/py3only.py:

~ nosetests -v --with-doctest pckg 
Failure: SyntaxError (invalid syntax (py3only.py, line 1)) ... ERROR 
SKIP: py3only unavailable on python 2.7.6 (default, Mar 22 2014, 22:59:56) 

funkcję podobną do ~/pckg/tests/test_py3only.py:setup_module() może rozwiązać ten problem, czy mogę dostać nose uruchomić ten kod, zanim będzie doctest plugin nawet próbuje zaimportować ten moduł.

Wygląda jak moja Najprościej jest napisać odpowiedni skrypt testowy najwyższego poziomu, który obsługuje zbiór testów ...

+0

moduł nie mogą być importowane bez X lub Y pachnie źle, to znaczy, na przykład, że ani '' pylint' pydoc' nie może być stosowany na kodzie. Zmiana modułu w czasie importu, ponieważ jest w fazie testowej, pokonuje cały punkt testowania, czyż nie? –

+0

Mam zasadniczo dwa przypadki: brakujące _optional_ zewnętrznych zależności i moduły przy użyciu nowej składni Pythona 3, testowane w python 2. W obu przypadkach testowanie jest zasadniczo próżne, moduły są niedostępne. Chcę wyłączyć błędy testowe i może zastąpić je komunikatami, że jakaś część biblioteki jest niedostępna z powodu braku zależności. – burnpanck

+0

'nosetests -v --with-doctest pckg' pozwalasz Pythonowi 2 zobaczyć kod Pythona 3, ponieważ uruchamiasz' --with-doctest' z górnego katalogu. Uruchom testy zarówno unittest, jak i doctest z folderu 'tests'. Aby doctest powiodło się, wyodrębnij go do zwykłego pliku tekstowego, tak jak zrobiłem to, abyś mógł warunkowo zaimportować. –

Odpowiedz

2

Określone pliki testowe, katalogi, klasy lub metody można wyłączyć przy użyciu wtyczki nosowej nose-exclude. Ma opcje --exclude-*.

Aby obsłużyć brakujące moduły, należy załatać numer sys.modules przy użyciu mock.

F.e, Jest klasa Calc w module mycalc, ale nie mam do niej dostępu, ponieważ jej brakuje. I są jeszcze dwa moduły: mysuper_calc i mysuper_calc3, ten ostatni jest specyficzny dla Pythona 3. Te dwa moduły, importujące mycalc i mysuper_calc3, nie powinny być testowane w Pythonie 2. Jak doctest je z modułu, który jest w pliku tekstowym? Zakładam, że to sytuacja OP.

calc/mysuper_calc3.py

from sys import version_info 
if version_info[0] != 3: 
    raise Exception('Python 3 required') 
from mycalc import Calc 
class SuperCalc(Calc): 
    '''This class implements an enhanced calculator 
    ''' 
    def __init__(self): 
     Calc.__init__(self) 

    def add(self, n, m): 
     return Calc.add(self, n, m) 

calc/mysuper_calc.py

from mycalc import Calc 

class SuperCalc(Calc): 
    '''This class implements an enhanced calculator 
    ''' 
    def __init__(self): 
     Calc.__init__(self) 

    def add(self, n, m): 
     return Calc.add(self, n, m) 

Teraz wyśmiewać się mycalc,

>>> from mock import Mock, patch 
>>> mock = Mock(name='mycalc') 

Moduł mycalc ma klasę Calc który ma metodę add . Testuję metodę instancji add z 2+3.

>>> mock.Calc.add.return_value = 5 

Teraz załatać sys.modules i mysuper_calc3 można warunkowo przywiezione w bloku with.

>>> with patch.dict('sys.modules',{'mycalc': mock}): 
...  from mysuper_calc import SuperCalc 
...  if version_info[0] == 3: 
...   from mysuper_calc3 import SuperCalc 

calc/doctest/mysuper_calc_doctest.txt

>>> from sys import version_info 
>>> from mock import Mock, patch 
>>> mock = Mock(name='mycalc') 
>>> mock.Calc.add.return_value = 5 

>>> with patch.dict('sys.modules',{'mycalc': mock}): 
...  from mysuper_calc import SuperCalc 
...  if version_info[0] == 3: 
...   from mysuper_calc3 import SuperCalc 
>>> c = SuperCalc() 
>>> c.add(2,3) 
5 

Plik mysuper_calc_doctest.txt musi być sam w swoim katalogu inaczej nosetests wyszukuje doctest w modułach non-badawczych.

PYTHONPATH=.. nosetests --with-doctest --doctest-extension=txt --verbosity=3 

Doctest: mysuper_calc_doctest.txt ... ok


Ran 1 test w 0.038s

OK

otoki wokół nosetests wykryć Python 3, który przechodzi .py pliki bez błędów składniowych do nosetests

mynosetests.py

import sys 
from subprocess import Popen, PIPE 
from glob import glob 

f_list = [] 

py_files = glob('*py') 
try: 
    py_files.remove(sys.argv[0]) 
except ValueError: 
    pass 

for py_file in py_files: 
    try: 
     exec open(py_file) 
    except SyntaxError: 
     continue 
    else: 
     f_list.append(py_file) 

proc = Popen(['nosetests'] + sys.argv[1:] + f_list,stdout=PIPE, stderr=PIPE) 
print('%s\n%s' % proc.communicate()) 
sys.exit(proc.returncode) 
+1

Oczywiście, łatanie 'sys.modules' z modułami próbnymi byłoby jedną możliwą akcją, którą mój sprzęt mógł wykonać, aby uczynić je importowalnymi. Problem polega na tym, gdzie umieścić ten kod urządzenia tak, że 'nose' uruchamia go zanim' nose-doctest' spróbuje zaimportować moduł? – burnpanck

+1

Ponadto, podczas gdy 'nose-exclude'would pozwoli mi wyłączyć pliki ze składnią python 3 z testów, pozwala to tylko statycznie z pliku' node.cfg' lub z linii poleceń. Wolałbym, aby urządzenie decydowało o przeskakiwaniu, ponieważ chcę tylko pomijać podczas testowania Pythona 2, ale nie podczas testowania Pythona 3 i bez żadnej ręcznej interakcji. – burnpanck

+1

"fixture" w twoim kontekście jest niejasne. Pokaż nam przykładowy kod, opisujący twoją sytuację, 'nose' nie może zaimportować, a 'fixutre' decydować o pomijaniu. –

1

Nos ma następującą opcję:

--doctest-fixtures=SUFFIX 
        Find fixtures for a doctest file in module with this 
        name appended to the base name of the doctest file 

Być może można izolować urządzenia do osobnego pliku?

+1

Brzmi interesująco, ważne pytanie brzmi, czy urządzenie zostanie uruchomione przed zaimportowaniem modułu. Dam ci szansę. – burnpanck

+1

Niestety, '--doctest-fixtures' jest brane pod uwagę tylko w przypadku _non-module_ doctests. Dlatego to nie może mi pomóc ukryć 'SyntaxError's podczas importowania, gdy doctest przeszukuje moduły w celu testowania. Dziękuję za odpowiedź! – burnpanck

Powiązane problemy