how to ignore missing statemet in jenkins test coverage in django - django

Is it possible to ignore the missing branch coverage? I am using jenkins for test coverage and pylint testing. Is there any possibility to ingore missing statements and get 100% branch coverage? Maybe a property that can be set in project setting?

I have found the solution of my question.
1) create .coveragerc file in your django project
2) define
JENKINS_TASKS = ('django_jenkins.tasks.run_pylint',)
COVERAGE_EXCLUDES_FOLDERS = ['packsit/migrations/*','packsit/api/v1/images.py']
COVERAGE_RCFILE = '.coveragerc'
in your setting file.
3) .coveragerc file should contains:
[run]
branch = True
omit =
*/.local/*
/usr/*
[report]
exclude_lines =
pragma: no cover
def __repr__
if self\.debug
raise AssertionError
raise NotImplementedError
if 0:
if __name__ == .__main__.:
return
try:
except:
if
self.*
ignore_errors = True
include =
packsit/api/v1/client/*
[html]
directory = coverage_html_report
then run command on terminal:
$ python manage.py jenkins --enable-coverage --coverage-format html --coverage-exclude=COVERAGE_EXCLUDES_FOLDERS
this will exclude 'if, return, self, try , except' from report generated.

Related

Why coverage doesn't report anything on Djangos views.py?

I have a class based view in a Django app that looks something like this :
class CBView(View):
def get(self, request, client, *args, **kwargs):
output1 = self.method1(argument1)
output2 = self.method2(argument2)
# Rest of the method implementation
...
return response
def method1(self, argument1):
# Implementation
...
return output1
def method2(self, argument2):
# Implementation
...
return output2
And I'm trying to write unit tests for the 'easy' class methods, namely method1 and method2. The tests looks like this :
class TestCBView(TestCase):
def setUp(self):
self.view = CBView()
def test_method1(self):
# Testing that output1 is as expected
...
output1 = self.view.method1(argument1)
...
self.assertEquals(output1, expected_output1)
def test_method2(self):
# Testing that output2 is as expected
...
output2 = self.view.method2(argument2)
...
self.assertEquals(output2, expected_output2)
After that, I run:
coverage run ./manage.py test django_app.tests.test_cbview
Which runs all the tests successfully, then I try to run:
coverage report -m django_app/views.py
And I get :
Name Stmts Miss Cover Missing
-------------------------------------
No data to report.
Am I doing something wrong ?
I'm using Coverage.py, version 4.0.3., Django 1.8.15 and Python 2.7.13.
I just had the same problem. It appeared I had some not migrated data, so after I ran in the terminal
python manage.py makemigrations
python manage.py migrate
and I tried again with
coverage html --include=django_app/views.py
coverage run manage.py test django_app.tests
everything was already fine.
When running tests with coverage it generates the .coverage file which is in a private format and not intended to be read directly. This file contains the raw reports which will be used to show the report for you, either on console or in html format with coverage html. So normally if the tests were ran, the .coverage file must be there in the directory from which you launched the command coverage run ./manage.py test django_app.tests.test_cbview and then being under that directory, you can hit coverage report ... and should work.

Python ConfigParser KeyError:

I am following an example to read a config file from the following: https://wiki.python.org/moin/ConfigParserExamples
But I get a KeyError and can't figure out why. It is reading the files and I can even print the sections. I think I am doing something really stupid. Any help greatly appreciated.
Here is the code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import ConfigParser
import logging
config_default=ConfigParser.ConfigParser()
class Setting(object):
def get_setting(self, section, my_setting):
default_setting = self.default_section_map(section)[my_setting]
return default_setting
def default_section_map(self,section):
dict_default = {}
config_default.read('setting.cfg')
sec=config_default.sections()
options_default = config_default.options(section)
logging.info('options_default: {0}'.format(options_default))
for option in options_default:
try:
dict_default[option] = config_default.get(section, option)
if dict_default[option] == -1:
print("skip: %s" % option)
except:
print("exception on %s!" % option)
dict_default[option] = None
return dict_default
return complete_path
if __name__ == '__main__':
conf=Setting()
host=conf.get_setting('mainstuff','name')
#host=conf.setting
print 'host setting is :' + host
My config file is named setting.cfg and looks like this:
[mainstuff]
name = test1
domain = test2
[othersection]
database_ismaster = no
database_master = test3
database_default = test4
[mysql]
port = 311111
user = someuser
passwd = somecrazylongpassword
[api]
port = 1111
And the Error is this...
exception on domain! Traceback (most recent call last): File
"./t.py", line 51, in
host=conf.get_setting('mainstuff','name') File "./t.py", line 14, in get_setting
default_setting = self.default_section_map(section)[my_setting] KeyError: 'name'
Be sure that your complete file path is setting.cfg. If you put your file in another folder or if it is named different, Python is going to report the same KeyError.
you have no general section. in order to get the hostname you need something like
[general]
hostname = 'hostname.net'
in your setting.cfg. now your config file matches the program -- maybe you prefer to adapt your porgram to match the config file? ...this should get you started at least.
UPDATE:
as my answer is useless now, here is something you could try to build on (assuming it works for you...)
import ConfigParser
class Setting(object):
def __init__(self, cfg_path):
self.cfg = ConfigParser.ConfigParser()
self.cfg.read(cfg_path)
def get_setting(self, section, my_setting):
try:
ret = self.cfg.get(section, my_setting)
except ConfigParser.NoOptionError:
ret = None
return ret
if __name__ == '__main__':
conf=Setting('setting.cfg')
host = conf.get_setting('mainstuff', 'name')
print 'host setting is :', host
This error occurs mainly due to 2 reasons:
Issue in reading the config file due to not getting the proper path. Absolute path may be used. Try reading the config file first whether any issue.
f = open("config.ini", "r")
print(f.read())
Not been able to find mentioned section in config file.

Django Testing: DatabaseCreation' object has no attribute '_rollback_works'

I have written a example test and I'm trying to run it without creating a new database every time.
The first time I run my test everything is ok (takes sometime due to building the DB):
> REUSE_DB=1 python manage.py test contacts
Ran 1 test in 0.251s
The second time I get the following error:
> REUSE_DB=1 python manage.py test contacts
nosetests --verbosity 1 contacts
AttributeError: 'DatabaseCreation' object has no attribute '_rollback_works'
Why and how do I solve? Thanks.
My Test:
class ExampleTestCase(TestCase):
def test_contact_page(self):
resp = self.client.get('/contact/single/')
self.assertEqual(resp.status_code, 200)
Settings.py
DEBUG = True
TEMPLATE_DEBUG = DEBUG
INSTALLED_APPS += (
'django_nose',
)
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
Just use nose from github and you're good to go! I belive this is your issue:
https://github.com/jbalogh/django-nose/pull/95
I came across this a long while ago, it is now fixed on the github master, but unfortunately django-nose is not updated on pypi since last year..

django: running tests with coverage

I am trying to run tests on django with coverage. It works fine, but it doesn't detect class definitions, because they are defined before coverage is started. I have following test runner, that I use, when I compute coverage:
import sys
import os
import logging
from django.conf import settings
MAIN_TEST_RUNNER = 'django.test.simple.run_tests'
if settings.COMPUTE_COVERAGE:
try:
import coverage
except ImportError:
print "Warning: coverage module not found: test code coverage will not be computed"
else:
coverage.exclude('def __unicode__')
coverage.exclude('if DEBUG')
coverage.exclude('if settings.DEBUG')
coverage.exclude('raise')
coverage.erase()
coverage.start()
MAIN_TEST_RUNNER = 'django-test-coverage.runner.run_tests'
def run_tests(test_labels, verbosity=1, interactive=True, extra_tests=[]):
# start coverage - jeśli włączmy już tutaj, a wyłączymy w django-test-coverage,
# to dostaniemy dobrze wyliczone pokrycie dla instrukcji wykonywanych przy
# imporcie modułów
test_path = MAIN_TEST_RUNNER.split('.')
# Allow for Python 2.5 relative paths
if len(test_path) > 1:
test_module_name = '.'.join(test_path[:-1])
else:
test_module_name = '.'
test_module = __import__(test_module_name, {}, {}, test_path[-1])
test_runner = getattr(test_module, test_path[-1])
failures = test_runner(test_labels, verbosity=verbosity, interactive=interactive)
if failures:
sys.exit(failures)
What can I do, to have classes also included in coverage? Otherwise I have quite a low coverage and I can't easily detect places, that really need to be covered.
The simplest thing to do is to use coverage to execute the test runner. If your runner is called "runner.py", then use:
coverage run runner.py
You can put your four exclusions into a .coveragerc file, and you'll have all of the benefits of your coverage code, without keeping any of your coverage code.

Configure Django to find all doctests in all modules?

If I run the following command:
>python manage.py test
Django looks at tests.py in my application, and runs any doctests or unit tests in that file. It also looks at the __ test __ dictionary for extra tests to run. So I can link doctests from other modules like so:
#tests.py
from myapp.module1 import _function1, _function2
__test__ = {
"_function1": _function1,
"_function2": _function2
}
If I want to include more doctests, is there an easier way than enumerating them all in this dictionary? Ideally, I just want to have Django find all doctests in all modules in the myapp application.
Is there some kind of reflection hack that would get me where I want to be?
I solved this for myself a while ago:
apps = settings.INSTALLED_APPS
for app in apps:
try:
a = app + '.test'
__import__(a)
m = sys.modules[a]
except ImportError: #no test jobs for this module, continue to next one
continue
#run your test using the imported module m
This allowed me to put per-module tests in their own test.py file, so they didn't get mixed up with the rest of my application code. It would be easy to modify this to just look for doc tests in each of your modules and run them if it found them.
Use django-nose since nose automatically find all tests recursivelly.
Here're key elements of solution:
tests.py:
def find_modules(package):
"""Return list of imported modules from given package"""
files = [re.sub('\.py$', '', f) for f in os.listdir(os.path.dirname(package.__file__))
if f.endswith(".py") and os.path.basename(f) not in ('__init__.py', 'test.py')]
return [imp.load_module(file, *imp.find_module(file, package.__path__)) for file in files]
def suite(package=None):
"""Assemble test suite for Django default test loader"""
if not package: package = myapp.tests # Default argument required for Django test runner
return unittest.TestSuite([doctest.DocTestSuite(m) for m in find_modules(package)])
To add recursion use os.walk() to traverse module tree and find python packages.
Thanks to Alex and Paul. This is what I came up with:
# tests.py
import sys, settings, re, os, doctest, unittest, imp
# import your base Django project
import myapp
# Django already runs these, don't include them again
ALREADY_RUN = ['tests.py', 'models.py']
def find_untested_modules(package):
""" Gets all modules not already included in Django's test suite """
files = [re.sub('\.py$', '', f)
for f in os.listdir(os.path.dirname(package.__file__))
if f.endswith(".py")
and os.path.basename(f) not in ALREADY_RUN]
return [imp.load_module(file, *imp.find_module(file, package.__path__))
for file in files]
def modules_callables(module):
return [m for m in dir(module) if callable(getattr(module, m))]
def has_doctest(docstring):
return ">>>" in docstring
__test__ = {}
for module in find_untested_modules(myapp.module1):
for method in modules_callables(module):
docstring = str(getattr(module, method).__doc__)
if has_doctest(docstring):
print "Found doctest(s) " + module.__name__ + "." + method
# import the method itself, so doctest can find it
_temp = __import__(module.__name__, globals(), locals(), [method])
locals()[method] = getattr(_temp, method)
# Django looks in __test__ for doctests to run
__test__[method] = getattr(module, method)
I'm not up to speed on Djano's testing, but as I understand it uses automatic unittest discovery, just like python -m unittest discover and Nose.
If so, just put the following file somewhere the discovery will find it (usually just a matter of naming it test_doctest.py or similar).
Change your_package to the package to test. All modules (including subpackages) will be doctested.
import doctest
import pkgutil
import your_package as root_package
def load_tests(loader, tests, ignore):
modules = pkgutil.walk_packages(root_package.__path__, root_package.__name__ + '.')
for _, module_name, _ in modules:
try:
suite = doctest.DocTestSuite(module_name)
except ValueError:
# Presumably a "no docstrings" error. That's OK.
pass
else:
tests.addTests(suite)
return tests