123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- # Lint as: python3
- # Copyright 2022 The Chromium Authors. All rights reserved.
- # Use of this source code is governed by a BSD-style license that can be
- # found in the LICENSE file.
- import dataclasses
- import datetime as dt
- import logging
- import os
- import pathlib
- import sys
- from typing import List, Optional, Set, Tuple, Union
- _TOOLS_ANDROID_PATH = pathlib.Path(__file__).resolve(strict=True).parents[1]
- if str(_TOOLS_ANDROID_PATH) not in sys.path:
- sys.path.append(str(_TOOLS_ANDROID_PATH))
- from python_utils import git_metadata_utils
- import java_test_utils
- _CHROMIUM_SRC_PATH = git_metadata_utils.get_chromium_src_path()
- _IGNORED_DIRS = ('out', 'third_party', 'clank', 'build/linux', 'native_client',
- 'tools/android/test_health/testdata')
- _IGNORED_FILES = set()
- @dataclasses.dataclass(frozen=True)
- class GitRepoInfo:
- """Holder class for Git repository information."""
- git_head: str
- """The SHA1 hash of the Git repository's commit at HEAD."""
- git_head_time: dt.datetime
- """The datetime of the Git repository's commit at HEAD."""
- @dataclasses.dataclass(frozen=True)
- class TestHealthInfo:
- """Holder class for test health information about a test class."""
- test_name: str
- """The name of the test, e.g., the class name of a Java test."""
- test_dir: pathlib.Path
- """The directory containing the test, relative to the Git repo root."""
- test_filename: str
- """The filename of the test, e.g., FooJavaTest.java."""
- java_test_health: Optional[java_test_utils.JavaTestHealth]
- """Java test health info and counters; this is None if not a Java test."""
- git_repo_info: GitRepoInfo
- """Information about the Git repository being sampled."""
- def get_repo_test_health(git_repo: Optional[pathlib.Path] = None,
- *,
- test_dir: Union[str, pathlib.Path, None] = None,
- ignored_dirs: Tuple[str, ...] = _IGNORED_DIRS,
- ignored_files: Set[str] = _IGNORED_FILES
- ) -> List[TestHealthInfo]:
- """Gets test health information and stats for a Git repository.
- This function checks for Java tests annotated as disabled or flaky but could
- be extended to check other metrics or languages in the future.
- Args:
- git_repo:
- The path to the root of the Git repository being checked; defaults
- to the Chromium repo.
- test_dir:
- The subdirectory, relative to the Git repo root, containing the
- tests of interest; defaults to the root of the Git repo.
- ignored_dirs:
- A list of directories to skip (paths relative to `test_dir`);
- defaults to a set of directories that should be ignored in the
- Chromium Git repo.
- ignored_files:
- A set of file paths to skip (relative to `test_dir`); defaults to
- files in the Chromium Git repo with unsupported Java syntax.
- Returns:
- A list of `TestHealthInfo` objects, one for each test file processed.
- """
- git_repo = git_repo or _CHROMIUM_SRC_PATH
- test_dir = test_dir or pathlib.Path('.')
- tests_root = (git_repo / test_dir).resolve(strict=True)
- repo_info = _get_git_repo_info(git_repo)
- test_health_infos: list[TestHealthInfo] = []
- for dirpath, _, filenames in os.walk(tests_root):
- if os.path.relpath(dirpath, tests_root).startswith(ignored_dirs):
- continue
- for filename in filenames:
- if not filename.endswith('Test.java'):
- continue
- test_path = pathlib.Path(dirpath) / filename
- if os.path.relpath(test_path, tests_root) in ignored_files:
- continue
- test_health_info = _get_test_health_info(git_repo, test_path,
- repo_info)
- if test_health_info:
- test_health_infos.append(test_health_info)
- return test_health_infos
- def _get_test_health_info(repo_root: pathlib.Path, test_path: pathlib.Path,
- repo_info: GitRepoInfo) -> Optional[TestHealthInfo]:
- test_file = test_path.relative_to(repo_root)
- try:
- test_health_stats = java_test_utils.get_java_test_health(test_path)
- except java_test_utils.JavaSyntaxError:
- # This can occur if the file uses syntax not supported by the underlying
- # javalang python module used by java_test_utils. These files should be
- # investigated manually.
- logging.warning(f'Skipped file "{test_file}" due to'
- ' Java syntax error.')
- return None
- return TestHealthInfo(test_name=test_file.stem,
- test_dir=test_file.parent,
- test_filename=test_file.name,
- java_test_health=test_health_stats,
- git_repo_info=repo_info)
- def _get_git_repo_info(git_repo: pathlib.Path) -> GitRepoInfo:
- return GitRepoInfo(git_metadata_utils.get_head_commit_hash(git_repo),
- git_metadata_utils.get_head_commit_datetime(git_repo))
|