#!/usr/bin/python
"""
unit tests for checkers
"""
import unittest
import sys
import os
import tarfile
import shutil
from os.path import join, dirname, abspath
from logilab.common.testlib import unittest_main, TestCase, TestSuite
import cubicweb.devtools
from cubes.apycot.testutils import MockTest, MockRepository, MockCheckWriter
from apycotlib import SUCCESS, FAILURE, PARTIAL, NODATA, ERROR
from checkers.apycot.python import *
from checkers.apycot.debcheck import *
def input_path(path=''):
return join(dirname(abspath(__file__)), 'data', path)
WRITER = MockCheckWriter()
def setUpModule():
for repo in ('badpkg2_repo', 'goodpkg_repo'):
path = input_path(repo)
if exists(path):
shutil.rmtree(path)
tarfile.open(input_path('%s.tar.gz' % repo), 'r|gz').extractall(input_path(''))
def tearDownModule():
for repo in ('badpkg2', 'goodpkg'):
path = input_path(repo)
if exists(path):
shutil.rmtree(path)
class FileCheckerTest(TestCase):
def __init__(self, checker, files, method_name):
TestCase.__init__(self, method_name)
self.checker = checker
self.files = [input_path(file) for file in files]
self.set_description('checker: <%s>, files: %s' % (checker.id, files))
def _init_test(self, file):
atest = MockTest(MockRepository(path=file))
atest._apycot_config.update(self.checker.options)
for k, v in atest._apycot_config.items():
if isinstance(v, list):
atest._apycot_config[k] = ','.join(v)
atest.writer = self.checker.writer
return atest
def check_file(self,file):
return self.checker.check_file(file)
def check_dir(self,file):
return self.checker.check(self._init_test(file))
def chks_test_(self, expected, func):
self.checker.writer.start(self.checker)
self.checker.check_options()
for file in self.files:
self.checker.writer.clear_writer()
status = func(file)
msg = []
msg.append('%s on %s status: %s expecting %s' % (self.checker.id, file, status, expected))
if self.checker.options:
msg.extend(' '+('='.join(str(i) for i in pair)) for pair in self.checker.options.iteritems())
msg.append('last messages:')
msg.extend(WRITER._logs[-5:])
msg = '\n'.join(msg)
self.failUnlessEqual(status, expected, msg)#+'\n-----\n'+WRITER.stderr.getvalue())
def chks_test_file_success(self):
self.chks_test_(SUCCESS, self.check_file)
def chks_test_file_failure(self):
self.chks_test_(FAILURE, self.check_file)
def chks_test_file_error(self):
self.chks_test_(ERROR, self.check_file)
def chks_test_dir_success(self):
self.chks_test_(SUCCESS, self.check_dir)
def chks_test_dir_failure(self):
self.chks_test_(FAILURE, self.check_dir)
def chks_test_dir_partial(self):
self.chks_test_(PARTIAL, self.check_dir)
def chks_test_dir_nodata(self):
self.chks_test_(NODATA, self.check_dir)
def chks_test_dir_error(self):
self.chks_test_(ERROR, self.check_dir)
class ModuleCheckerTest(FileCheckerTest):
def check_pkg(self, file):
return self.checker.check(self._init_test(file))
def chks_test_success(self):
self.chks_test_(SUCCESS, self.check_pkg)
def chks_test_error(self):
self.chks_test_(ERROR, self.check_pkg)
def chks_test_failure(self):
self.chks_test_(FAILURE, self.check_pkg)
def chks_test_partial(self):
self.chks_test_(PARTIAL, self.check_pkg)
def chks_test_nodata(self):
self.chks_test_(NODATA, self.check_dir)
def load_tests(loader, tests, pattern):
"""return the unitest suite"""
testsuite = TestSuite()
addTest = testsuite.addTest
##### FileChecker #####
file_checker = PythonSyntaxChecker(WRITER)
addTest(FileCheckerTest(file_checker, ['empty_dir'], 'chks_test_dir_nodata'))
##### PythonSyntaxChecker #####
python_syntax = PythonSyntaxChecker(WRITER)
addTest(FileCheckerTest(python_syntax, ['goodsyntax.py'], 'chks_test_file_success'))
addTest(FileCheckerTest(python_syntax, ['badsyntax.py'], 'chks_test_file_failure'))
addTest(FileCheckerTest(python_syntax, ['goodsyntax/'], 'chks_test_dir_success'))
addTest(FileCheckerTest(python_syntax, ['badsyntax/'], 'chks_test_dir_failure'))
addTest(FileCheckerTest(python_syntax, ['mixedsyntax/'], 'chks_test_dir_failure'))
addTest(FileCheckerTest(python_syntax, ['extentionfilter/'], 'chks_test_dir_success'))
addTest(FileCheckerTest(python_syntax, ['syntax_dir/badsyntax/'], 'chks_test_dir_failure'))
addTest(FileCheckerTest(python_syntax, ['goodsyntax.py'], 'chks_test_file_success'))
python_syntax = PythonSyntaxChecker(WRITER, {'ignore': 'wrongsyntax.py'})
addTest(FileCheckerTest(python_syntax, ['syntax_dir/badsyntax/'], 'chks_test_dir_success'))
python_syntax = PythonSyntaxChecker(WRITER, {'ignore':'rootbadsyntax.py,badsyntax'})
addTest(FileCheckerTest(python_syntax, ['syntax_dir/'], 'chks_test_dir_success'))
# check filtering of specific subdirectory
python_syntax = PythonSyntaxChecker(WRITER, {'ignore':'dodo/bad'})
addTest(FileCheckerTest(python_syntax, ['full_path_filtering/'], 'chks_test_dir_success'))
# check filtering of absolute path
python_syntax = PythonSyntaxChecker(WRITER, {'ignore':'full_path_filtering/dodo/bad'})
addTest(FileCheckerTest(python_syntax, ['full_path_filtering/'], 'chks_test_dir_success'))
python_syntax = PythonSyntaxChecker(WRITER)
python_syntax.best_status = 'partial'
addTest(FileCheckerTest(python_syntax, ['extentionfilter/'], 'chks_test_dir_partial'))
# check providing a custom file filter function
class CorrectFilter(PythonSyntaxChecker):
id = 'correct_filter'
def filename_filter(self, dirpath, dirnames, filenames):
for filename in filenames:
if not filename.endswith('.py'):
filenames.remove(filename)
python_syntax = CorrectFilter(WRITER)
addTest(FileCheckerTest(python_syntax, ['extentionfilter/'], 'chks_test_dir_success'))
class IncorrectFilter(PythonSyntaxChecker):
id = 'incorrect_filter'
def filename_filter(self, dirpath, dirnames, filenames):
for filename in filenames:
if not 'badsyntax' in filename:
filenames.remove(filename)
python_syntax = IncorrectFilter(WRITER)
addTest(FileCheckerTest(python_syntax, ['extentionfilter/'], 'chks_test_dir_failure'))
class CorrectDirFilter(PythonSyntaxChecker):
id = 'correct_dir_filter'
def filename_filter(self, dirpath, dirnames, filenames):
for dirname in dirnames[:]:
if 'bad' in dirname:
dirnames.remove(dirname)
for filename in filenames:
if 'bad' in filename:
filenames.remove(filename)
python_syntax = CorrectDirFilter(WRITER)
addTest(FileCheckerTest(python_syntax, ['syntax_dir/'], 'chks_test_dir_success'))
class IncorrectDirFilter(PythonSyntaxChecker):
id = 'incorrect_dir_filter'
def filename_filter(self, dirpath, dirnames, filenames):
for dirname in dirnames[:]:
if 'goodsyntax' in dirname:
dirnames.remove(dirname)
for filename in filenames:
if 'bad' in filename:
filenames.remove(filename)
python_syntax = IncorrectDirFilter(WRITER)
addTest(FileCheckerTest(python_syntax, ['syntax_dir/'], 'chks_test_dir_failure'))
##### PyUnitTestChecker #####
python_unit = PyUnitTestChecker(WRITER)
addTest(ModuleCheckerTest(python_unit, ['goodpkg'], 'chks_test_success'))
addTest(ModuleCheckerTest(python_unit, ['badpkg1'], 'chks_test_nodata'))
addTest(ModuleCheckerTest(python_unit, ['badpkg2'], 'chks_test_failure'))
python_unit = PyUnitTestChecker(WRITER, {'test_dirs':'dir_for_tetsing'}) # typo is intentional#
addTest(ModuleCheckerTest(python_unit, ['test_dirs_test_pkg/'], 'chks_test_success'))
# use sys.executable, success
python_unit = PyUnitTestChecker(WRITER, {'use_pkginfo_python_versions': '0'})
addTest(ModuleCheckerTest(python_unit, ['goodpkg2.4/'], 'chks_test_success'))
# py 2.4 & py 2.5, success
python_unit = PyUnitTestChecker(WRITER, {'use_pkginfo_python_versions': '1'})
addTest(ModuleCheckerTest(python_unit, ['goodpkg2.4/'], 'chks_test_success'))
# use sys.executable, success
python_unit = PyUnitTestChecker(WRITER, {'ignored_python_versions':'2.4'})
addTest(ModuleCheckerTest(python_unit, ['goodpkg2.4/'], 'chks_test_success'))
# unavailable py 2.3, error (ignored_python_versions option ignored when tested_python_versions is set)
python_unit = PyUnitTestChecker(WRITER, {'ignored_python_versions':'2.3', 'tested_python_versions':'2.3'})
addTest(ModuleCheckerTest(python_unit, ['goodpkg2.4/'], 'chks_test_error'))
python_unit = PyUnitTestChecker(WRITER, {'tested_python_versions':'2.3', 'use_pkginfo_python_versions':'0'})
addTest(ModuleCheckerTest(python_unit, ['goodpkg2.4/'], 'chks_test_error'))
##### PyCoverageChecker #####
if coverage is not None:
import os.path as osp
datadir = osp.dirname(osp.abspath(__file__))
goodfile = osp.join(datadir, 'data/goodpkg2.4/tests/.coverage')
os.environ['COVERAGE_FILE'] = goodfile # FIXME
pycoverage = PyCoverageChecker(WRITER, {'coverage_data': osp.join(datadir, 'data/unknown')})
addTest(ModuleCheckerTest(pycoverage, ['goodpkg'], 'chks_test_nodata'))
pycoverage = PyCoverageChecker(WRITER, {'pycoverage_threshold': 80,
'coverage_data': goodfile})
addTest(ModuleCheckerTest(pycoverage, ['goodpkg'], 'chks_test_failure'))
pycoverage = PyCoverageChecker(WRITER, {'pycoverage_threshold': 0,
'coverage_data': goodfile})
addTest(ModuleCheckerTest(pycoverage, ['goodpkg'], 'chks_test_success'))
##### PyLintChecker #####
try:
import pylint as _pylint
except ImportError:
pass
else:
pylint = PyLintChecker(WRITER, {'pylint.threshold': 7})
addTest(ModuleCheckerTest(pylint, ['pylint_ok.py'], 'chks_test_success'))
addTest(ModuleCheckerTest(pylint, ['pylint_bad.py'], 'chks_test_failure'))
pylint_rc = PyLintChecker(WRITER, {'pylint_threshold': 7,
'pylintrc':input_path("pylintrc"),
"pylint.show_categories": "F,E,W,C"})
addTest(ModuleCheckerTest(pylint_rc, ['pylint_bad.py'], 'chks_test_success'))
return testsuite
if __name__ == '__main__':
unittest_main()