test/unittest_checkers.py
author David Douard <david.douard@logilab.fr>
Sun, 09 Nov 2014 20:07:45 +0100
changeset 1773 35a2edaa84e5
parent 1769 8e817371cba1
permissions -rw-r--r--
[migration] add a migration script for 4.0.0

#!/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, 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(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)

    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 chks_test_success(self):
        self.chks_test_(SUCCESS, self.check_dir)

    def chks_test_error(self):
        self.chks_test_(ERROR, self.check_dir)

    def chks_test_failure(self):
        self.chks_test_(FAILURE, self.check_dir)

    def chks_test_partial(self):
        self.chks_test_(PARTIAL, self.check_dir)

    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'))
    # XXX 
    # 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()