diff options
Diffstat (limited to 'tests/test_functional.py')
-rw-r--r-- | tests/test_functional.py | 169 |
1 files changed, 92 insertions, 77 deletions
diff --git a/tests/test_functional.py b/tests/test_functional.py index bb4145c4d..9ff9e7763 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -31,19 +31,20 @@ from pylint import checkers, interfaces, lint, reporters class test_dialect(csv.excel): if sys.version_info[0] < 3: - delimiter = b':' - lineterminator = b'\n' + delimiter = b":" + lineterminator = b"\n" else: - delimiter = ':' - lineterminator = '\n' + delimiter = ":" + lineterminator = "\n" -csv.register_dialect('test', test_dialect) +csv.register_dialect("test", test_dialect) class NoFileError(Exception): pass + # Notes: # - for the purpose of this test, the confidence levels HIGH and UNDEFINED # are treated as the same. @@ -54,14 +55,23 @@ class NoFileError(Exception): # If message files should be updated instead of checked. UPDATE = False -class OutputLine(collections.namedtuple('OutputLine', - ['symbol', 'lineno', 'object', 'msg', 'confidence'])): + +class OutputLine( + collections.namedtuple( + "OutputLine", ["symbol", "lineno", "object", "msg", "confidence"] + ) +): @classmethod def from_msg(cls, msg): return cls( - msg.symbol, msg.line, msg.obj or '', msg.msg.replace("\r\n", "\n"), + msg.symbol, + msg.line, + msg.obj or "", + msg.msg.replace("\r\n", "\n"), msg.confidence.name - if msg.confidence != interfaces.UNDEFINED else interfaces.HIGH.name) + if msg.confidence != interfaces.UNDEFINED + else interfaces.HIGH.name, + ) @classmethod def from_csv(cls, row): @@ -76,20 +86,21 @@ class OutputLine(collections.namedtuple('OutputLine', # Common sub-expressions. -_MESSAGE = {'msg': r'[a-z][a-z\-]+'} +_MESSAGE = {"msg": r"[a-z][a-z\-]+"} # Matches a #, # - followed by a comparison operator and a Python version (optional), # - followed by a line number with a +/- (optional), # - followed by a list of bracketed message symbols. # Used to extract expected messages from testdata files. _EXPECTED_RE = re.compile( - r'\s*#\s*(?:(?P<line>[+-]?[0-9]+):)?' - r'(?:(?P<op>[><=]+) *(?P<version>[0-9.]+):)?' - r'\s*\[(?P<msgs>%(msg)s(?:,\s*%(msg)s)*)\]' % _MESSAGE) + r"\s*#\s*(?:(?P<line>[+-]?[0-9]+):)?" + r"(?:(?P<op>[><=]+) *(?P<version>[0-9.]+):)?" + r"\s*\[(?P<msgs>%(msg)s(?:,\s*%(msg)s)*)\]" % _MESSAGE +) def parse_python_version(str): - return tuple(int(digit) for digit in str.split('.')) + return tuple(int(digit) for digit in str.split(".")) class FunctionalTestReporter(reporters.BaseReporter): @@ -107,51 +118,50 @@ class FunctionalTestFile(object): """A single functional test case file with options.""" _CONVERTERS = { - 'min_pyver': parse_python_version, - 'max_pyver': parse_python_version, - 'requires': lambda s: s.split(',') + "min_pyver": parse_python_version, + "max_pyver": parse_python_version, + "requires": lambda s: s.split(","), } - def __init__(self, directory, filename): self._directory = directory - self.base = filename.replace('.py', '') + self.base = filename.replace(".py", "") self.options = { - 'min_pyver': (2, 5), - 'max_pyver': (4, 0), - 'requires': [], - 'except_implementations': [], - } + "min_pyver": (2, 5), + "max_pyver": (4, 0), + "requires": [], + "except_implementations": [], + } self._parse_options() def _parse_options(self): cp = configparser.ConfigParser() - cp.add_section('testoptions') + cp.add_section("testoptions") try: cp.read(self.option_file) except NoFileError: pass - for name, value in cp.items('testoptions'): + for name, value in cp.items("testoptions"): conv = self._CONVERTERS.get(name, lambda v: v) self.options[name] = conv(value) @property def option_file(self): - return self._file_type('.rc') + return self._file_type(".rc") @property def module(self): package = os.path.basename(self._directory) - return '.'.join([package, self.base]) + return ".".join([package, self.base]) @property def expected_output(self): - return self._file_type('.txt', check_exists=False) + return self._file_type(".txt", check_exists=False) @property def source(self): - return self._file_type('.py') + return self._file_type(".py") def _file_type(self, ext, check_exists=True): name = os.path.join(self._directory, self.base + ext) @@ -161,15 +171,11 @@ class FunctionalTestFile(object): raise NoFileError -_OPERATORS = { - '>': operator.gt, - '<': operator.lt, - '>=': operator.ge, - '<=': operator.le, -} +_OPERATORS = {">": operator.gt, "<": operator.lt, ">=": operator.ge, "<=": operator.le} + def parse_expected_output(stream): - return [OutputLine.from_csv(row) for row in csv.reader(stream, 'test')] + return [OutputLine.from_csv(row) for row in csv.reader(stream, "test")] def get_expected_messages(stream): @@ -183,22 +189,22 @@ def get_expected_messages(stream): match = _EXPECTED_RE.search(line) if match is None: continue - line = match.group('line') + line = match.group("line") if line is None: line = i + 1 - elif line.startswith('+') or line.startswith('-'): + elif line.startswith("+") or line.startswith("-"): line = i + 1 + int(line) else: line = int(line) - version = match.group('version') - op = match.group('op') + version = match.group("version") + op = match.group("op") if version: required = parse_python_version(version) if not _OPERATORS[op](sys.version_info, required): continue - for msg_id in match.group('msgs').split(','): + for msg_id in match.group("msgs").split(","): messages[line, msg_id.strip()] += 1 return messages @@ -233,7 +239,7 @@ class LintModuleTest(object): self._linter.set_reporter(test_reporter) self._linter.config.persistent = 0 checkers.initialize(self._linter) - self._linter.disable('I') + self._linter.disable("I") try: self._linter.read_config_file(test_file.option_file) self._linter.load_config_file() @@ -243,33 +249,40 @@ class LintModuleTest(object): def setUp(self): if self._should_be_skipped_due_to_version(): - pytest.skip( 'Test cannot run with Python %s.' % (sys.version.split(' ')[0],)) + pytest.skip( + "Test cannot run with Python %s." % (sys.version.split(" ")[0],) + ) missing = [] - for req in self._test_file.options['requires']: + for req in self._test_file.options["requires"]: try: __import__(req) except ImportError: missing.append(req) if missing: - pytest.skip('Requires %s to be present.' % (','.join(missing),)) - if self._test_file.options['except_implementations']: + pytest.skip("Requires %s to be present." % (",".join(missing),)) + if self._test_file.options["except_implementations"]: implementations = [ - item.strip() for item in - self._test_file.options['except_implementations'].split(",") + item.strip() + for item in self._test_file.options["except_implementations"].split(",") ] implementation = platform.python_implementation() if implementation in implementations: pytest.skip( - 'Test cannot run with Python implementation %r' - % (implementation, )) + "Test cannot run with Python implementation %r" % (implementation,) + ) def _should_be_skipped_due_to_version(self): - return (sys.version_info < self._test_file.options['min_pyver'] or - sys.version_info > self._test_file.options['max_pyver']) + return ( + sys.version_info < self._test_file.options["min_pyver"] + or sys.version_info > self._test_file.options["max_pyver"] + ) def __str__(self): - return "%s (%s.%s)" % (self._test_file.base, self.__class__.__module__, - self.__class__.__name__) + return "%s (%s.%s)" % ( + self._test_file.base, + self.__class__.__module__, + self.__class__.__name__, + ) def _open_expected_file(self): return open(self._test_file.expected_output) @@ -310,15 +323,16 @@ class LintModuleTest(object): if expected_messages != received_messages: msg = ['Wrong results for file "%s":' % (self._test_file.base)] - missing, unexpected = multiset_difference(expected_messages, - received_messages) + missing, unexpected = multiset_difference( + expected_messages, received_messages + ) if missing: - msg.append('\nExpected in testdata:') - msg.extend(' %3d: %s' % msg for msg in sorted(missing)) + msg.append("\nExpected in testdata:") + msg.extend(" %3d: %s" % msg for msg in sorted(missing)) if unexpected: - msg.append('\nUnexpected in testdata:') - msg.extend(' %3d: %s' % msg for msg in sorted(unexpected)) - pytest.fail('\n'.join(msg)) + msg.append("\nUnexpected in testdata:") + msg.extend(" %3d: %s" % msg for msg in sorted(unexpected)) + pytest.fail("\n".join(msg)) self._check_output_text(expected_messages, expected_text, received_text) def _split_lines(self, expected_messages, lines): @@ -330,10 +344,10 @@ class LintModuleTest(object): omitted.append(msg) return emitted, omitted - def _check_output_text(self, expected_messages, expected_lines, - received_lines): - assert self._split_lines(expected_messages, expected_lines)[0] == \ - received_lines, self._test_file.base + def _check_output_text(self, expected_messages, expected_lines, received_lines): + assert ( + self._split_lines(expected_messages, expected_lines)[0] == received_lines + ), self._test_file.base class LintModuleOutputUpdate(LintModuleTest): @@ -343,25 +357,24 @@ class LintModuleOutputUpdate(LintModuleTest): except IOError: return io.StringIO() - def _check_output_text(self, expected_messages, expected_lines, - received_lines): + def _check_output_text(self, expected_messages, expected_lines, received_lines): if not expected_messages: return emitted, remaining = self._split_lines(expected_messages, expected_lines) if emitted != received_lines: remaining.extend(received_lines) remaining.sort(key=lambda m: (m[1], m[0], m[3])) - with open(self._test_file.expected_output, 'w') as fobj: - writer = csv.writer(fobj, dialect='test') + with open(self._test_file.expected_output, "w") as fobj: + writer = csv.writer(fobj, dialect="test") for line in remaining: writer.writerow(line.to_csv()) + def get_tests(): - input_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'functional') + input_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "functional") suite = [] for fname in os.listdir(input_dir): - if fname != '__init__.py' and fname.endswith('.py'): + if fname != "__init__.py" and fname.endswith(".py"): suite.append(FunctionalTestFile(input_dir, fname)) return suite @@ -372,13 +385,15 @@ TESTS_NAMES = [t.base for t in TESTS] @pytest.mark.parametrize("test_file", TESTS, ids=TESTS_NAMES) def test_functional(test_file): - LintTest = LintModuleOutputUpdate(test_file) if UPDATE else LintModuleTest(test_file) + LintTest = ( + LintModuleOutputUpdate(test_file) if UPDATE else LintModuleTest(test_file) + ) LintTest.setUp() LintTest._runTest() -if __name__ == '__main__': - if '-u' in sys.argv: +if __name__ == "__main__": + if "-u" in sys.argv: UPDATE = True - sys.argv.remove('-u') + sys.argv.remove("-u") pytest.main(sys.argv) |