Skip to content

Commit 6008aca

Browse files
dbasunagpre-commit-ci[bot]rnetsermyakove
authored
Add polarion test requirement verification script (#6)
* Revert "initial PR" This reverts commit de9e568. * initial commit for unused_code * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * address code review comments on unused_code * update config location * add polarion test case requirement validation script * fix imports * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * update to polarion requirement check script * Update pyproject.toml * Update pyproject.toml * Update apps/polarion/polarion_verify_tc_requirements.py Co-authored-by: Ruth Netser <[email protected]> * add more tests using unittest.mock and address review comments * fix readme * update rename of the script * Update apps/polarion/polarion_utils.py Co-authored-by: Ruth Netser <[email protected]> * address review comments * Update apps/utils.py Co-authored-by: Meni Yakove <[email protected]> * Update apps/utils.py Co-authored-by: Meni Yakove <[email protected]> * address review comments * added missing config for pytest-cov * update for coverage * addressed comments * address review comments * Update tests/polarion/test_polarion.py Co-authored-by: Ruth Netser <[email protected]> * update based on review comments * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * address review comments * address review comments * update poetry * remove polarion tests --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Ruth Netser <[email protected]> Co-authored-by: Meni Yakove <[email protected]>
1 parent 73ecb63 commit 6008aca

17 files changed

+309
-32
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ coverage.xml
5050
.hypothesis/
5151
.pytest_cache/
5252
cover/
53+
.tests_coverage/
5354

5455
# Translations
5556
*.mo

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# python-utility-scripts
22
Repository for various python utility scripts
3-
* [pyappsutils-unusedcode](https://github.com/RedHatQE/python-utility-scripts/blob/main/README.md)
3+
* [pyutils-unusedcode](https://github.com/RedHatQE/python-utility-scripts/blob/main/apps/unused_code/README.md)
4+
* [pyutils-polarion-verify-tc-requirements](https://github.com/RedHatQE/python-utility-scripts/blob/main/apps/polarion/README.md)
45

56
## Installation
67

apps/polarion/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# scripts to interact with Polarion instance
2+
3+
## pyutils-polarion-verify-tc-requirements
4+
Utility to check if test cases in a pytest repository has associated Polarion requirements.
5+
6+
## Requirements
7+
This script uses [pylero](https://github.com/RedHatQE/pylero) and expects .pylero config file to be present in current directory or user's home directory.
8+
9+
## Usage
10+
```bash
11+
pyutils-polarion-verify-tc-requirements --help
12+
pyutils-polarion-verify-tc-requirements --project_id <project_id>
13+
```
14+
15+
## Config file
16+
To specify polation project id for polarion scripts, it can be added to the config file:
17+
`~/.config/python-utility-scripts/config.yaml`
18+
19+
20+
### Example:
21+
22+
```yaml
23+
pyutils-polarion-verify-tc-requirements :
24+
project_id: "<project_id>"
25+
```
26+
This would run the polarion requirement check against Polarion project <project_id>
27+
28+
To run from CLI with `--project-id`
29+
30+
```bash
31+
pyutils-polarion-verify-tc-requirements --project-id 'my_project_id'
32+
```

apps/polarion/__init__.py

Whitespace-only changes.

apps/polarion/polarion_utils.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from simple_logger.logger import get_logger
2+
import shlex
3+
import subprocess
4+
from pylero.exceptions import PyleroLibException
5+
6+
7+
LOGGER = get_logger(name=__name__)
8+
9+
10+
def git_diff():
11+
data = subprocess.check_output(shlex.split("git diff HEAD^-1"))
12+
data = data.decode("utf-8")
13+
return data
14+
15+
16+
def git_diff_lines():
17+
diff = {}
18+
for line in git_diff().splitlines():
19+
LOGGER.debug(line)
20+
if line.startswith("+"):
21+
diff.setdefault("added", []).append(line)
22+
23+
return diff
24+
25+
26+
def validate_polarion_requirements(polarion_test_ids, polarion_project_id):
27+
tests_with_missing_requirements = []
28+
from pylero.work_item import Requirement, TestCase
29+
30+
for _id in polarion_test_ids:
31+
has_req = False
32+
LOGGER.debug(f"Checking if {_id} verifies any requirement")
33+
tc = TestCase(project_id=polarion_project_id, work_item_id=_id)
34+
for link in tc.linked_work_items:
35+
try:
36+
Requirement(project_id=polarion_project_id, work_item_id=link.work_item_id)
37+
has_req = True
38+
break
39+
except PyleroLibException:
40+
continue
41+
42+
if not has_req:
43+
LOGGER.error(f"{_id}: Is missing requirement")
44+
tests_with_missing_requirements.append(_id)
45+
return tests_with_missing_requirements
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import re
2+
import logging
3+
from simple_logger.logger import get_logger
4+
import os
5+
import click
6+
7+
from apps.polarion.polarion_utils import (
8+
git_diff_lines,
9+
validate_polarion_requirements,
10+
)
11+
from apps.utils import get_util_config
12+
13+
LOGGER = get_logger(name=__name__)
14+
15+
16+
@click.command()
17+
@click.option(
18+
"--config-file-path",
19+
help="Provide absolute path to the config file. Any CLI option(s) would override YAML file",
20+
type=click.Path(),
21+
default=os.path.expanduser("~/.config/python-utility-scripts/config.yaml"),
22+
)
23+
@click.option("--project-id", "-p", help="Provide the polarion project id")
24+
@click.option("--verbosity", default=False, is_flag=True)
25+
def has_verify(config_file_path, project_id, verbosity):
26+
if verbosity:
27+
LOGGER.setLevel(logging.DEBUG)
28+
polarion_project_id = project_id or get_util_config(
29+
util_name="pyutils-polarion-verify-tc-requirements", config_file_path=config_file_path
30+
).get("project_id")
31+
if not polarion_project_id:
32+
click.echo("Polarion project id must be passed via config file or command line")
33+
raise click.Abort()
34+
35+
if added_ids := re.findall(
36+
rf"pytest.mark.polarion.*({polarion_project_id}-[0-9]+)",
37+
"\n".join(git_diff_lines().get("added", [])),
38+
re.MULTILINE | re.IGNORECASE,
39+
):
40+
LOGGER.debug(f"Checking following ids: {added_ids}")
41+
if tests_with_missing_requirements := validate_polarion_requirements(
42+
polarion_test_ids=added_ids, polarion_project_id=polarion_project_id
43+
):
44+
click.echo(f"TestCases with missing requirement: {tests_with_missing_requirements}")
45+
raise click.Abort()
46+
47+
48+
if __name__ == "__main__":
49+
has_verify()

apps/unused_code/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
# pyappsutils-unusedcode
1+
# pyutils-unusedcode
22
Helper to identify unused code in a pytest repository. It should be run from inside the test repository using this tool.
33

44
## Usage
55

66
```bash
7-
pyappsutils-unusedcode
8-
pyappsutils-unusedcode --help
7+
pyutils-unusedcode
8+
pyutils-unusedcode --help
99
```
1010

1111
## Config file
@@ -15,7 +15,7 @@ To skip unused code check on specific files or functions of a repository, a conf
1515
### Example:
1616

1717
```yaml
18-
pyappsutils-unusedcode:
18+
pyutils-unusedcode:
1919
exclude_files:
2020
- "my_exclude_file.py"
2121
exclude_function_prefix:
@@ -26,11 +26,11 @@ This would exclude any functions with prefix my_exclude_function_prefix and file
2626
To run from CLI with `--exclude-function-prefixes`
2727

2828
```bash
29-
pyappsutils-unusedcode --exclude-function-prefixes 'my_exclude_function1,my_exclude_function2'
29+
pyutils-unusedcode --exclude-function-prefixes 'my_exclude_function1,my_exclude_function2'
3030
```
3131

3232
To run from CLI with `--exclude-files`
3333

3434
```bash
35-
pyappsutils-unusedcode --exclude-files 'my_exclude_file1.py,my_exclude_file2.py'
35+
pyutils-unusedcode --exclude-files 'my_exclude_file1.py,my_exclude_file2.py'
3636
```

apps/unused_code/unused_code.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import ast
2+
import logging
23
import os
34
import subprocess
45
import click
5-
import yaml
66
from simple_logger.logger import get_logger
77

8-
from apps.utils import all_python_files, ListParamType
8+
from apps.utils import all_python_files, ListParamType, get_util_config
99

1010
LOGGER = get_logger(name=__name__)
1111

@@ -42,19 +42,12 @@ def is_test(_elm):
4242
yield elm
4343

4444

45-
def read_config_file(config_file_path):
46-
if os.path.exists(config_file_path):
47-
with open(config_file_path) as _file:
48-
return yaml.safe_load(_file)
49-
return {}
50-
51-
5245
def is_ignore_function_list(ignore_prefix_list, function):
5346
ignore_function_lists = [
5447
function.name for ignore_prefix in ignore_prefix_list if function.name.startswith(ignore_prefix)
5548
]
5649
if ignore_function_lists:
57-
LOGGER.info(f"Following functions are getting skipped: {ignore_function_lists}")
50+
LOGGER.debug(f"Following functions are getting skipped: {ignore_function_lists}")
5851
return True
5952

6053

@@ -75,10 +68,12 @@ def is_ignore_function_list(ignore_prefix_list, function):
7568
help="Provide a comma-separated string or list of function prefixes to exclude",
7669
type=ListParamType(),
7770
)
78-
def get_unused_functions(config_file_path, exclude_files, exclude_function_prefixes):
71+
@click.option("--verbosity", default=False, is_flag=True)
72+
def get_unused_functions(config_file_path, exclude_files, exclude_function_prefixes, verbosity):
73+
if verbosity:
74+
LOGGER.setLevel(logging.DEBUG)
7975
_unused_functions = []
80-
config_yaml = read_config_file(config_file_path=config_file_path)
81-
unused_code_config = config_yaml.get("pyappsutils-unusedcode", {})
76+
unused_code_config = get_util_config(util_name="pyutils-unusedcode", config_file_path=config_file_path)
8277
func_ignore_prefix = exclude_function_prefixes or unused_code_config.get("exclude_function_prefix", [])
8378
file_ignore_list = exclude_files or unused_code_config.get("exclude_files", [])
8479
for py_file in all_python_files():

apps/utils.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
import os
2+
3+
import yaml
24
from simple_logger.logger import get_logger
35
import json
46
import click
57

68
LOGGER = get_logger(name=__name__)
79

810

11+
def get_util_config(util_name, config_file_path):
12+
if os.path.exists(config_file_path):
13+
with open(config_file_path) as _file:
14+
return yaml.safe_load(_file).get(util_name, {})
15+
return {}
16+
17+
918
# Reference: https://gist.github.com/welel/9cf860dd3f4d3e09f9b4305878b3a04e
1019
class ListParamType(click.ParamType):
1120
"""Represents the list type of a CLI parameter.

config.example.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pyutils-unusedcode:
2+
exclude_files:
3+
- "my_exclude_file.py"
4+
exclude_function_prefix:
5+
- "my_exclude_function_prefix"
6+
pyutils-polarion-verify-tc-requirements:
7+
project_id: "ABC"

0 commit comments

Comments
 (0)