From a6860616e8e2b805f18a19d671ca8aea0ca8f697 Mon Sep 17 00:00:00 2001 From: leonardomilv3 Date: Tue, 9 Jul 2024 22:24:33 -0300 Subject: [PATCH 1/7] fix: sonar version and properties --- .github/workflows/metrics.yml | 2 +- .github/workflows/test.yml | 4 ++-- README.md | 2 +- sonar-project.properties | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/metrics.yml b/.github/workflows/metrics.yml index 5107a671..3c3d7137 100644 --- a/.github/workflows/metrics.yml +++ b/.github/workflows/metrics.yml @@ -25,7 +25,7 @@ jobs: run: | git config --global user.email "${{secrets.USER_EMAIL}}" git config --global user.name "${{secrets.USER_NAME}}" - git clone --single-branch --branch main "https://x-access-token:${{secrets.API_TOKEN_DOC}}@github.com/fga-eps-mds/2023.2-MeasureSoftGram-DOC" doc + git clone --single-branch --branch main "https://x-access-token:${{secrets.API_TOKEN_DOC}}@github.com/fga-eps-mds/2024.1-MeasureSoftGram-DOC" doc mkdir -p doc/analytics-raw-data cp -R analytics-raw-data/*.json doc/analytics-raw-data cd doc/ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cd48269f..4c5ecca1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,13 +31,13 @@ jobs: run: tox - name: Scanner do SonarCloud - uses: SonarSource/sonarcloud-github-action@v1.8 + uses: SonarSource/sonarcloud-github-action@v2.3.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - name: Envia cobertura para o Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4.0.1 with: token: ${{ secrets.CODECOV_TOKEN }} directory: ./ diff --git a/README.md b/README.md index f128d3ff..78b7343b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 2023-2 MeasureSoftGram-CLI +# 2024-1 MeasureSoftGram-CLI ## Badges diff --git a/sonar-project.properties b/sonar-project.properties index f313c8cf..5f04bd42 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,4 +1,4 @@ -sonar.projectKey=fga-eps-mds_2023-2-MeasureSoftGram-CLI +sonar.projectKey=fga-eps-mds_2024.1-MeasureSoftGram-CLI sonar.organization=fga-eps-mds-1 sonar.python.version=3 From de428406e4d759d9b679469ee65c5e7e3a4d3d25 Mon Sep 17 00:00:00 2001 From: Adne Moretti <64036847+AdneMoretti@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:01:08 -0300 Subject: [PATCH 2/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 78b7343b..ada37c1d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # 2024-1 MeasureSoftGram-CLI - +Command line project to MeasureSoftGram ## Badges [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=fga-eps-mds_2023-1-MeasureSoftGram-CLI&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=fga-eps-mds_2023-1-MeasureSoftGram-CLI) From 037e30caed6c19e8faee8db59db379f5a7dd3312 Mon Sep 17 00:00:00 2001 From: Thiago Gomes Date: Sat, 27 Jul 2024 16:19:53 -0300 Subject: [PATCH 3/7] Feat: add norm diff command --- src/cli/commands/cmd_norm_diff.py | 91 +++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/cli/commands/cmd_norm_diff.py diff --git a/src/cli/commands/cmd_norm_diff.py b/src/cli/commands/cmd_norm_diff.py new file mode 100644 index 00000000..086b750f --- /dev/null +++ b/src/cli/commands/cmd_norm_diff.py @@ -0,0 +1,91 @@ +import logging +from core.transformations import norm_diff +from src.cli.jsonReader import open_json_file +from src.cli.utils import print_error, print_info, print_rule +from src.cli.exceptions import exceptions +import numpy as np + +logger = logging.getLogger("msgram") + +def read_json_file(file_path, sort_key=None): + try: + json_data = open_json_file(file_path) + return sorted(json_data, key=lambda x: x[sort_key]) if sort_key else json_data + except exceptions.MeasureSoftGramCLIException as e: + print_error(f"[red]Error reading file {file_path}: {e}\n") + print_rule() + exit(1) + +def read_calculated_file(extracted_calculation): + try: + calculated_data = [] + json = open_json_file(extracted_calculation) + for item in json: + characteristics = sorted(item["characteristics"], key=lambda x: x["key"]) + repository = item["repository"][0]["value"] + version = item["version"][0]["value"] + calculated_data.append( + { + "repository": repository, + "version": version, + "characteristics": characteristics, + } + ) + + return calculated_data + except exceptions.MeasureSoftGramCLIException as e: + print_error( + f"[red]Error reading calculated file in {extracted_calculation}: {e}\n" + ) + print_rule() + exit(1) + +def command_norm_diff(args): + try: + planned_path = args["planned_path"] + calculated_path = args["calculated_path"] + except KeyError as e: + logger.error(f"KeyError: args[{e}] - non-existent parameters") + print_error(f"KeyError: args[{e}] - non-existent parameters") + exit(1) + + planned_data = read_json_file(planned_path, sort_key="key") + calculated_data = read_calculated_file(calculated_path) + + planned_vector, calculated_vector = extract_values(planned_data, calculated_data) + norm_diff_value = norm_diff(planned_vector, calculated_vector) + + print_info("\n[#A9A9A9]Norm diff calculation performed successfully![/]") + print_info("[#A9A9A9]For more detailed informations use 'diff' command.[/]") + print(f"Norm Diff: {norm_diff_value}") + + print_rule() + +def extract_values(planned_data, calculated_data): + try: + planned = planned_data + calculated = [] + for item in calculated_data: + for characteristic in item['characteristics']: + calculated.append({'key': characteristic['key'], 'value': characteristic['value']}) + + + planned_keys = {item['key'].strip() for item in planned} + calculated_keys = {item['key'].strip() for item in calculated} + + if planned_keys != calculated_keys: + raise exceptions.MeasureSoftGramCLIException( + "Planned and calculated files have different characteristics" + ) + + planned_dict = {item['key'].strip(): item['value'] for item in planned} + calculated_dict = {item['key'].strip(): item['value'] for item in calculated} + + planned_values = [planned_dict[key] for key in planned_keys] + calculated_values = [calculated_dict[key] for key in planned_keys] + + return (np.array(planned_values), np.array(calculated_values)) + except exceptions.MeasureSoftGramCLIException as e: + print_error(f"[red]Error extracting values: {e}\n") + print_rule() + exit(1) From 837ed07d8596bf489a755af3e8ef2452fcf32ab9 Mon Sep 17 00:00:00 2001 From: Thiago Gomes Date: Sat, 27 Jul 2024 16:20:31 -0300 Subject: [PATCH 4/7] Chore: add parser to norm diff command --- src/cli/commands/__init__.py | 1 + src/cli/parsers.py | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/cli/commands/__init__.py b/src/cli/commands/__init__.py index 1486296d..901e15dd 100644 --- a/src/cli/commands/__init__.py +++ b/src/cli/commands/__init__.py @@ -1,3 +1,4 @@ from src.cli.commands.cmd_init import command_init from src.cli.commands.cmd_extract import command_extract from src.cli.commands.cmd_calculate import command_calculate +from src.cli.commands.cmd_norm_diff import command_norm_diff diff --git a/src/cli/parsers.py b/src/cli/parsers.py index c57ab131..3e2780af 100644 --- a/src/cli/parsers.py +++ b/src/cli/parsers.py @@ -6,6 +6,7 @@ from src.cli.commands.cmd_extract import command_extract from src.cli.commands.cmd_calculate import command_calculate from src.cli.commands.cmd_list import command_list +from src.cli.commands.cmd_norm_diff import command_norm_diff from src.config.settings import ( AVAILABLE_IMPORTS, @@ -152,4 +153,26 @@ def create_parser(): ) parser_calculate.set_defaults(func=command_calculate) # function command calculate + # =====================================< COMMAND norm-diff >===================================== + parser_norm_diff = subparsers.add_parser( + "norm-diff", + help="Calculate the norm difference between the planned metrics and the developed.", + ) + + parser_norm_diff.add_argument( + "-p", + "--planned_path", + type=lambda p: Path(p).absolute(), + help="Path to the json with the planned metrics.", + ) + + parser_norm_diff.add_argument( + "-c", + "--calculated_path", + type=lambda p: Path(p).absolute(), + help="Path to the json with the calculated metrics.", + ) + + parser_norm_diff.set_defaults(func=command_norm_diff) # function command list config + return parser From ffcd3ce9ea7c72d2abff0f1bbe6cda6c0c988601 Mon Sep 17 00:00:00 2001 From: Thiago Gomes Date: Sun, 28 Jul 2024 20:08:17 -0300 Subject: [PATCH 5/7] Fix: adjust read planned file function name --- src/cli/commands/cmd_norm_diff.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/cli/commands/cmd_norm_diff.py b/src/cli/commands/cmd_norm_diff.py index 086b750f..f9c5684c 100644 --- a/src/cli/commands/cmd_norm_diff.py +++ b/src/cli/commands/cmd_norm_diff.py @@ -7,19 +7,19 @@ logger = logging.getLogger("msgram") -def read_json_file(file_path, sort_key=None): +def read_planned_file(file_path, sort_key=None): try: json_data = open_json_file(file_path) return sorted(json_data, key=lambda x: x[sort_key]) if sort_key else json_data except exceptions.MeasureSoftGramCLIException as e: - print_error(f"[red]Error reading file {file_path}: {e}\n") + print_error(f"[red]Error reading planned file in {file_path}: {e}\n") print_rule() exit(1) -def read_calculated_file(extracted_calculation): +def read_calculated_file(file_path): try: calculated_data = [] - json = open_json_file(extracted_calculation) + json = open_json_file(file_path) for item in json: characteristics = sorted(item["characteristics"], key=lambda x: x["key"]) repository = item["repository"][0]["value"] @@ -35,7 +35,7 @@ def read_calculated_file(extracted_calculation): return calculated_data except exceptions.MeasureSoftGramCLIException as e: print_error( - f"[red]Error reading calculated file in {extracted_calculation}: {e}\n" + f"[red]Error reading calculated file in {file_path}: {e}\n" ) print_rule() exit(1) @@ -49,7 +49,7 @@ def command_norm_diff(args): print_error(f"KeyError: args[{e}] - non-existent parameters") exit(1) - planned_data = read_json_file(planned_path, sort_key="key") + planned_data = read_planned_file(planned_path, sort_key="key") calculated_data = read_calculated_file(calculated_path) planned_vector, calculated_vector = extract_values(planned_data, calculated_data) @@ -58,7 +58,6 @@ def command_norm_diff(args): print_info("\n[#A9A9A9]Norm diff calculation performed successfully![/]") print_info("[#A9A9A9]For more detailed informations use 'diff' command.[/]") print(f"Norm Diff: {norm_diff_value}") - print_rule() def extract_values(planned_data, calculated_data): From a78a8919f870eb2935112532a98b4df66d6d04f9 Mon Sep 17 00:00:00 2001 From: Thiago Gomes Date: Sun, 28 Jul 2024 20:10:40 -0300 Subject: [PATCH 6/7] Test: add tests to test norm diff command --- .gitignore | 2 + tests/unit/data/calculated.json | 52 +++++++++++ tests/unit/data/missmatch-planned.json | 14 +++ tests/unit/data/planned.json | 10 +++ tests/unit/test_norm_diff.py | 119 +++++++++++++++++++++++++ 5 files changed, 197 insertions(+) create mode 100644 tests/unit/data/calculated.json create mode 100644 tests/unit/data/missmatch-planned.json create mode 100644 tests/unit/data/planned.json create mode 100644 tests/unit/test_norm_diff.py diff --git a/.gitignore b/.gitignore index a765f380..b4c8550e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,8 @@ __pycache__/ venv/ ENV/ .tox +msgram-cli-venv +.python-version # Distribution / packaging .Python diff --git a/tests/unit/data/calculated.json b/tests/unit/data/calculated.json new file mode 100644 index 00000000..628dd3fb --- /dev/null +++ b/tests/unit/data/calculated.json @@ -0,0 +1,52 @@ +[ + { + "repository": [ + { + "key": "repository", + "value": "Example Repository" + } + ], + "version": [ + { + "key": "version", + "value": "27-07-2024-21-40" + } + ], + "measures": [ + { + "key": "first_measure", + "value": 1.0 + }, + { + "key": "second_measure", + "value": 0.9996066627522133 + } + ], + "subcharacteristics": [ + { + "key": "first_subcharacteristics", + "value": 0.8421061048464034 + }, + { + "key": "second_subcharacteristics", + "value": 0.6415437113263573 + } + ], + "characteristics": [ + { + "key": "first_characteristics", + "value": 0.8421061048464034 + }, + { + "key": "second_characteristics", + "value": 0.6415437113263573 + } + ], + "tsqmi": [ + { + "key": "tsqmi", + "value": 0.7485723162667646 + } + ] + } +] \ No newline at end of file diff --git a/tests/unit/data/missmatch-planned.json b/tests/unit/data/missmatch-planned.json new file mode 100644 index 00000000..63501135 --- /dev/null +++ b/tests/unit/data/missmatch-planned.json @@ -0,0 +1,14 @@ +[ + { + "key": "first_characteristics", + "value": 0.95 + }, + { + "key": "second_characteristics ", + "value": 0.95 + }, + { + "key": "third_characteristics ", + "value": 0.95 + } + ] \ No newline at end of file diff --git a/tests/unit/data/planned.json b/tests/unit/data/planned.json new file mode 100644 index 00000000..52587df4 --- /dev/null +++ b/tests/unit/data/planned.json @@ -0,0 +1,10 @@ +[ + { + "key": "first_characteristics", + "value": 0.95 + }, + { + "key": "second_characteristics ", + "value": 0.95 + } + ] \ No newline at end of file diff --git a/tests/unit/test_norm_diff.py b/tests/unit/test_norm_diff.py new file mode 100644 index 00000000..2e41dee7 --- /dev/null +++ b/tests/unit/test_norm_diff.py @@ -0,0 +1,119 @@ +from io import StringIO +from pathlib import Path +import shutil +import sys +import tempfile + +import pytest +from src.cli.commands.cmd_norm_diff import command_norm_diff + +def test_norm_diff(): + config_dirpath = tempfile.mkdtemp() + + captured_output = StringIO() + sys.stdout = captured_output + + shutil.copy("tests/unit/data/planned.json", f"{config_dirpath}/planned.json") + shutil.copy("tests/unit/data/calculated.json", f"{config_dirpath}/calculated.json") + + command_norm_diff({ + "planned_path": Path(config_dirpath) / "planned.json", + "calculated_path": Path(config_dirpath) / "calculated.json", + }) + + sys.stdout = sys.__stdout__ + + output = captured_output.getvalue() + + assert "Norm diff calculation performed successfully!" in output + assert "For more detailed informations use 'diff' command." in output + + norm_diff_value = float(output.split("Norm Diff:")[1].split("\n")[0].strip()) + assert norm_diff_value == 0.24323122001478284 + +def test_missing_args(): + config_dirpath = tempfile.mkdtemp() + + captured_output = StringIO() + sys.stdout = captured_output + + shutil.copy("tests/unit/data/planned.json", f"{config_dirpath}/planned.json") + shutil.copy("tests/unit/data/calculated.json", f"{config_dirpath}/calculated.json") + + with pytest.raises(SystemExit) as excinfo: + command_norm_diff({ + "planned_path": Path(config_dirpath) / "planned.json" + }) + + sys.stdout = sys.__stdout__ + + output = captured_output.getvalue() + + assert excinfo.value.code == 1 + assert "non-existent parameters" in output + +def test_invalid_calculated_file(): + config_dirpath = tempfile.mkdtemp() + + captured_output = StringIO() + sys.stdout = captured_output + + shutil.copy("tests/unit/data/planned.json", f"{config_dirpath}/planned.json") + shutil.copy("tests/unit/data/calculated.json", f"{config_dirpath}/calculated.json") + + with pytest.raises(SystemExit) as excinfo: + command_norm_diff({ + "planned_path": Path(config_dirpath) / "planned.json", + "calculated_path": Path(config_dirpath) / "invalid.json", + }) + + sys.stdout = sys.__stdout__ + + output = captured_output.getvalue() + + assert excinfo.value.code == 1 + assert "Error reading calculate" in output + +def test_invalid_planned_file(): + config_dirpath = tempfile.mkdtemp() + + captured_output = StringIO() + sys.stdout = captured_output + + shutil.copy("tests/unit/data/planned.json", f"{config_dirpath}/planned.json") + shutil.copy("tests/unit/data/calculated.json", f"{config_dirpath}/calculated.json") + + with pytest.raises(SystemExit) as excinfo: + command_norm_diff({ + "planned_path": Path(config_dirpath) / "invalid.json", + "calculated_path": Path(config_dirpath) / "calculated.json", + }) + + sys.stdout = sys.__stdout__ + + output = captured_output.getvalue() + + assert excinfo.value.code == 1 + assert "Error reading planned" in output + +def test_missmatch_values(): + config_dirpath = tempfile.mkdtemp() + + captured_output = StringIO() + sys.stdout = captured_output + + shutil.copy("tests/unit/data/missmatch-planned.json", f"{config_dirpath}/missmatch-planned.json") + shutil.copy("tests/unit/data/calculated.json", f"{config_dirpath}/calculated.json") + + with pytest.raises(SystemExit) as excinfo: + command_norm_diff({ + "planned_path": Path(config_dirpath) / "missmatch-planned.json", + "calculated_path": Path(config_dirpath) / "calculated.json", + }) + + sys.stdout = sys.__stdout__ + + output = captured_output.getvalue() + + assert excinfo.value.code == 1 + assert "Error extracting values" in output \ No newline at end of file From d3964dd23ab7fbf6ffcbf817af00c0dcf56be24a Mon Sep 17 00:00:00 2001 From: Thiago Gomes Date: Sun, 28 Jul 2024 21:01:22 -0300 Subject: [PATCH 7/7] Fix: adjust lint of cmd norm diff files --- src/cli/aggregate_metrics.py | 12 +++--- src/cli/commands/cmd_calculate.py | 23 +++++++---- src/cli/commands/cmd_norm_diff.py | 25 +++++++----- src/cli/parsers.py | 4 +- tests/unit/test_aggregate.py | 29 +++++++++---- tests/unit/test_calculate.py | 44 ++++++++++---------- tests/unit/test_norm_diff.py | 56 ++++++++++++++++---------- tests/unit/test_parser.py | 67 +++++++++++++++++++------------ 8 files changed, 158 insertions(+), 102 deletions(-) diff --git a/src/cli/aggregate_metrics.py b/src/cli/aggregate_metrics.py index f35fc282..19d76793 100644 --- a/src/cli/aggregate_metrics.py +++ b/src/cli/aggregate_metrics.py @@ -127,7 +127,9 @@ def process_github_metrics(folder_path, github_files, metrics): github_file_content = read_msgram(github_file_path) if not github_file_content: - print_error(f"> [red] Error to read github metrics in: {github_file_path}\n") + print_error( + f"> [red] Error to read github metrics in: {github_file_path}\n" + ) continue github_key = next(iter(github_file_content.keys() - metrics["sonar"]), "") @@ -155,9 +157,9 @@ def process_github_metrics(folder_path, github_files, metrics): def find_common_part(sonar_filename, github_result): sonar_filename_root, _ = os.path.splitext(sonar_filename) - sonar_parts = sonar_filename_root.split('-') + sonar_parts = sonar_filename_root.split("-") if len(sonar_parts) >= 7: - sonar_key = '-'.join(sonar_parts[:7]) + sonar_key = "-".join(sonar_parts[:7]) for github_filename, github_metrics in github_result: github_filename_root, _ = os.path.splitext(github_filename) @@ -187,9 +189,7 @@ def aggregate_metrics(folder_path, config: json): config_has_github = should_process_github_metrics(config) if config_has_github: - github_result = process_github_metrics( - folder_path, github_files, metrics - ) + github_result = process_github_metrics(folder_path, github_files, metrics) if not github_result: print_error("> [red]Error: Unexpected result from process_github_metrics") diff --git a/src/cli/commands/cmd_calculate.py b/src/cli/commands/cmd_calculate.py index 1ecc4579..8935949c 100644 --- a/src/cli/commands/cmd_calculate.py +++ b/src/cli/commands/cmd_calculate.py @@ -118,12 +118,14 @@ def calculate_all(json_data, file_name, config): "repository": [{"key": "repository", "value": repository}], "version": [{"key": "version", "value": version}] if version else [], "measures": data_measures["measures"] if data_measures else [], - "subcharacteristics": data_subcharacteristics["subcharacteristics"] - if data_subcharacteristics - else [], - "characteristics": data_characteristics["characteristics"] - if data_characteristics - else [], + "subcharacteristics": ( + data_subcharacteristics["subcharacteristics"] + if data_subcharacteristics + else [] + ), + "characteristics": ( + data_characteristics["characteristics"] if data_characteristics else [] + ), "tsqmi": data_tsqmi["tsqmi"] if data_tsqmi else [], } @@ -186,12 +188,17 @@ def show_tree(data_calculated, pre_config): for subchar_c in char_c["subcharacteristics"]: subchar = get_obj_by_element(subcharacteristics, "key", subchar_c["key"]) if subchar: - sub_char_tree = Node(f"[blue]{subchar['key']} {subchar['value']}", parent=char_tree) + sub_char_tree = Node( + f"[blue]{subchar['key']} {subchar['value']}", parent=char_tree + ) for measure_c in subchar_c["measures"]: measure = get_obj_by_element(measures, "key", measure_c["key"]) if measure: - Node(f"[yellow]{measure['key']} {measure['value']}", parent=sub_char_tree) + Node( + f"[yellow]{measure['key']} {measure['value']}", + parent=sub_char_tree, + ) for pre, fill, node in RenderTree(tsqmi_tree): print(f"{pre}{node.name}") diff --git a/src/cli/commands/cmd_norm_diff.py b/src/cli/commands/cmd_norm_diff.py index f9c5684c..83979041 100644 --- a/src/cli/commands/cmd_norm_diff.py +++ b/src/cli/commands/cmd_norm_diff.py @@ -7,6 +7,7 @@ logger = logging.getLogger("msgram") + def read_planned_file(file_path, sort_key=None): try: json_data = open_json_file(file_path) @@ -16,6 +17,7 @@ def read_planned_file(file_path, sort_key=None): print_rule() exit(1) + def read_calculated_file(file_path): try: calculated_data = [] @@ -34,12 +36,11 @@ def read_calculated_file(file_path): return calculated_data except exceptions.MeasureSoftGramCLIException as e: - print_error( - f"[red]Error reading calculated file in {file_path}: {e}\n" - ) + print_error(f"[red]Error reading calculated file in {file_path}: {e}\n") print_rule() exit(1) + def command_norm_diff(args): try: planned_path = args["planned_path"] @@ -60,25 +61,27 @@ def command_norm_diff(args): print(f"Norm Diff: {norm_diff_value}") print_rule() + def extract_values(planned_data, calculated_data): try: planned = planned_data calculated = [] for item in calculated_data: - for characteristic in item['characteristics']: - calculated.append({'key': characteristic['key'], 'value': characteristic['value']}) - + for characteristic in item["characteristics"]: + calculated.append( + {"key": characteristic["key"], "value": characteristic["value"]} + ) - planned_keys = {item['key'].strip() for item in planned} - calculated_keys = {item['key'].strip() for item in calculated} + planned_keys = {item["key"].strip() for item in planned} + calculated_keys = {item["key"].strip() for item in calculated} if planned_keys != calculated_keys: raise exceptions.MeasureSoftGramCLIException( "Planned and calculated files have different characteristics" ) - - planned_dict = {item['key'].strip(): item['value'] for item in planned} - calculated_dict = {item['key'].strip(): item['value'] for item in calculated} + + planned_dict = {item["key"].strip(): item["value"] for item in planned} + calculated_dict = {item["key"].strip(): item["value"] for item in calculated} planned_values = [planned_dict[key] for key in planned_keys] calculated_values = [calculated_dict[key] for key in planned_keys] diff --git a/src/cli/parsers.py b/src/cli/parsers.py index 3e2780af..b1a4d73f 100644 --- a/src/cli/parsers.py +++ b/src/cli/parsers.py @@ -173,6 +173,8 @@ def create_parser(): help="Path to the json with the calculated metrics.", ) - parser_norm_diff.set_defaults(func=command_norm_diff) # function command list config + parser_norm_diff.set_defaults( + func=command_norm_diff + ) # function command list config return parser diff --git a/tests/unit/test_aggregate.py b/tests/unit/test_aggregate.py index 17110739..1e05c642 100644 --- a/tests/unit/test_aggregate.py +++ b/tests/unit/test_aggregate.py @@ -13,7 +13,7 @@ process_github_metrics, process_sonar_metrics, aggregate_metrics, - find_common_part + find_common_part, ) @@ -93,7 +93,9 @@ def test_process_github_metrics(): metrics = {"sonar": ["some_metric"], "github": ["resolved_issues", "total_issues"]} - result = process_github_metrics(folder_path, [github_file_name, github_file_name], metrics) + result = process_github_metrics( + folder_path, [github_file_name, github_file_name], metrics + ) expected_result = ( github_file_name, @@ -152,10 +154,12 @@ def test_aggregate_metrics(): folder_path = temp_dir msgram_file1 = os.path.join( - folder_path, "fga-eps-mds-2023-2-MeasureSoftGram-CLI-01-05-2023-21-40-30-develop-extracted.msgram" + folder_path, + "fga-eps-mds-2023-2-MeasureSoftGram-CLI-01-05-2023-21-40-30-develop-extracted.msgram", ) msgram_file2 = os.path.join( - folder_path, "github_fga-eps-mds-2023-2-MeasureSoftGram-CLI-09-12-2023-01-24-36-extracted.msgram" + folder_path, + "github_fga-eps-mds-2023-2-MeasureSoftGram-CLI-09-12-2023-01-24-36-extracted.msgram", ) with open(msgram_file1, "w") as file: @@ -177,7 +181,8 @@ def test_aggregate_metrics(): assert result is True output_file_path = os.path.join( - folder_path, "fga-eps-mds-2023-2-MeasureSoftGram-CLI-01-05-2023-21-40-30-develop-extracted.metrics" + folder_path, + "fga-eps-mds-2023-2-MeasureSoftGram-CLI-01-05-2023-21-40-30-develop-extracted.metrics", ) assert os.path.exists(output_file_path) @@ -200,11 +205,19 @@ def test_aggregate_metrics(): def test_find_common_part(): sonar_filename = "fga-eps-mds-2023-2-MeasureSoftGram-Parser-02-06-2023-21-40-30-develop-extracted" github_files = [ - ("github_fga-eps-mds-2023-2-MeasureSoftGram-Parser-09-12-2023-01-24-36-extracted.msgram", "Metrics1"), - ("github_fga-eps-mds-2023-2-MeasureSoftGram-CLI-09-12-2023-01-24-36-extracted.msgram", "Metrics2") + ( + "github_fga-eps-mds-2023-2-MeasureSoftGram-Parser-09-12-2023-01-24-36-extracted.msgram", + "Metrics1", + ), + ( + "github_fga-eps-mds-2023-2-MeasureSoftGram-CLI-09-12-2023-01-24-36-extracted.msgram", + "Metrics2", + ), ] - with patch("builtins.print"): # Mocking the print function to avoid print statements during testing + with patch( + "builtins.print" + ): # Mocking the print function to avoid print statements during testing result = find_common_part(sonar_filename, github_files) assert result == "Metrics1" diff --git a/tests/unit/test_calculate.py b/tests/unit/test_calculate.py index 0b2bbcbb..36c6228c 100644 --- a/tests/unit/test_calculate.py +++ b/tests/unit/test_calculate.py @@ -23,30 +23,32 @@ def test_show_tree(capfd): data_calculated = { - 'repository': [{'key': 'repository', 'value': 'fga-eps-mds-2022-2-MeasureSoftGram-CLI'}], - 'version': [{'key': 'version', 'value': '01-05-2023-21-40'}], - 'measures': [ - {'key': 'passed_tests', 'value': 1.0}, - {'key': 'test_builds', 'value': 0.9996066627522133}, - {'key': 'test_coverage', 'value': 0.40234848484848484}, - {'key': 'non_complex_file_density', 'value': 0.44347274991556906}, - {'key': 'commented_file_density', 'value': 0.04318181818181818}, - {'key': 'duplication_absence', 'value': 1.0}, - {'key': 'team_throughput', 'value': 0.6969696969696971}, - {'key': 'ci_feedback_time', 'value': 0.06117908787541713} + "repository": [ + {"key": "repository", "value": "fga-eps-mds-2022-2-MeasureSoftGram-CLI"} + ], + "version": [{"key": "version", "value": "01-05-2023-21-40"}], + "measures": [ + {"key": "passed_tests", "value": 1.0}, + {"key": "test_builds", "value": 0.9996066627522133}, + {"key": "test_coverage", "value": 0.40234848484848484}, + {"key": "non_complex_file_density", "value": 0.44347274991556906}, + {"key": "commented_file_density", "value": 0.04318181818181818}, + {"key": "duplication_absence", "value": 1.0}, + {"key": "team_throughput", "value": 0.6969696969696971}, + {"key": "ci_feedback_time", "value": 0.06117908787541713}, ], - 'subcharacteristics': [ - {'key': 'testing_status', 'value': 0.8421061048464034}, - {'key': 'maturity', 'value': 0.06117908787541713}, - {'key': 'modifiability', 'value': 0.6415437113263573}, - {'key': 'functional_completeness', 'value': 0.6969696969696971} + "subcharacteristics": [ + {"key": "testing_status", "value": 0.8421061048464034}, + {"key": "maturity", "value": 0.06117908787541713}, + {"key": "modifiability", "value": 0.6415437113263573}, + {"key": "functional_completeness", "value": 0.6969696969696971}, ], - 'characteristics': [ - {'key': 'reliability', 'value': 0.5970282960684735}, - {'key': 'maintainability', 'value': 0.6415437113263573}, - {'key': 'functional_suitability', 'value': 0.6969696969696971} + "characteristics": [ + {"key": "reliability", "value": 0.5970282960684735}, + {"key": "maintainability", "value": 0.6415437113263573}, + {"key": "functional_suitability", "value": 0.6969696969696971}, ], - 'tsqmi': [{'key': 'tsqmi', 'value': 0.6455181338484177}] + "tsqmi": [{"key": "tsqmi", "value": 0.6455181338484177}], } expected_output = ( diff --git a/tests/unit/test_norm_diff.py b/tests/unit/test_norm_diff.py index 2e41dee7..29f24918 100644 --- a/tests/unit/test_norm_diff.py +++ b/tests/unit/test_norm_diff.py @@ -7,6 +7,7 @@ import pytest from src.cli.commands.cmd_norm_diff import command_norm_diff + def test_norm_diff(): config_dirpath = tempfile.mkdtemp() @@ -16,10 +17,12 @@ def test_norm_diff(): shutil.copy("tests/unit/data/planned.json", f"{config_dirpath}/planned.json") shutil.copy("tests/unit/data/calculated.json", f"{config_dirpath}/calculated.json") - command_norm_diff({ - "planned_path": Path(config_dirpath) / "planned.json", - "calculated_path": Path(config_dirpath) / "calculated.json", - }) + command_norm_diff( + { + "planned_path": Path(config_dirpath) / "planned.json", + "calculated_path": Path(config_dirpath) / "calculated.json", + } + ) sys.stdout = sys.__stdout__ @@ -31,6 +34,7 @@ def test_norm_diff(): norm_diff_value = float(output.split("Norm Diff:")[1].split("\n")[0].strip()) assert norm_diff_value == 0.24323122001478284 + def test_missing_args(): config_dirpath = tempfile.mkdtemp() @@ -41,9 +45,7 @@ def test_missing_args(): shutil.copy("tests/unit/data/calculated.json", f"{config_dirpath}/calculated.json") with pytest.raises(SystemExit) as excinfo: - command_norm_diff({ - "planned_path": Path(config_dirpath) / "planned.json" - }) + command_norm_diff({"planned_path": Path(config_dirpath) / "planned.json"}) sys.stdout = sys.__stdout__ @@ -52,6 +54,7 @@ def test_missing_args(): assert excinfo.value.code == 1 assert "non-existent parameters" in output + def test_invalid_calculated_file(): config_dirpath = tempfile.mkdtemp() @@ -62,10 +65,12 @@ def test_invalid_calculated_file(): shutil.copy("tests/unit/data/calculated.json", f"{config_dirpath}/calculated.json") with pytest.raises(SystemExit) as excinfo: - command_norm_diff({ - "planned_path": Path(config_dirpath) / "planned.json", - "calculated_path": Path(config_dirpath) / "invalid.json", - }) + command_norm_diff( + { + "planned_path": Path(config_dirpath) / "planned.json", + "calculated_path": Path(config_dirpath) / "invalid.json", + } + ) sys.stdout = sys.__stdout__ @@ -74,6 +79,7 @@ def test_invalid_calculated_file(): assert excinfo.value.code == 1 assert "Error reading calculate" in output + def test_invalid_planned_file(): config_dirpath = tempfile.mkdtemp() @@ -84,10 +90,12 @@ def test_invalid_planned_file(): shutil.copy("tests/unit/data/calculated.json", f"{config_dirpath}/calculated.json") with pytest.raises(SystemExit) as excinfo: - command_norm_diff({ - "planned_path": Path(config_dirpath) / "invalid.json", - "calculated_path": Path(config_dirpath) / "calculated.json", - }) + command_norm_diff( + { + "planned_path": Path(config_dirpath) / "invalid.json", + "calculated_path": Path(config_dirpath) / "calculated.json", + } + ) sys.stdout = sys.__stdout__ @@ -96,24 +104,30 @@ def test_invalid_planned_file(): assert excinfo.value.code == 1 assert "Error reading planned" in output + def test_missmatch_values(): config_dirpath = tempfile.mkdtemp() captured_output = StringIO() sys.stdout = captured_output - shutil.copy("tests/unit/data/missmatch-planned.json", f"{config_dirpath}/missmatch-planned.json") + shutil.copy( + "tests/unit/data/missmatch-planned.json", + f"{config_dirpath}/missmatch-planned.json", + ) shutil.copy("tests/unit/data/calculated.json", f"{config_dirpath}/calculated.json") with pytest.raises(SystemExit) as excinfo: - command_norm_diff({ - "planned_path": Path(config_dirpath) / "missmatch-planned.json", - "calculated_path": Path(config_dirpath) / "calculated.json", - }) + command_norm_diff( + { + "planned_path": Path(config_dirpath) / "missmatch-planned.json", + "calculated_path": Path(config_dirpath) / "calculated.json", + } + ) sys.stdout = sys.__stdout__ output = captured_output.getvalue() assert excinfo.value.code == 1 - assert "Error extracting values" in output \ No newline at end of file + assert "Error extracting values" in output diff --git a/tests/unit/test_parser.py b/tests/unit/test_parser.py index 5c0894ab..56320009 100644 --- a/tests/unit/test_parser.py +++ b/tests/unit/test_parser.py @@ -25,46 +25,61 @@ def mock_command_list(args): def test_parser_init(): parser = create_parser() - args = parser.parse_args(['init', '-cp', '/path/to/config']) + args = parser.parse_args(["init", "-cp", "/path/to/config"]) assert args.func == command_init - assert args.config_path == Path('/path/to/config') + assert args.config_path == Path("/path/to/config") def test_parser_list(): parser = create_parser() - args = parser.parse_args(['list', '-cp', '/path/to/config', 'all']) + args = parser.parse_args(["list", "-cp", "/path/to/config", "all"]) assert args.func == command_list - assert args.config_path == Path('/path/to/config') - assert args.all == 'all' + assert args.config_path == Path("/path/to/config") + assert args.all == "all" def test_parser_extract(): parser = create_parser() - args = parser.parse_args(['extract', - '-o', - 'sonarqube', - '-dp', - '/path/to/data', - '-ep', - '/path/to/extracted', - '-le', - 'py', - '-rep', - '/path/to/repo']) + args = parser.parse_args( + [ + "extract", + "-o", + "sonarqube", + "-dp", + "/path/to/data", + "-ep", + "/path/to/extracted", + "-le", + "py", + "-rep", + "/path/to/repo", + ] + ) assert args.func == command_extract - assert args.output_origin == 'sonarqube' - assert args.data_path == Path('/path/to/data') - assert args.extracted_path == Path('/path/to/extracted') - assert args.language_extension == 'py' - assert args.repository_path == '/path/to/repo' + assert args.output_origin == "sonarqube" + assert args.data_path == Path("/path/to/data") + assert args.extracted_path == Path("/path/to/extracted") + assert args.language_extension == "py" + assert args.repository_path == "/path/to/repo" def test_parser_calculate(): parser = create_parser() - args = parser.parse_args(['calculate', 'all', '-ep', '/path/to/extracted', '-cp', '/path/to/config', '-o', 'csv']) + args = parser.parse_args( + [ + "calculate", + "all", + "-ep", + "/path/to/extracted", + "-cp", + "/path/to/config", + "-o", + "csv", + ] + ) assert args.func == command_calculate - assert args.all == 'all' - assert args.extracted_path == Path('/path/to/extracted') - assert args.config_path == Path('/path/to/config') - assert args.output_format == 'csv' + assert args.all == "all" + assert args.extracted_path == Path("/path/to/extracted") + assert args.config_path == Path("/path/to/config") + assert args.output_format == "csv"