nose2 vs nose test discovery (nose2 not finding tests) - python-2.7

I just started a python project and I'm trying out different test frameworks.
The problem I have is that nose2 does not find my tests:
$ nose2 --verbose
Ran 0 tests in 0.000s
OK
while nosetests find them all
$ nosetests --collect-only
.................................
Ran 33 tests in 0.004s
OK
Otherwhise I can execute a single test with nose2 from same directory:
$ nose2 myproj.client.test.mypkg.mymodule_test
.
Ran 1 test in 0.007s
OK
where myproj.client.test.mypkg.mymodule_test is like:
'''
Created on 18/04/2013
#author: julia
'''
from unittest import TestCase, main
import os
from myproj.client.mymodule import SUT
from mock import Mock
import tempfile
class SUTTest(TestCase):
def setUp(self):
self.folder = tempfile.mkdtemp(suffix='myproj')
self.sut = SUT(self.folder, Mock())
self.sut.init()
def test_wsName(self):
myfolder = os.path.join(self.folder, 'myfolder')
os.mkdir(myfolder)
self.sut.change_dir(myfolder)
self.assertEquals(self.SUT.name, 'myfolder')
if __name__ == "__main__":
main()
I've been looking at documentation and I cannot find a possible cause for this.
Running python 2.7.3 on MacOs 10.8.3

Adding to MichaelJCox's answer, another problem is that nose2, by default, is looking for your test file names to begin with 'test'. In other words, 'testFilePattern == test*.py' (you can find that in nose2/session.py).
You can fix this in two ways:
Specify a different test file pattern in a configuration file:
Create a configuration file somewhere in your project (the base directory is a good place, or wherever you will run nose2). nose2 will look for and load any file called nose2.cfg or unittest.cfg.
Add this to that configuration file.
[unittest]
test-file-pattern=*.py
Now run nose2 again and it'll find those old test cases. I'm unsure if this could adversely affect nose2 performance or what, but so far so good for me.
Rename your test files so that they begin with test.
For example, if you have a project like this:
/tests/
__init__.py
fluxcapacitor.py
Rename /tests/fluxcapacitor.py to /tests/test_fluxcapacitor.py, now nose2 will find the tests inside fluxcapacitor.py again.
More verbose output
Finally, this is unrelated to your question but might be helpful in the future: If -verbose doesn't output enough info, you can also pass the following additional arg --log-level debug for even more output.

It looks like nose2 needs 1 of 3 things to find the test:
Your tests need to be in packages (just create __init__.py files in each dir of your test structure)
You need a directory named 'test' in the same directory in which nose2 is being run
It needs to be in the same directory
nose2's _discovery method (in nose2.plugins.loader.discovery.py) is explicitly looking for directories named 'test' or directories that are packages (if it doesn't just pick up your test files from the same directory):
if ('test' in path.lower()
or util.ispackage(entry_path)
or path in self.session.libDirs):
for test in self._find_tests(event, entry_path, top_level):
yield test
If I set up a similar test file (called tests.py) and run nose2 in the same directory, it gives me the 1 test OK back.
If I create a directory named 'test', move the file to it, and run nose2 from the top directory, I get an error stating that it can't import my py file. Creating an __init__.py in that directory fixes that error.
If I make a directory 'blah' instead and move the file there, then I see the issue you list above:
Ran 0 tests in 0.000s
OK
However, if I then create an __init__.py in directory 'blah', the test runs and I get my 1 test found and OK'd.

Related

What does this code in .cicleci/config.yml mean?

My coworkers are trying to write unit test code and test API by using Circleci2.0 and Flake8. But I don't understand how I should write test code because this line pytest --flake8 in the below code does not mean.
What does this code in .cicleci/config.yml mean ?
Do we need to write test code in another xx.py file and execute this .py file like pytest xx.py?
If we should, does this line pytest --flake8 mean execution of xx.py file in another directly or the same directly even though this code dose not mention file path which execute test code file ?
- run:
name: Flake8 Check
command: |
. venv/bin/activate
pytest --flake8
You don't need to specify a filename. To quote the Pytest docs:
By default, pytest will run all files of the form test_*.py or *_test.py in the current directory and its subdirectories. More generally, it follows standard test discovery rules.

python: import a helper function in a module

In a top folder I have a python file (helpers.py) which contains a single function:
def play(name, verbose=False):
if verbose:
print name + "with verbose on"
else:
print name + "verbose off"
And in a subfolder named project I have second python file (program.py) that imports and uses helpers.py:
from .. import helpers as hp
def main(device,verbose=False):
hp.play(device)
#here goes the code
if __name__ == "__main__":
#Test the program
main('Foo')
main('Foo', verbose=True)
Both folders contain the __init__.py file to allow module importing. I want to execute the program.py file to test the main function.
Following How to fix "Attempted relative import in non-package" even with __init__.py I try to run :
python -m top.project.program
getting
# /usr/bin/python: No module named top.project
I don't understand what I am doing wrong. Any help? thanks
-m doesn't indicate an import; it is expecting the path to the module you wish to execute. So it probably wants -m top/project/program.py (although you may need to provide an absolute path).
The answer is in a comment of the accepted answer in the link I posted in my question. It matters from which directory you are executing your python command from. The code works when executing the following shell command:
python -m top.project.program
From the top directory only. It is not working when executed from its subdirectory project.

Cannot create test suite for Django

I'm having trouble creating a test suite in Django 1.3.
Say I have an installed app in a directory called app_name. One of the files in that directory is foo.py which defines a class named Foo. I want to test that, so I also have a file that directory called foo_test.py which defines a class named FooTest. That file looks like:
import unittest
import foo
class FooTest(unittest.TestCase):
def setUp(self):
self.foo_instance = foo.Foo()
... etc
Now down the line I'll have other test cases in other files, and I'll want to run them all as part of a test suite. So in the same directory app_name I created a file tests.py which will define the suite. At first I defined it like:
import foo_test
from django.test.simple import DjangoTestSuiteRunner
def suite():
runner = DjangoTestSuiteRunner()
return runner.build_suite(['app_name'])
Unfortunately, this fails because calling runner.build_suite(['app_name']) searches app_name for a tests.py file, executes suite(), and this continues recursively until the Python interpreter stops everything for exceeding the maximum recursion depth.
Changing runner.build_suite(['app_name']) to
runner.build_suite(['app_name.foo_test'])
or
runner.build_suite(['app_name.foo_test.FooTest'])
leads to errors like ValueError: Test label 'app_name.foo_test' does not refer to a test.
And changing it to:
runner.build_suite(['foo_test'])
or
runner.build_suite(['foo_test.FooTest'])
leads to errors like App with label foo_test could not be found.
I'm kind of out of ideas at this point. Any help would be very much appreciated. Thanks!
See the Python documentation for organizing tests, and use one of the alternative methods there to build your test suite. Incidentally, none of the recommended methods employ build_suite.

What is the simplest way to make manage.py test app.TestCase work again after replacing tests.py with tests/ directory?

I have replaced project/app/tests.py with a project/app/tests/ directory. The directory contains several Python files (call them apples.py, bananas.py, etc.), each of which defines one or more classes derived from TestCase (call them TestApples, TestBananas, etc.). The file project/app/tests/__init__.py contains
from apples import TestApples
from bananas import TestBananas
The command manage.py test app still works, but manage.py test app.bananas and manage.py test app.tests.bananas do not, e.g.:
ValueError: Test label 'app.bananas' does not refer to a test
manage.py test app.tests.bananas fails with the same error, but manage.py test app.tests.bananas.TestBananas is more hopeful:
ValueError: Test label 'store.tests.bananas.TestBananas' should be of the form app.TestCase or app.TestCase.test_method
The Django docs and Python docs suggest that the solution is to write a custom test runner or test collector and plug it in; this StackOverflow question goes down the same route, then seems to recommend switching to django-nose. I'd rather not unless I have to, and I'm curious to see how to make this work with Django's standard tools. Anyone have a simple(ish) solution?
In your example, if you run manage.py test app.TestBananas then you can run that specific test.
You can get everything working by making sure all your tests are imported into __init__.py but when you have lots of tests this becomes difficult to manage. If you want to run the tests in PyCharm then django-nose isn't an option.
To make this easier we can have the test suite automatically find all tests in the tests package. Just put this in __init__.py (Be sure to replace "appname"):
def suite():
return unittest.TestLoader().discover("appname.tests", pattern="*.py")
This still won't allow us to run specific tests. To do that you'll need to add this code at the top of __init__.py:
import pkgutil
import unittest
for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
module = loader.find_module(module_name).load_module(module_name)
for name in dir(module):
obj = getattr(module, name)
if isinstance(obj, type) and issubclass(obj, unittest.case.TestCase):
exec ('%s = obj' % obj.__name__)
Now you can run all your tests via manage.py test app or specific ones via manage.py test app.TestApples
I just do this tutorial.
Edit: after django 1.6, the test discovery mechanism changed. You just have to create a folder tests with an __init__.py file inside, and put your test files there.
Your test files should match test*.py pattern.
I use django-nose! Don't be scared of packages.
Did you try renaming your test files to "test_foo.py", instead of "foo.py", for example?

How to spread django unit tests over multiple files?

I have a python-django application
I'm using the unit testing framework
The tests are arranged in the file "tests.py" in the module directory
I'm running the tests via ./manage.py test app
Now..
The tests.py file is getting rather large/complex/messy
I'd like to break tests.py up into smaller collections of tests...
How?
Note that this approach is no longer valid from Django 1.6, see this post.
You can create tests folder with ___init___.py inside (so that it becomes a package). Then you add your split test .py files there and import all of them in ___init___.py.
I.e: Substitute the test.py file with a module that looks and acts like the file:
Create a tests Directory under the app in question
app
app\models.py
app\views.py
app\tests
app\tests\__init__.py
app\tests\bananas.py
app\tests\apples.py
Import the submodules into app\tests\__init__.py:
from bananas import *
from apples import *
Now you can use ./manage.py as if they were all in a single file:
./manage.py test app.some_test_in_bananas
The behavior has changed in Django 1.6, so there is no longer a need to create a package. Just name your files test*.py.
From Django 1.7 documentation
When you run your tests, the default behavior of the test utility is
to find all the test cases (that is, subclasses of unittest.TestCase)
in any file whose name begins with test, automatically build a test
suite out of those test cases, and run that suite.
From Django 1.6 documentation,
Test discovery is based on the unittest module’s built-in test
discovery. By default, this will discover tests in any file named
“test*.py” under the current working directory.
Previous behavior, from Django 1.5 documentation:
When you run your tests, the default behavior of the test utility is
to find all the test cases (that is, subclasses of unittest.TestCase)
in models.py and tests.py, automatically build a test suite out of
those test cases, and run that suite.
There is a second way to define the test suite for a module: if you
define a function called suite() in either models.py or tests.py, the
Django test runner will use that function to construct the test suite
for that module. This follows the suggested organization for unit
tests. See the Python documentation for more details on how to
construct a complex test suite.
The answer as stated by Tomasz is correct. However, it can become tedious to ensure that the imports in __init__.py match your file structure.
To automatically detect all tests in the folder you can add this in __init__.py:
import unittest
def suite():
return unittest.TestLoader().discover("appname.tests", pattern="*.py")
This will allow you to run ./manage.py test appname but won't handle running specific tests. To do that you can use this code (also in __init__.py):
import pkgutil
import unittest
for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
module = loader.find_module(module_name).load_module(module_name)
for name in dir(module):
obj = getattr(module, name)
if isinstance(obj, type) and issubclass(obj, unittest.case.TestCase):
exec ('%s = obj' % obj.__name__)
Now you can run all your tests via manage.py test app or specific ones via manage.py test app.TestApples
Just make your directory structure like this:
myapp/
__init__.py
tests/
__init__.py
test_one.py
test_two.py
...
...
And python manage.py test myapp will work as expected.
http://docs.python.org/library/unittest.html#organizing-tests talks about splitting the files into modules, and the section right above it has an example.
With Django 2.2 a simple and fairly good solution could be to create a test folder inside an app, and you can put your related test_...py files into, just add __init__.py to the test folder.
No need to code anything in init.
Just create a subdirectory in your app. Only requirement is not to call it tests*
For exemple
app/
app/__init_.py
app/serializers.py
app/testing/
app/testing/__init__.py
app/testing/tests_serializers.py
If you have a more complicated setup, or don't want to use from ... import *-type statements, you can define a function called suite in your tests.py (or tests/__init__.py), which returns an instance of unittest.TestSuite.
I have two files. One is tests.py and another is test_api.py. I can run these individually as below.
manage.py test companies.tests
manage.py test companies.test_api
Refer #osa's response about file naming convention.
I think ./manage.py test simply does running all the tests trick (in django >= 1.7).
If your organizing tests is about grouping and cherrypicking and you are fan of nose use django nose:
python manage.py test another.test:TestCase.test_method
If you know nose, then you know how to "wildcard" much nicer over all your files.
PS
It is just a better practice. Hope that helps. The answer was borrowed from here: Running a specific test case in Django when your app has a tests directory
In django you can use below comman or can check documentation. Also using this command will pick up files with pattern you provide not just test*.py or test_*.py.
Documentation
You can specify a custom filename pattern match using the -p (or --pattern) option, if your test files are named differently from the test*.py pattern:
$ ./manage.py test --pattern="tests_*.py"
Just create different test files with tests_name in your app
Say you have following test files:
tests_admins.py
tests_staff.py
tests_others.py
# will run both test files
(venv)..yourapp$./manage.py test --keepdb -v 2 appname
Or in Windows, if you do not want to create a package (i.e folder with __init__.py) and just want to create a folder called "Tests" and this folder contains the test files then to run tests in cmd just enter
python manage.py test your_app_name/Tests
Since a path is expected