/
githubmirror
/
oppia
Обзор
Документация
Войти
/
githubmirror
/
oppia
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
develop
scripts/linters/python_linter_test.py
231 строка
9 KB
Gabriel Fuentes
Black formatter staging (#23456)
05 окт 2025, 06:15
Не верифицирован
05 окт 2025, 06:15
62ec95a
Код
Авторство
О чём код?
# coding: utf-8 # # Copyright 2020 The Oppia Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS-IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for scripts/linters/python_linter.py.""" from __future__ import annotations import multiprocessing import os import tempfile from core.tests import test_utils from . import python_linter, run_lint_checks LINTER_TESTS_DIR = os.path.join(os.getcwd(), 'scripts', 'linters', 'test_files') VALID_PY_FILEPATH = os.path.join(LINTER_TESTS_DIR, 'valid.py') VALID_PY_JOBS_FILEPATH = os.path.join(LINTER_TESTS_DIR, 'valid_job_imports.py') INVALID_IMPORT_FILEPATH = os.path.join( LINTER_TESTS_DIR, 'invalid_import_order.py' ) INVALID_PYTHON3_FILEPATH = os.path.join( LINTER_TESTS_DIR, 'invalid_python_three.py' ) INVALID_DOCSTRING_FILEPATH = os.path.join( LINTER_TESTS_DIR, 'invalid_docstring.py' ) INVALID_PYCODESTYLE_CONTENT = """from __future__ import annotations class FakeClass: \"\"\"Fake docstring for valid syntax purposes.\"\"\" def __init__(self, fake_arg): self.fake_arg = fake_arg def fake_method(self, name): \"\"\"This doesn't do anything. Args: name: str. Means nothing. Yields: tuple(str, str). \"\"\" yield (name, name)""" NAME_SPACE = multiprocessing.Manager().Namespace() NAME_SPACE.files = run_lint_checks.FileCache() FILE_CACHE = NAME_SPACE.files class PythonLintChecksManagerTests(test_utils.LinterTestBase): """Test for python linter.""" def test_unsorted_import_order(self) -> None: lint_task_report = python_linter.ThirdPartyPythonLintChecksManager( [INVALID_IMPORT_FILEPATH] ).check_import_order() self.assert_same_list_elements( ['FAILED Import order check failed'], lint_task_report.get_report() ) self.assertEqual('Import order', lint_task_report.name) self.assertTrue(lint_task_report.failed) def test_sorted_import_order(self) -> None: lint_task_report = python_linter.ThirdPartyPythonLintChecksManager( [VALID_PY_FILEPATH] ).check_import_order() self.assertEqual( ['SUCCESS Import order check passed'], lint_task_report.get_report(), ) self.assertEqual('Import order', lint_task_report.name) self.assertFalse(lint_task_report.failed) def test_valid_job_imports(self) -> None: batch_jobs_dir: str = os.path.join( os.getcwd(), 'core', 'jobs', 'batch_jobs' ) lint_task_report = python_linter.check_jobs_imports( batch_jobs_dir, VALID_PY_JOBS_FILEPATH ) self.assertEqual( 'SUCCESS Check jobs imports in jobs registry check passed', lint_task_report.get_report()[-1], ) self.assertEqual( 'Check jobs imports in jobs registry', lint_task_report.name ) self.assertFalse(lint_task_report.failed) def test_invalid_job_imports(self) -> None: batch_jobs_dir: str = os.path.join( os.getcwd(), 'core', 'jobs', 'batch_jobs' ) lint_task_report = python_linter.check_jobs_imports( batch_jobs_dir, INVALID_IMPORT_FILEPATH ) self.assertEqual( 'FAILED Check jobs imports in jobs registry check failed', lint_task_report.get_report()[-1], ) self.assertEqual( 'Check jobs imports in jobs registry', lint_task_report.name ) self.assertTrue(lint_task_report.failed) def test_valid_file_with_pylint(self) -> None: lint_task_report = python_linter.ThirdPartyPythonLintChecksManager( [VALID_PY_FILEPATH] ).lint_py_files() self.assertEqual( ['SUCCESS Pylint check passed'], lint_task_report.get_report() ) self.assertEqual('Pylint', lint_task_report.name) self.assertFalse(lint_task_report.failed) def test_invalid_file_with_pylint_error(self) -> None: lint_task_report = python_linter.ThirdPartyPythonLintChecksManager( [INVALID_DOCSTRING_FILEPATH] ).lint_py_files() self.assert_same_list_elements( ['W9025: Period is not used at the end of the docstring.'], lint_task_report.trimmed_messages, ) self.assertEqual('Pylint', lint_task_report.name) self.assertTrue(lint_task_report.failed) def test_get_trimmed_error_output(self) -> None: lint_message = ( '************* Module oppia.scripts.linters.test_files.invalid_' 'docstring\n\n\n' 'W: 27, 0: Period is not used at the end of the docstring. ' '(no-period-used)\n\n\n\n' '---------------------------------------------------' '---------------\n\n' 'Your code has been rated at 8.75/10 (previous run: 8.75/10, +0.00)' '\n\n\n' ) trimmed_messages = python_linter.ThirdPartyPythonLintChecksManager( [INVALID_DOCSTRING_FILEPATH] ).get_trimmed_error_output(lint_message) self.assertEqual( trimmed_messages, '************* Module oppia.scripts.linters.test_files.' 'invalid_docstring\n\n\nW: 27, 0: Period is not used at ' 'the end of the docstring. \n', ) def test_third_party_linter_with_no_files(self) -> None: lint_task_report = python_linter.ThirdPartyPythonLintChecksManager( [] ).perform_all_lint_checks() self.assert_same_list_elements( ['There are no Python files to lint.'], lint_task_report[0].get_report(), ) self.assertEqual('Python lint', lint_task_report[0].name) self.assertFalse(lint_task_report[0].failed) def get_third_party_python_lint_checks_manager_obj( self, file: str ) -> python_linter.ThirdPartyPythonLintChecksManager: """Returns a ThirdPartyPythonLintChecksManager for a temporary Python file. This helper method writes the provided string `file` into a temporary `.py` file and uses it to initialize a ThirdPartyPythonLintChecksManager. A temporary file is used because Black automatically modifies newline formatting at the end of real files, which can interfere with testing. Args: file: str. The Python source code to be written to a temporary file. Returns: ThirdPartyPythonLintChecksManager. A linter object initialized with the temporary file. """ temp_file = tempfile.NamedTemporaryFile( mode='w+', suffix='.py', delete=False ) temp_file.write(file) temp_file.close() linter = python_linter.ThirdPartyPythonLintChecksManager( [temp_file.name] ) self.addCleanup(temp_file.close) return linter def test_third_party_perform_all_lint_checks(self) -> None: lint_task_report = self.get_third_party_python_lint_checks_manager_obj( INVALID_PYCODESTYLE_CONTENT ).perform_all_lint_checks() self.assertTrue(isinstance(lint_task_report, list)) def test_pycodestyle_with_error_message(self) -> None: # We use a temporary file here instead of a real one because # the Black formatter auto-fixes newlines at the end of files. lint_task_report = self.get_third_party_python_lint_checks_manager_obj( INVALID_PYCODESTYLE_CONTENT ).lint_py_files() print(lint_task_report.trimmed_messages) self.assert_same_list_elements( ['3:1: E302 expected 2 blank lines, found 1'], lint_task_report.trimmed_messages, ) self.assertEqual('Pylint', lint_task_report.name) self.assertTrue(lint_task_report.failed) def test_get_linters_with_success(self) -> None: custom_linter, third_party_linter = python_linter.get_linters( [VALID_PY_FILEPATH] ) self.assertIsNone(custom_linter) self.assertIsInstance( third_party_linter, python_linter.ThirdPartyPythonLintChecksManager )