pytest-django doesn't discover my tests, unless explicitly invoked - django

I just started using Django, and have only used PyTest for a couple of projects, but I love them both.
So I was happy to discover the pytest-django plugin that seems incredibly straight-forward and easy to use.
Per part 5 of the Django tutorial (I've been working through that), I've written a number of tests in mysite/polls/tests.py. These run flawlessly with the built-in test runner.
So, now with pytest and pytest-django installed, when I run py.test from within the project root, or py.test polls I get nothing:
When I explicitly invoke my file with py.test polls/tests.py, I get the colorful expected output:
What have I missed? I've followed the set up to the letter, and the Basic Usage docs of the plugin attest that a simple py.test should automatically find my tests. Why aren't they being found?

Following pytest naming conventions, try renaming your test file to:
test_[some text here].py
For example:
test_polls_unittests.py
Read more about pytest - tests naming conventions here.

Related

What Django TEST_RUNNER supports xunit xml and logging capture?

I'm attempting to set up a new django project, and I've configured TEST_RUNNER in settings.py to be django_nose.NoseTestSuiteRunner.
I chose this test runner because it seems to be the only one I can find that has the following features:
writes xunit xml test report
captures logging/stdout and only displays for failed tests.
However I've heard that nose is unmaintained and I'm having a hard time finding a suitable replacement. The standard test runner doesn't capture logging nor writes xunit as far as I'm able to tell (would love to be proven wrong!)
I run tests like so:
python -m coverage run manage.py test --noinput
python -m coverage report --include="app/*" --show-missing --fail-under=100
python -m coverage xml --include="app/*" -o ./reports/coverage.xml
With this in settings.py:
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
And this setup.cfg:
[nosetests]
verbosity=0
with-xunit=1
xunit-file=./reports/xunit.xml
logging-clear-handlers=1
The last two lines are the real juicy bits I can't seem to find in other test runners. nose captures the logging and clears other logging handlers (eg, the handler that dumps on stdout) so the test runs output is much cleaner (you only see logging for tests that failed).
In other non-django projects I typically use nose2 but django-nose2 project appears to be 6 years old and lacking python3 support??
Please let me know which test runner is the "recommended" one (eg, most popular) with django support, thanks.
I have had success with unittest-xml-reporting:
TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner'
https://github.com/xmlrunner/unittest-xml-reporting#django-support
The output directory can be configured with the TEST_OUTPUT_DIR setting.
You may still use nose runner:
INSTALLED_APPS += ['django_nose']
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
NOSE_ARGS = [
'--with-xunit',
'--xunit-file=nosetests.xml',
'--with-coverage',
'--cover-erase',
'--cover-xml',
'--cover-xml-file=nosecover.xml',
]
So pytest produces some very nice test output. I've unset TEST_RUNNER in settings.py and changed my test script to:
python -m coverage run -m pytest --junitxml=./reports/junit.xml
python -m coverage report --include="app/*" --show-missing --fail-under=100
python -m coverage xml --include="app/*" -o ./reports/coverage.xml
This works, and captures ALL logging output (nose was a little buggy and let one or two logging statements slip through, very strange behavior).
The only thing is that I'm a django novice so I don't know if there are any bad side-effects of not using manage.py test for testing django. Any guidance is appreciated, thanks!

nosetests unable to import coverage with virtualenv

I've installed nose and coverage to my virtual env, but it doesn't work
(venv) ../my_cookbook$ nosetests --with-coverage
nose.plugins.cover: ERROR: Coverage not available: unable to import coverage module
I wondered if it was escaping my venv somehow, so I tried this and it worked!
(venv) ../my_cookbook$ ./venv/bin/nosetests --with-coverage
Then I wanted to see if my path was some how messed up.
(venv) ../my_cookbook$ which nosetests
/home/peter/Projects/my_cookbook/venv/bin/nosetests
(venv) ../my_cookbook$ which coverage
/home/peter/Projects/my_cookbook/venv/bin/coverage
So what is going on here? Somehow the nosetests command is escaping my virtualenv but I don't know how.
Unfortunately, I don't have an explanation why the nose plugin is not picking up coverage, but, executing your tests through coverage should be preferred as opposed to using test runner plugins (nose coverage plugin in your case). Quoting Ned Batchelder (the author of coverage):
using a plugin means you are depending on that plugin's behavior being correct and understandable. In the name of being helpful, plugins will have their own logic that may have been the best idea when they were written, but the test runner and/or coverage.py may have changed in the meantime. The plugins tend not to be as well-maintained as the other components. If you can avoid them, you have one less thing to think about.
In other words, run:
$ coverage run -m nose
and to get the coverage report:
$ coverage report

launch one jasmine test with grunt and karma?

I have a big web project with many javascript Jasmine unit tests.
In that web project, i use grunt, karma and jasmine.
Is there any way to launch only one test javascript with grunt with a command line ?
Launching all tests is long, so how to do that without modify my gruntfile.js or my karma-unit.conf.js ??
I tried the following command, but it is more a hack than a real solution :
karma run -- --grep=filteredtestexpr
I am not sure of the best way to specify which test to run from the command line. But it seems like your problem can be solved with the following two pointers:
Change the name of a test from it to iit and karma will run only that test (actually all iit tests).
Change describe to ddescribe to run the entire describe block.
Also, use xit and xdescribe to explicitly exclude tests.

How to use pdb.set_trace() in a Django unittest?

I want to debug a Django TestCase just like I would any other Python code: Simply call pdb.set_trace() and then drop into an interactive session. When I do that, I don't see anything, as the tests are run in a different process. I'm using django-discover-runner, but my guess is that this applies to the default Django test runner.
The question:
Is it possible to drop into a pdb session while using django-discover-runner a) on every error / fail, AND/OR b) only when I call pdb.set_trace() in my test code?
Some research:
This answer explains that Django creates another process, and suggests using a call to rpdb2 debugger, a part of winpdb, but I don't want to use winpdb, I'd rather use ipdb.
This answer solves the problem for django-nose by running the test command like this: ./manage.py test -- -s, but that option's not available for django-discover-runner.
This answer shows that I can do this with ipython:
In [9]: %pdb
Automatic pdb calling has been turned ON
That seems like a potential option, but it seems a bit cumbersome to fire up ipython every time I run tests.
Finally, this answer shows that nose comes with a --pdb flag that drops into pdb on errors, which is what I want. Is my only option to switch to the django-nose test runner?
I don't see any options for this in the built-in help for django-discover-runner:
$ python manage.py help test --settings=settings.test
Usage: manage.py test [options] [appname ...]
Runs the test suite for the specified applications, or the entire site if no apps are specified.
Options:
-v VERBOSITY, --verbosity=VERBOSITY
Verbosity level; 0=minimal output, 1=normal output,
2=verbose output, 3=very verbose output
--settings=SETTINGS The Python path to a settings module, e.g.
"myproject.settings.main". If this isn't provided, the
DJANGO_SETTINGS_MODULE environment variable will be
used.
--pythonpath=PYTHONPATH
A directory to add to the Python path, e.g.
"/home/djangoprojects/myproject".
--traceback Print traceback on exception
--noinput Tells Django to NOT prompt the user for input of any
kind.
--failfast Tells Django to stop running the test suite after
first failed test.
--testrunner=TESTRUNNER
Tells Django to use specified test runner class
instead of the one specified by the TEST_RUNNER
setting.
--liveserver=LIVESERVER
Overrides the default address where the live server
(used with LiveServerTestCase) is expected to run
from. The default value is localhost:8081.
-t TOP_LEVEL, --top-level-directory=TOP_LEVEL
Top level of project for unittest discovery.
-p PATTERN, --pattern=PATTERN
The test matching pattern. Defaults to test*.py.
--version show program's version number and exit
-h, --help show this help message and exit
Django does not run tests in a separate process; the linked answer claiming it does is simply wrong. (The closest is the LiveServerTestCase for Selenium tests, which starts up a separate thread to run the development server, but this is still not a separate process, and it doesn't prevent use of pdb). You should be able to insert import pdb; pdb.set_trace() anywhere in a test (or in the tested code) and get a usable pdb prompt. I've never had trouble with this, and I just verified it again in a fresh project with Django 1.5.1 and django-discover-runner 1.0. If this isn't working for you, it's due to something else in your project, not due to Django or django-discover-runner.
Nose captures all output by default, which breaks import pdb; pdb.set_trace(). The -s option turns off output capturing. This is not necessary with the stock Django test runner or django-discover-runner, since neither of them do output-capturing to begin with.
I don't know of any equivalent to nose's --pdb option if you're using django-discover-runner. There is a django-pdb project that provides this, but a quick perusal of its code suggests to me that it wouldn't play well with django-discover-runner; its code might give you some clues towards implementing this yourself, though.
FWIW, personally I use py.test with pytest-django rather than django-discover-runner or django-nose. And even though py.test provides a --pdb option like nose, I don't use it; I often want to break earlier than the actual point of error in order to step through execution prior to the error, so I usually just insert import pytest; pytest.set_trace() (importing set_trace from pytest does the equivalent of nose's -s option; it turns off py.test's output capturing before running pdb) where I want it in the code and then remove it when I'm done. I don't find this onerous; YMMV.
Try to use ipdb instead of pdb -
import ipdb;ipdb.set_trace()
or (works in case of nose test runner)
from nose.tools import set_trace;set_trace()

Why Django nose test need --exe?

Why do I have to use the --exe argument while I run django-nose tests.
If I don't use it, it will skip the tests to run
e.g.
manage.py test myapp
Ran 0 tests in 0.000s
while my tests are in the correct place etc.
Running it in verbosity 3 it shows:
nosetests --verbosity 3 myapp
it shows: (changed the path names, but anyway, nose finds them but skips them!!)
nose.selector: INFO: /path_to_project/path_to_app/myapp/tests.pyc is executable; skipped
nose.selector: INFO: /path_to_project/path_to_app/myapp/tests.py~ is executable; skipped
The only way to run the tests is using the --exe argument
I Am using:
Ubuntu (both 10.4 or 11.4 doesn't matter)
Python 2.6 and 2.7
Django 1.4.3
why is that?
According to the documents you won't need --exe
But after puzzling for a while... and googling and looking here, i got this suggestion.
see Nose doesn't find Django tests
and Nose unable to find tests in ubuntu
But nowhere the explanation of this workaround for what seems to be a bug?
Or Am I missing something?
I requestion this, because the other questions are quite old, and no satisfactory answer to this problem found.....
It's not a bug - it's a feature.
Please, see good explanations here: What does "import safe" mean in Python?