Nose-add-module before importing the module

I use the nose for a collection of tests, and I also want to use its doctest plugin. I have a module that needs to be adapted to be imported. Therefore, I cannot use the night module devices, since they are loaded from the tested module. Is there a way to specify modules for the nose doctrine outside the module?

In some cases of use, the option should be to detect a launch within the framework of the doctrine and use the device at the beginning of the module. I would be interested to hear the answers to this use case as well.

However, there are situations when this cannot work: when the import fails due to SyntaxError , the module code does not start. In my case, I mainly develop code that is compatible with python 2 and python 3 (without 2to3 ). However, there are a few special python 3 modules that just don't need to be checked on the nose when they run under python 2. What is my best option?

EDIT: MWE (for SyntaxError situation)

I have a package with many small modules, some of them use python 3 syntax. Here is the package structure:

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

Some tests are written as unittest.TestCase , but I also want code examples in checked docstrings. ~/pckg/__init__.py empty.

~ / pckg / py3only.py:

 def fancy_py3_func(a:"A function argument annotation (python 3 only syntax)"): """ A function using fancy syntax doubling it input. >>> fancy_py3_func(4) 8 """ return a*2 

~ / pckg / tests / 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) 

Testing in python 3, everything passes the test and passes (it is launched from the closing folder, for example ~ ):

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

On python 2, the fixture ~/pckg/tests/test_py2only.py correctly detects the situation and passes the test. However, we get a SyntaxError from ~/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) 

A function similar to ~/pckg/tests/test_py3only.py:setup_module() can solve this problem if I could get nose to run this code before the doctest plugin even tries to import this module.

It seems like my best bet is to write a valid top-level test script that handles a collection of tests ...

+5
source share
2 answers

Specific test files, directories, classes, or methods can be excluded using the nose-exclude plug-in for the nose. It has options --exclude-* .

To handle missing modules, you must install sys.modules with mock .

Fe, There's a Calc class in the mycalc module, but I don't have access to it because it is missing. And two more modules: mysuper_calc and mysuper_calc3 , the last one specific to Python 3. These two modules import mycalc and mysuper_calc3 should not be tested under Python 2. How can I guess them from the module in the text file? I guess this is the situation with OP.

calcareous / 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) 

calcareous / 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) 

Now, to make fun of mycalc ,

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

The mycalc module has a Calc class that has an add method. I am testing the SuperCalc instance add method with 2+3 .

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

Now the sys.modules and mysuper_calc3 can be conditionally imported into the with block.

 >>> 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 

The mysuper_calc_doctest.txt file must be alone in its own directory, otherwise nosetests will search for doctest in modules not tested.

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

Doctest: mysuper_calc_doctest.txt ... ok


Ran 1 test at 0.038s

Ok

Python 3 detection wrapper around nosetests that passes .py files without syntax errors to 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) 
+2
source

The nose has the following option:

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

Perhaps you can select devices in a separate file?

+1
source

Source: https://habr.com/ru/post/1204981/


All Articles