From 6b23c4052b2962c893afe6efac610e016ff443e3 Mon Sep 17 00:00:00 2001 From: Inengs Date: Tue, 3 Mar 2026 10:13:46 +0100 Subject: [PATCH 01/15] tests: add unit tests for AugurUUID and subclasses Signed-off-by: Inengs --- .../test_util/test_augur_uuid.py | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py diff --git a/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py b/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py new file mode 100644 index 000000000..0202980dc --- /dev/null +++ b/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py @@ -0,0 +1,86 @@ +import pytest +import uuid +from augur.tasks.util.AugurUUID import AugurUUID, GithubUUID, GitlabUUID, UnresolvableUUID + +# AugurUUID tests + +# this checks whether a brand new AugurUUID object starts as 16 zero bytes +def test_augur_uuid_initializes_with_16_zero_bytes(): + uid = AugurUUID() + assert len(uid.bytes) == 16 + assert all(b == 0 for b in uid.bytes) + +# checks that githubUUID sets its platform number to 1 +def test_github_uuid_platform_is_1(): + uid = GithubUUID() + assert uid["platform"] == 1 + +# checks that gitlabUUID sets its platform number to 2 +def test_gitlab_uuid_platform_is_2(): + uid = GitlabUUID() + assert uid["platform"] == 2 + +def test_unresolvable_uuid_platform_is_0(): + uid = UnresolvableUUID() + assert uid["platform"] == 0 + +# checks the that you can store a value in the user field +def test_github_uuid_set_user(): + uid = GithubUUID() + uid["user"] = 12345 + assert uid["user"] == 12345 + +# checks the that you can store a value in the user field +def test_gitlab_uuid_set_user(): + uid = GitlabUUID() + uid["user"] = 99999 + assert uid["user"] == 99999 + +# checks that to_UUID returs the uuid.UUID object +def test_to_uuid_returns_valid_uuid(): + uid = GithubUUID() + uid["user"] = 15 + result = uid.to_UUID() + assert isinstance(result, uuid.UUID) + +# checks that set_byte correctly rejects a value that is too large +def test_set_byte_raises_on_invalid_value(): + uid = AugurUUID() + with pytest.raises(ValueError): + uid.set_byte(0, 256) # too big for one byte + +# checks that set_byte rejects an index that doesnt exist +def test_set_byte_raises_on_out_of_range_index(): + uid = AugurUUID() + with pytest.raises(IndexError): + uid.set_byte(16, 1) # index 16 is out of bounds + +# checks that 2 UUIDs with the same values are considered equal. +def test_equality(): + uid1 = GithubUUID() + uid2 = GithubUUID() + uid1["user"] = 100 + uid2["user"] = 100 + assert uid1 == uid2 + +# checks that 2 UUIDs with different values are not equal +def test_inequality(): + uid1 = GithubUUID() + uid2 = GithubUUID() + uid1["user"] = 100 + uid2["user"] = 200 + assert uid1 != uid2 + +# checks that writeint correctly rejects a number +def test_write_int_raises_on_overflow(): + uid = GithubUUID() + with pytest.raises(ValueError): + uid["user"] = 99999999999 # too big for 4 bytes + +# checks that the same user produces different user IDs across platforms +def test_github_and_gitlab_different_for_same_user(): + github_uid = GithubUUID() + gitlab_uid = GitlabUUID() + github_uid["user"] = 100 + gitlab_uid["user"] = 100 + assert github_uid != gitlab_uid \ No newline at end of file From f87fda64ed2ec6fa48f6495fa84bcdd3e0c0865d Mon Sep 17 00:00:00 2001 From: Inengs Date: Wed, 4 Mar 2026 01:04:34 +0100 Subject: [PATCH 02/15] tests: add test_augur_uuid.py to pytest testpaths in pyproject.toml Signed-off-by: Inengs --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 85f11e3e6..25edd9a69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -147,7 +147,8 @@ testpaths = [ "tests/test_classes", "tests/test_application/test_cli/test_csv_utils.py", "tests/test_tasks/test_task_utilities/test_util/test_worker_util.py" - # "tests/test_routes", # runs, but needs a fixture for connecting to the web interface of CollectOSS + "tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py", + # "tests/test_routes", # runs, but needs a fixture for connecting to the web interface of Augur # "tests/test_metrics", # "tests/test_tasks", # "tests/test_application", From a1ae7a57cdb5b9741e96f743f59d0320d8a84c22 Mon Sep 17 00:00:00 2001 From: Inengs Date: Fri, 6 Mar 2026 07:29:05 +0100 Subject: [PATCH 03/15] tests: add edge case and boundary tests for AugurUUID Signed-off-by: Inengs --- .../test_util/test_augur_uuid.py | 128 +++++++++++++++--- 1 file changed, 112 insertions(+), 16 deletions(-) diff --git a/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py b/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py index 0202980dc..2f81a8f84 100644 --- a/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py +++ b/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py @@ -20,21 +20,32 @@ def test_gitlab_uuid_platform_is_2(): uid = GitlabUUID() assert uid["platform"] == 2 -def test_unresolvable_uuid_platform_is_0(): - uid = UnresolvableUUID() - assert uid["platform"] == 0 - # checks the that you can store a value in the user field def test_github_uuid_set_user(): uid = GithubUUID() uid["user"] = 12345 assert uid["user"] == 12345 -# checks the that you can store a value in the user field -def test_gitlab_uuid_set_user(): - uid = GitlabUUID() - uid["user"] = 99999 - assert uid["user"] == 99999 +# tests platform_id edge cases +def test_set_platform_id_raises_on_non_integer(): + uid = AugurUUID() + with pytest.raises(ValueError): + uid.set_platform_id("github") + +def test_set_platform_id_raises_on_overflow(): + uid = AugurUUID() + with pytest.raises(ValueError): + uid.set_platform_id(256) # too big for 1 byte + +# checks that writing to one field doesnt accidentally overwrite bytes belonging to another field +def test_fields_dont_overlap(): + uid = GithubUUID() + + uid["user"] = 12345 + uid["repo"] = 99999 + + assert uid["user"] == 12345 + assert uid["repo"] == 99999 # checks that to_UUID returs the uuid.UUID object def test_to_uuid_returns_valid_uuid(): @@ -43,6 +54,46 @@ def test_to_uuid_returns_valid_uuid(): result = uid.to_UUID() assert isinstance(result, uuid.UUID) +# checks the start_byte is within range(0, 16) for set_bytes +def test_set_bytes_raises_on_invalid_start_byte(): + uid = AugurUUID() + with pytest.raises(ValueError): + uid.set_bytes([1, 2, 3], 16) + +# checks that set_bytes correctly raises an error when you write more bytes that will fit in the UUID starting at a given position +def test_set_bytes_raises_on_too_many_bytes(): + uid = AugurUUID() + with pytest.raises(ValueError): + uid.set_bytes([1] * 10, 10) + +# checks that writeint correctly rejects a number +def test_write_int_raises_on_overflow(): + uid = GithubUUID() + with pytest.raises(ValueError): + uid["user"] = 99999999999 # too big for 4 bytes + +def test_write_int_with_non_integer(): + uid = GithubUUID() + + with pytest.raises(ValueError): + uid.write_int("abc", 1, 4) + +def test_write_int_and_get_int_roundtrip(): + uid = AugurUUID() + uid.write_int(65535, 1, 2) + assert uid.get_int(1, 2) == 65535 + +# checks __int__ method +def test_int_conversion(): + uid = AugurUUID() + uid.set_byte(15, 1) + assert int(uid) == 1 + +def test_get_byte_invalid_index(): + uid = AugurUUID() + with pytest.raises(IndexError): + uid.get_byte(20) + # checks that set_byte correctly rejects a value that is too large def test_set_byte_raises_on_invalid_value(): uid = AugurUUID() @@ -55,6 +106,11 @@ def test_set_byte_raises_on_out_of_range_index(): with pytest.raises(IndexError): uid.set_byte(16, 1) # index 16 is out of bounds +def test_set_byte_raises_on_non_integer(): + uid = AugurUUID() + with pytest.raises(ValueError): + uid.set_byte(0, "hello") + # checks that 2 UUIDs with the same values are considered equal. def test_equality(): uid1 = GithubUUID() @@ -71,16 +127,56 @@ def test_inequality(): uid2["user"] = 200 assert uid1 != uid2 -# checks that writeint correctly rejects a number -def test_write_int_raises_on_overflow(): - uid = GithubUUID() - with pytest.raises(ValueError): - uid["user"] = 99999999999 # too big for 4 bytes - # checks that the same user produces different user IDs across platforms def test_github_and_gitlab_different_for_same_user(): github_uid = GithubUUID() gitlab_uid = GitlabUUID() github_uid["user"] = 100 gitlab_uid["user"] = 100 - assert github_uid != gitlab_uid \ No newline at end of file + assert github_uid != gitlab_uid + +# checks the maximum value that fits into user field +def test_user_field_max_value(): + uid = GithubUUID() + uid["user"] = 4294967295 + assert uid["user"] == 4294967295 + +# checks the minimum boundary +def test_user_field_zero_value(): + uid = GithubUUID() + uid["user"] = 0 + assert uid["user"] == 0 + +def test_len_returns_16(): + uid = AugurUUID() + assert len(uid) == 16 + +def test_dict_representation(): + uid = GithubUUID() + uid["user"] = 10 + + result = uid.__dict__() + + assert result["platform"] == 1 + assert result["user"] == 10 + +def test_string_representation(): + uid = GithubUUID() + uid["user"] = 10 + + result = str(uid) + + assert "user" in result + assert "platform" in result + +def test_iteration_over_bytes(): + uid = AugurUUID() + bytes_list = list(uid) + + assert len(bytes_list) == 16 + +def test_setting_same_field_twice(): + uid = GithubUUID() + uid["user"] = 42 + uid["user"] = 100 # overwrite with different value + assert uid["user"] == 100 \ No newline at end of file From 29ce9588e76e79c67ed82b20b869af4243ed2e73 Mon Sep 17 00:00:00 2001 From: Inengiye Emmanuel Date: Tue, 17 Mar 2026 18:09:09 +0100 Subject: [PATCH 04/15] Remove redundant UUID tests Signed-off-by: Inengiye Emmanuel --- .../test_util/test_augur_uuid.py | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py b/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py index 2f81a8f84..a377468e4 100644 --- a/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py +++ b/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py @@ -135,22 +135,6 @@ def test_github_and_gitlab_different_for_same_user(): gitlab_uid["user"] = 100 assert github_uid != gitlab_uid -# checks the maximum value that fits into user field -def test_user_field_max_value(): - uid = GithubUUID() - uid["user"] = 4294967295 - assert uid["user"] == 4294967295 - -# checks the minimum boundary -def test_user_field_zero_value(): - uid = GithubUUID() - uid["user"] = 0 - assert uid["user"] == 0 - -def test_len_returns_16(): - uid = AugurUUID() - assert len(uid) == 16 - def test_dict_representation(): uid = GithubUUID() uid["user"] = 10 @@ -169,12 +153,6 @@ def test_string_representation(): assert "user" in result assert "platform" in result -def test_iteration_over_bytes(): - uid = AugurUUID() - bytes_list = list(uid) - - assert len(bytes_list) == 16 - def test_setting_same_field_twice(): uid = GithubUUID() uid["user"] = 42 From e87983d4d57bec5df43ee643ce9e74dfa405ce1c Mon Sep 17 00:00:00 2001 From: Adrian Edwards Date: Thu, 7 May 2026 09:42:32 -0400 Subject: [PATCH 05/15] add some basic unit tests to assert that the URL generation works as intended These pass but require that the collectoss/tasks/github/__init__.py file be commented out first before they will run Co-Authored-By: Cursor Signed-off-by: Adrian Edwards --- tests/test_classes/test_github_data_access.py | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/test_classes/test_github_data_access.py diff --git a/tests/test_classes/test_github_data_access.py b/tests/test_classes/test_github_data_access.py new file mode 100644 index 000000000..7a3064d8d --- /dev/null +++ b/tests/test_classes/test_github_data_access.py @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: MIT +import pytest +from unittest.mock import Mock, patch + +from collectoss.tasks.github.util.github_data_access import GithubDataAccess + + +@pytest.fixture +def mock_logger(): + return Mock() + + +@pytest.fixture +def mock_key_manager(): + return Mock() + + +@pytest.fixture +def gda(mock_key_manager, mock_logger): + with patch("collectoss.tasks.github.util.github_data_access.KeyClient"): + return GithubDataAccess(mock_key_manager, mock_logger) + + +class TestEndpointUrl: + + def test_basic_path(self, gda): + result = gda.endpoint_url("/users/MoralCode") + assert result == "https://api.github.com/users/MoralCode" + + def test_path_without_leading_slash(self, gda): + result = gda.endpoint_url("repos/owner/repo") + assert result == "https://api.github.com/repos/owner/repo" + + def test_with_single_param(self, gda): + result = gda.endpoint_url("/users/MoralCode", {"per_page": "100"}) + assert "per_page=100" in result + assert result.startswith("https://api.github.com/users/MoralCode") + + def test_with_multiple_params(self, gda): + result = gda.endpoint_url("/repos/owner/repo/pulls", {"per_page": "50", "state": "open"}) + assert "per_page=50" in result + assert "state=open" in result + assert result.startswith("https://api.github.com/repos/owner/repo/pulls") + + def test_none_params_produces_no_query_string(self, gda): + result = gda.endpoint_url("/users/MoralCode", None) + assert result == "https://api.github.com/users/MoralCode" + + def test_empty_params_produces_no_query_string(self, gda): + result = gda.endpoint_url("/users/MoralCode", {}) + assert result == "https://api.github.com/users/MoralCode" + + def test_path_with_existing_query_params(self, gda): + result = gda.endpoint_url("/search/repositories?q=python", {"per_page": "10"}) + assert "q=python" in result + assert "per_page=10" in result + assert result.startswith("https://api.github.com/search/repositories") From e6976be4ca786cbe60dc787a80c14a5d5cfbab82 Mon Sep 17 00:00:00 2001 From: Adrian Edwards Date: Fri, 8 May 2026 11:41:14 -0400 Subject: [PATCH 06/15] fix merge conflict error Signed-off-by: Adrian Edwards --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 25edd9a69..5c155b7d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -146,7 +146,7 @@ addopts = "-ra -s" testpaths = [ "tests/test_classes", "tests/test_application/test_cli/test_csv_utils.py", - "tests/test_tasks/test_task_utilities/test_util/test_worker_util.py" + "tests/test_tasks/test_task_utilities/test_util/test_worker_util.py", "tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py", # "tests/test_routes", # runs, but needs a fixture for connecting to the web interface of Augur # "tests/test_metrics", From c47b20b21592b5f79fcbee56e895aa470f0ebd1f Mon Sep 17 00:00:00 2001 From: Adrian Edwards Date: Thu, 7 May 2026 09:45:00 -0400 Subject: [PATCH 07/15] move task imports to the one place they're actually needed this prevents them from messing with unit testing stuff Signed-off-by: Adrian Edwards --- collectoss/tasks/github/__init__.py | 7 ------- collectoss/tasks/start_tasks.py | 8 +++++++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/collectoss/tasks/github/__init__.py b/collectoss/tasks/github/__init__.py index de3f37bd8..e69de29bb 100644 --- a/collectoss/tasks/github/__init__.py +++ b/collectoss/tasks/github/__init__.py @@ -1,7 +0,0 @@ -from collectoss.tasks.github.contributors import * -from collectoss.tasks.github.events import * -from collectoss.tasks.github.issues import * -from collectoss.tasks.github.messages import * -from collectoss.tasks.github.pull_requests.tasks import * -from collectoss.tasks.github.repo_info.tasks import * -from collectoss.tasks.github.releases.tasks import * diff --git a/collectoss/tasks/start_tasks.py b/collectoss/tasks/start_tasks.py index 644b6cbc4..8e130f926 100644 --- a/collectoss/tasks/start_tasks.py +++ b/collectoss/tasks/start_tasks.py @@ -7,7 +7,13 @@ import sqlalchemy as s -from collectoss.tasks.github import * +from collectoss.tasks.github.contributors import * +from collectoss.tasks.github.events import * +from collectoss.tasks.github.issues import * +from collectoss.tasks.github.messages import * +from collectoss.tasks.github.pull_requests.tasks import * +from collectoss.tasks.github.repo_info.tasks import * +from collectoss.tasks.github.releases.tasks import * if os.environ.get('AUGUR_DOCKER_DEPLOY') != "1": from collectoss.tasks.data_analysis import * from collectoss.tasks.github.detect_move.tasks import detect_github_repo_move_core, detect_github_repo_move_secondary From 309f8521411cd01094c778a5789999d923c32e96 Mon Sep 17 00:00:00 2001 From: Adrian Edwards Date: Fri, 8 May 2026 11:41:23 -0400 Subject: [PATCH 08/15] rename the class Signed-off-by: Adrian Edwards --- .../test_util/test_augur_uuid.py | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py b/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py index a377468e4..22d7703bb 100644 --- a/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py +++ b/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py @@ -1,12 +1,12 @@ import pytest import uuid -from augur.tasks.util.AugurUUID import AugurUUID, GithubUUID, GitlabUUID, UnresolvableUUID +from collectoss.tasks.util.ContributorUUID import ContributorUUID, GithubUUID, GitlabUUID, UnresolvableUUID -# AugurUUID tests +# ContributorUUID tests -# this checks whether a brand new AugurUUID object starts as 16 zero bytes +# this checks whether a brand new ContributorUUID object starts as 16 zero bytes def test_augur_uuid_initializes_with_16_zero_bytes(): - uid = AugurUUID() + uid = ContributorUUID() assert len(uid.bytes) == 16 assert all(b == 0 for b in uid.bytes) @@ -28,12 +28,12 @@ def test_github_uuid_set_user(): # tests platform_id edge cases def test_set_platform_id_raises_on_non_integer(): - uid = AugurUUID() + uid = ContributorUUID() with pytest.raises(ValueError): uid.set_platform_id("github") def test_set_platform_id_raises_on_overflow(): - uid = AugurUUID() + uid = ContributorUUID() with pytest.raises(ValueError): uid.set_platform_id(256) # too big for 1 byte @@ -56,13 +56,13 @@ def test_to_uuid_returns_valid_uuid(): # checks the start_byte is within range(0, 16) for set_bytes def test_set_bytes_raises_on_invalid_start_byte(): - uid = AugurUUID() + uid = ContributorUUID() with pytest.raises(ValueError): uid.set_bytes([1, 2, 3], 16) # checks that set_bytes correctly raises an error when you write more bytes that will fit in the UUID starting at a given position def test_set_bytes_raises_on_too_many_bytes(): - uid = AugurUUID() + uid = ContributorUUID() with pytest.raises(ValueError): uid.set_bytes([1] * 10, 10) @@ -79,35 +79,35 @@ def test_write_int_with_non_integer(): uid.write_int("abc", 1, 4) def test_write_int_and_get_int_roundtrip(): - uid = AugurUUID() + uid = ContributorUUID() uid.write_int(65535, 1, 2) assert uid.get_int(1, 2) == 65535 # checks __int__ method def test_int_conversion(): - uid = AugurUUID() + uid = ContributorUUID() uid.set_byte(15, 1) assert int(uid) == 1 def test_get_byte_invalid_index(): - uid = AugurUUID() + uid = ContributorUUID() with pytest.raises(IndexError): uid.get_byte(20) # checks that set_byte correctly rejects a value that is too large def test_set_byte_raises_on_invalid_value(): - uid = AugurUUID() + uid = ContributorUUID() with pytest.raises(ValueError): uid.set_byte(0, 256) # too big for one byte # checks that set_byte rejects an index that doesnt exist def test_set_byte_raises_on_out_of_range_index(): - uid = AugurUUID() + uid = ContributorUUID() with pytest.raises(IndexError): uid.set_byte(16, 1) # index 16 is out of bounds def test_set_byte_raises_on_non_integer(): - uid = AugurUUID() + uid = ContributorUUID() with pytest.raises(ValueError): uid.set_byte(0, "hello") From a63d96a0c8d72f286b1530ccae7120b6e7505e1b Mon Sep 17 00:00:00 2001 From: Adrian Edwards Date: Fri, 8 May 2026 11:25:33 -0400 Subject: [PATCH 09/15] fix remove database dependency from the worker util test Signed-off-by: Adrian Edwards --- pyproject.toml | 1 + .../test_task_utilities/test_util/test_worker_util.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6445d832e..85f11e3e6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -146,6 +146,7 @@ addopts = "-ra -s" testpaths = [ "tests/test_classes", "tests/test_application/test_cli/test_csv_utils.py", + "tests/test_tasks/test_task_utilities/test_util/test_worker_util.py" # "tests/test_routes", # runs, but needs a fixture for connecting to the web interface of CollectOSS # "tests/test_metrics", # "tests/test_tasks", diff --git a/tests/test_tasks/test_task_utilities/test_util/test_worker_util.py b/tests/test_tasks/test_task_utilities/test_util/test_worker_util.py index affd40248..da420a2ab 100644 --- a/tests/test_tasks/test_task_utilities/test_util/test_worker_util.py +++ b/tests/test_tasks/test_task_utilities/test_util/test_worker_util.py @@ -2,11 +2,11 @@ import pytest import sqlalchemy as s -from collectoss.tasks.util.worker_util import * +from collectoss.tasks.util.worker_util import remove_duplicates_by_uniques logger = logging.getLogger(__name__) -def test_remove_duplicates_by_uniques(test_db_engine): +def test_remove_duplicates_by_uniques(): data_1 = {"cntrb_login": "Bob", "gh_user_id": 4, "gh_login": "bob", "cntrb_id": "01003f7a-8500-0000-0000-000000000000"} data_2 = {"cntrb_login": "amazing", "gh_user_id": 1700, "gh_login": "hello", "cntrb_id": "01003f7a-8500-0000-0000-000123002000"} From ecfa0d754ce0a01d105e3a0c0ff3df31edb8eff8 Mon Sep 17 00:00:00 2001 From: Adrian Edwards Date: Tue, 19 May 2026 09:06:09 -0400 Subject: [PATCH 10/15] actually run all the configured tests in CI Signed-off-by: Adrian Edwards --- .github/workflows/functional_test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/functional_test.yml b/.github/workflows/functional_test.yml index eaa50adf3..5ec4dc2b9 100644 --- a/.github/workflows/functional_test.yml +++ b/.github/workflows/functional_test.yml @@ -27,5 +27,4 @@ jobs: - name: Run Tests run: | uv run --python ${{ matrix.env }} pytest \ - tests/test_classes \ --color=yes From bc66238059322a18b08d19a4df6dc74272fbac1f Mon Sep 17 00:00:00 2001 From: Adrian Edwards Date: Tue, 19 May 2026 09:14:09 -0400 Subject: [PATCH 11/15] rename duplicate test function Signed-off-by: Adrian Edwards --- .../test_paginators/test_github_paginator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tasks/test_task_utilities/test_paginators/test_github_paginator.py b/tests/test_tasks/test_task_utilities/test_paginators/test_github_paginator.py index a8ea375f3..ec0c27745 100644 --- a/tests/test_tasks/test_task_utilities/test_paginators/test_github_paginator.py +++ b/tests/test_tasks/test_task_utilities/test_paginators/test_github_paginator.py @@ -92,7 +92,7 @@ def test_github_paginator_len(key_auth): assert len_contributors_list == 0 -def test_github_paginator_get_item(key_auth): +def test_github_paginator_get_item_2(key_auth): owner = "chaoss" name = "whitepaper" From 5840b23a12ae25407b625549eb6e23159a63452f Mon Sep 17 00:00:00 2001 From: Adrian Edwards Date: Tue, 19 May 2026 09:59:50 -0400 Subject: [PATCH 12/15] refactor most of the JSONConfig store tests into a class Signed-off-by: Adrian Edwards --- tests/test_classes/test_config_stores.py | 236 ++++++++++++----------- 1 file changed, 119 insertions(+), 117 deletions(-) diff --git a/tests/test_classes/test_config_stores.py b/tests/test_classes/test_config_stores.py index 8c15fd020..13fb6119d 100644 --- a/tests/test_classes/test_config_stores.py +++ b/tests/test_classes/test_config_stores.py @@ -14,73 +14,125 @@ def mock_session(): return Mock() -def test_jsonconfig_readonly_flags(mock_logger): - cfg = JsonConfig({"A": {"x": 1}}, mock_logger) - assert cfg.writable is False - assert cfg.empty is False - - -def test_jsonconfig_empty_true_false(mock_logger): - assert JsonConfig({}, mock_logger).empty is True - assert JsonConfig({"A": {}}, mock_logger).empty is False - - -def test_jsonconfig_write_protection(mock_logger): - # JsonConfig should be not writeable by default, so we should be unable to change - # its values, even by abusing references - - data = {"Alpha": {"a": 1, "b": "str"}, "Beta": {}} - cfg = JsonConfig(data, mock_logger) - - # mutation via input - data["Alpha"]["a"] = 2 - - config_test = cfg.retrieve_dict() - assert config_test != data # the data in the config should not change - - # mutation via output - config_test["Alpha"]["a"] = 3 - - config_test = cfg.retrieve_dict() - assert config_test != data # the data in the config should not change - -def test_jsonconfig_retrieve_has_get(mock_logger): - data = {"Alpha": {"a": 1, "b": "str"}, "Beta": {}} - cfg = JsonConfig(data, mock_logger) - - # retrieve full dict - assert cfg.retrieve_dict() == data - - # has/get section - assert cfg.has_section("Alpha") is True - assert cfg.has_section("Missing") is False - assert cfg.get_section("Alpha") == {"a": 1, "b": "str"} - assert cfg.get_section("Missing") is None - - # has/get value - assert cfg.has_value("Alpha", "a") is True - assert cfg.has_value("Alpha", "missing") is False - assert cfg.has_value("Missing", "a") is False - assert cfg.get_value("Alpha", "a") == 1 - assert cfg.get_value("Alpha", "missing") is None - assert cfg.get_value("Missing", "a") is None - - -@pytest.mark.parametrize( - "callable_name, args, kwargs", - [ - ("load_dict", ({"X": {"y": 2}},), {"ignore_existing": False}), - ("clear", tuple(), {}), - ("remove_section", ("X",), {}), - ("create_section", ("X", {"y": 2}), {"ignore_existing": False}), - ("remove_value", ("X", "y"), {}), - ("add_value", ("X", "y", 2), {"ignore_existing": False}), - ], -) -def test_jsonconfig_mutations_raise_not_writable(mock_logger, callable_name, args, kwargs): - cfg = JsonConfig({"A": {"x": 1}}, mock_logger) - with pytest.raises(NotWriteableException): - getattr(cfg, callable_name)(*args, **kwargs) +class TestJSONConfig: + + def test_jsonconfig_readonly_flags(self, mock_logger): + cfg = JsonConfig({"A": {"x": 1}}, mock_logger) + assert cfg.writable is False + assert cfg.empty is False + + + def test_jsonconfig_empty_true_false(self, mock_logger): + assert JsonConfig({}, mock_logger).empty is True + assert JsonConfig({"A": {}}, mock_logger).empty is False + + + def test_jsonconfig_write_protection(self, mock_logger): + # JsonConfig should be not writeable by default, so we should be unable to change + # its values, even by abusing references + + data = {"Alpha": {"a": 1, "b": "str"}, "Beta": {}} + cfg = JsonConfig(data, mock_logger) + + # mutation via input + data["Alpha"]["a"] = 2 + + config_test = cfg.retrieve_dict() + assert config_test != data # the data in the config should not change + + # mutation via output + config_test["Alpha"]["a"] = 3 + + config_test = cfg.retrieve_dict() + assert config_test != data # the data in the config should not change + + def test_jsonconfig_retrieve_has_get(self, mock_logger): + data = {"Alpha": {"a": 1, "b": "str"}, "Beta": {}} + cfg = JsonConfig(data, mock_logger) + + # retrieve full dict + assert cfg.retrieve_dict() == data + + # has/get section + assert cfg.has_section("Alpha") is True + assert cfg.has_section("Missing") is False + assert cfg.get_section("Alpha") == {"a": 1, "b": "str"} + assert cfg.get_section("Missing") is None + + # has/get value + assert cfg.has_value("Alpha", "a") is True + assert cfg.has_value("Alpha", "missing") is False + assert cfg.has_value("Missing", "a") is False + assert cfg.get_value("Alpha", "a") == 1 + assert cfg.get_value("Alpha", "missing") is None + assert cfg.get_value("Missing", "a") is None + + + @pytest.mark.parametrize( + "callable_name, args, kwargs", + [ + ("load_dict", ({"X": {"y": 2}},), {"ignore_existing": False}), + ("clear", tuple(), {}), + ("remove_section", ("X",), {}), + ("create_section", ("X", {"y": 2}), {"ignore_existing": False}), + ("remove_value", ("X", "y"), {}), + ("add_value", ("X", "y", 2), {"ignore_existing": False}), + ], + ) + def test_jsonconfig_mutations_raise_not_writable(self, mock_logger, callable_name, args, kwargs): + cfg = JsonConfig({"A": {"x": 1}}, mock_logger) + with pytest.raises(NotWriteableException): + getattr(cfg, callable_name)(*args, **kwargs) + + + def test_fetching_real_defaults(self, mock_logger, mock_session): + cfg = SystemConfig(mock_logger, mock_session) + cfg.config_sources = [JsonConfig(default_config, mock_logger)] + + assert cfg.get_value("Redis", "cache_group") == 0 + + + def test_load_config_utilizes_hierarchy(self): + + default_dict = { + "Section1": {"alpha": 1, "beta": "x"}, + "Section2": {"gamma": False, "delta": 3.14}, + } + + override_dict = { + "Section1": {"beta": "y"}, + "Section2": {"Epsilon": True, "delta": 6.28}, + "Section3": {"hi": "there"} + } + + cfg = SystemConfig(None, None, [JsonConfig(default_dict, mock_logger), JsonConfig(override_dict, mock_logger)]) + + expected_dict = { + "Section1": {"alpha": 1, "beta": "y"}, + "Section2": {"gamma": False, "Epsilon": True, "delta": 6.28}, + "Section3": {"hi": "there"} # test that new sections are accounted for too + } + + assert cfg.load_config() == expected_dict + + + def test_get_section_incorporates_hierarchy(self): + + default_dict = { + "Section1": {"alpha": 1, "beta": "x"}, + "Section2": {"gamma": False, "delta": 3.14}, + } + + override_dict = { + "Section1": {"beta": "y"}, + "Section2": {"gamma": False, "delta": 3.14}, + } + + cfg = SystemConfig(None, None, [JsonConfig(default_dict, mock_logger), JsonConfig(override_dict, mock_logger)]) + + expected_dict = {"alpha": 1, "beta": "y"} + + assert cfg.get_section("Section1") == expected_dict def test_dict_to_config_table_happy_path(): @@ -122,53 +174,3 @@ def test_dict_to_config_table_happy_path(): assert rows == expected - -def test_fetching_real_defaults(mock_logger, mock_session): - cfg = SystemConfig(mock_logger, mock_session) - cfg.config_sources = [JsonConfig(default_config, mock_logger)] - - assert cfg.get_value("Redis", "cache_group") == 0 - - -def test_load_config_utilizes_hierarchy(): - - default_dict = { - "Section1": {"alpha": 1, "beta": "x"}, - "Section2": {"gamma": False, "delta": 3.14}, - } - - override_dict = { - "Section1": {"beta": "y"}, - "Section2": {"Epsilon": True, "delta": 6.28}, - "Section3": {"hi": "there"} - } - - cfg = SystemConfig(None, None, [JsonConfig(default_dict, mock_logger), JsonConfig(override_dict, mock_logger)]) - - expected_dict = { - "Section1": {"alpha": 1, "beta": "y"}, - "Section2": {"gamma": False, "Epsilon": True, "delta": 6.28}, - "Section3": {"hi": "there"} # test that new sections are accounted for too - } - - assert cfg.load_config() == expected_dict - - -def test_get_section_incorporates_hierarchy(): - - default_dict = { - "Section1": {"alpha": 1, "beta": "x"}, - "Section2": {"gamma": False, "delta": 3.14}, - } - - override_dict = { - "Section1": {"beta": "y"}, - "Section2": {"gamma": False, "delta": 3.14}, - } - - cfg = SystemConfig(None, None, [JsonConfig(default_dict, mock_logger), JsonConfig(override_dict, mock_logger)]) - - expected_dict = {"alpha": 1, "beta": "y"} - - assert cfg.get_section("Section1") == expected_dict - From 606024dee3f0804e49ae082d69456371ce6942ca Mon Sep 17 00:00:00 2001 From: Adrian Edwards Date: Tue, 19 May 2026 10:11:43 -0400 Subject: [PATCH 13/15] encapsulate contributor UUID into a class Signed-off-by: Adrian Edwards --- .../test_util/test_augur_uuid.py | 310 +++++++++--------- 1 file changed, 155 insertions(+), 155 deletions(-) diff --git a/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py b/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py index 22d7703bb..b1ea766e7 100644 --- a/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py +++ b/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py @@ -3,158 +3,158 @@ from collectoss.tasks.util.ContributorUUID import ContributorUUID, GithubUUID, GitlabUUID, UnresolvableUUID # ContributorUUID tests - -# this checks whether a brand new ContributorUUID object starts as 16 zero bytes -def test_augur_uuid_initializes_with_16_zero_bytes(): - uid = ContributorUUID() - assert len(uid.bytes) == 16 - assert all(b == 0 for b in uid.bytes) - -# checks that githubUUID sets its platform number to 1 -def test_github_uuid_platform_is_1(): - uid = GithubUUID() - assert uid["platform"] == 1 - -# checks that gitlabUUID sets its platform number to 2 -def test_gitlab_uuid_platform_is_2(): - uid = GitlabUUID() - assert uid["platform"] == 2 - -# checks the that you can store a value in the user field -def test_github_uuid_set_user(): - uid = GithubUUID() - uid["user"] = 12345 - assert uid["user"] == 12345 - -# tests platform_id edge cases -def test_set_platform_id_raises_on_non_integer(): - uid = ContributorUUID() - with pytest.raises(ValueError): - uid.set_platform_id("github") - -def test_set_platform_id_raises_on_overflow(): - uid = ContributorUUID() - with pytest.raises(ValueError): - uid.set_platform_id(256) # too big for 1 byte - -# checks that writing to one field doesnt accidentally overwrite bytes belonging to another field -def test_fields_dont_overlap(): - uid = GithubUUID() - - uid["user"] = 12345 - uid["repo"] = 99999 - - assert uid["user"] == 12345 - assert uid["repo"] == 99999 - -# checks that to_UUID returs the uuid.UUID object -def test_to_uuid_returns_valid_uuid(): - uid = GithubUUID() - uid["user"] = 15 - result = uid.to_UUID() - assert isinstance(result, uuid.UUID) - -# checks the start_byte is within range(0, 16) for set_bytes -def test_set_bytes_raises_on_invalid_start_byte(): - uid = ContributorUUID() - with pytest.raises(ValueError): - uid.set_bytes([1, 2, 3], 16) - -# checks that set_bytes correctly raises an error when you write more bytes that will fit in the UUID starting at a given position -def test_set_bytes_raises_on_too_many_bytes(): - uid = ContributorUUID() - with pytest.raises(ValueError): - uid.set_bytes([1] * 10, 10) - -# checks that writeint correctly rejects a number -def test_write_int_raises_on_overflow(): - uid = GithubUUID() - with pytest.raises(ValueError): - uid["user"] = 99999999999 # too big for 4 bytes - -def test_write_int_with_non_integer(): - uid = GithubUUID() - - with pytest.raises(ValueError): - uid.write_int("abc", 1, 4) - -def test_write_int_and_get_int_roundtrip(): - uid = ContributorUUID() - uid.write_int(65535, 1, 2) - assert uid.get_int(1, 2) == 65535 - -# checks __int__ method -def test_int_conversion(): - uid = ContributorUUID() - uid.set_byte(15, 1) - assert int(uid) == 1 - -def test_get_byte_invalid_index(): - uid = ContributorUUID() - with pytest.raises(IndexError): - uid.get_byte(20) - -# checks that set_byte correctly rejects a value that is too large -def test_set_byte_raises_on_invalid_value(): - uid = ContributorUUID() - with pytest.raises(ValueError): - uid.set_byte(0, 256) # too big for one byte - -# checks that set_byte rejects an index that doesnt exist -def test_set_byte_raises_on_out_of_range_index(): - uid = ContributorUUID() - with pytest.raises(IndexError): - uid.set_byte(16, 1) # index 16 is out of bounds - -def test_set_byte_raises_on_non_integer(): - uid = ContributorUUID() - with pytest.raises(ValueError): - uid.set_byte(0, "hello") - -# checks that 2 UUIDs with the same values are considered equal. -def test_equality(): - uid1 = GithubUUID() - uid2 = GithubUUID() - uid1["user"] = 100 - uid2["user"] = 100 - assert uid1 == uid2 - -# checks that 2 UUIDs with different values are not equal -def test_inequality(): - uid1 = GithubUUID() - uid2 = GithubUUID() - uid1["user"] = 100 - uid2["user"] = 200 - assert uid1 != uid2 - -# checks that the same user produces different user IDs across platforms -def test_github_and_gitlab_different_for_same_user(): - github_uid = GithubUUID() - gitlab_uid = GitlabUUID() - github_uid["user"] = 100 - gitlab_uid["user"] = 100 - assert github_uid != gitlab_uid - -def test_dict_representation(): - uid = GithubUUID() - uid["user"] = 10 - - result = uid.__dict__() - - assert result["platform"] == 1 - assert result["user"] == 10 - -def test_string_representation(): - uid = GithubUUID() - uid["user"] = 10 - - result = str(uid) - - assert "user" in result - assert "platform" in result - -def test_setting_same_field_twice(): - uid = GithubUUID() - uid["user"] = 42 - uid["user"] = 100 # overwrite with different value - assert uid["user"] == 100 \ No newline at end of file +class TestContributorUUID: + # this checks whether a brand new ContributorUUID object starts as 16 zero bytes + def test_augur_uuid_initializes_with_16_zero_bytes(self): + uid = ContributorUUID() + assert len(uid.bytes) == 16 + assert all(b == 0 for b in uid.bytes) + + # checks that githubUUID sets its platform number to 1 + def test_github_uuid_platform_is_1(self): + uid = GithubUUID() + assert uid["platform"] == 1 + + # checks that gitlabUUID sets its platform number to 2 + def test_gitlab_uuid_platform_is_2(self): + uid = GitlabUUID() + assert uid["platform"] == 2 + + # checks the that you can store a value in the user field + def test_github_uuid_set_user(self): + uid = GithubUUID() + uid["user"] = 12345 + assert uid["user"] == 12345 + + # tests platform_id edge cases + def test_set_platform_id_raises_on_non_integer(self): + uid = ContributorUUID() + with pytest.raises(ValueError): + uid.set_platform_id("github") + + def test_set_platform_id_raises_on_overflow(self): + uid = ContributorUUID() + with pytest.raises(ValueError): + uid.set_platform_id(256) # too big for 1 byte + + # checks that writing to one field doesnt accidentally overwrite bytes belonging to another field + def test_fields_dont_overlap(self): + uid = GithubUUID() + + uid["user"] = 12345 + uid["repo"] = 99999 + + assert uid["user"] == 12345 + assert uid["repo"] == 99999 + + # checks that to_UUID returs the uuid.UUID object + def test_to_uuid_returns_valid_uuid(self): + uid = GithubUUID() + uid["user"] = 15 + result = uid.to_UUID() + assert isinstance(result, uuid.UUID) + + # checks the start_byte is within range(0, 16) for set_bytes + def test_set_bytes_raises_on_invalid_start_byte(self): + uid = ContributorUUID() + with pytest.raises(ValueError): + uid.set_bytes([1, 2, 3], 16) + + # checks that set_bytes correctly raises an error when you write more bytes that will fit in the UUID starting at a given position + def test_set_bytes_raises_on_too_many_bytes(self): + uid = ContributorUUID() + with pytest.raises(ValueError): + uid.set_bytes([1] * 10, 10) + + # checks that writeint correctly rejects a number + def test_write_int_raises_on_overflow(self): + uid = GithubUUID() + with pytest.raises(ValueError): + uid["user"] = 99999999999 # too big for 4 bytes + + def test_write_int_with_non_integer(self): + uid = GithubUUID() + + with pytest.raises(ValueError): + uid.write_int("abc", 1, 4) + + def test_write_int_and_get_int_roundtrip(self): + uid = ContributorUUID() + uid.write_int(65535, 1, 2) + assert uid.get_int(1, 2) == 65535 + + # checks __int__ method + def test_int_conversion(self): + uid = ContributorUUID() + uid.set_byte(15, 1) + assert int(uid) == 1 + + def test_get_byte_invalid_index(self): + uid = ContributorUUID() + with pytest.raises(IndexError): + uid.get_byte(20) + + # checks that set_byte correctly rejects a value that is too large + def test_set_byte_raises_on_invalid_value(self): + uid = ContributorUUID() + with pytest.raises(ValueError): + uid.set_byte(0, 256) # too big for one byte + + # checks that set_byte rejects an index that doesnt exist + def test_set_byte_raises_on_out_of_range_index(self): + uid = ContributorUUID() + with pytest.raises(IndexError): + uid.set_byte(16, 1) # index 16 is out of bounds + + def test_set_byte_raises_on_non_integer(self): + uid = ContributorUUID() + with pytest.raises(ValueError): + uid.set_byte(0, "hello") + + # checks that 2 UUIDs with the same values are considered equal. + def test_equality(self): + uid1 = GithubUUID() + uid2 = GithubUUID() + uid1["user"] = 100 + uid2["user"] = 100 + assert uid1 == uid2 + + # checks that 2 UUIDs with different values are not equal + def test_inequality(self): + uid1 = GithubUUID() + uid2 = GithubUUID() + uid1["user"] = 100 + uid2["user"] = 200 + assert uid1 != uid2 + + # checks that the same user produces different user IDs across platforms + def test_github_and_gitlab_different_for_same_user(self): + github_uid = GithubUUID() + gitlab_uid = GitlabUUID() + github_uid["user"] = 100 + gitlab_uid["user"] = 100 + assert github_uid != gitlab_uid + + def test_dict_representation(self): + uid = GithubUUID() + uid["user"] = 10 + + result = uid.__dict__() + + assert result["platform"] == 1 + assert result["user"] == 10 + + def test_string_representation(self): + uid = GithubUUID() + uid["user"] = 10 + + result = str(uid) + + assert "user" in result + assert "platform" in result + + def test_setting_same_field_twice(self): + uid = GithubUUID() + uid["user"] = 42 + uid["user"] = 100 # overwrite with different value + assert uid["user"] == 100 \ No newline at end of file From 9199b85da7c6c39ed06a10ad38342c572bdd429b Mon Sep 17 00:00:00 2001 From: Adrian Edwards Date: Tue, 19 May 2026 10:09:02 -0400 Subject: [PATCH 14/15] rename unit test file Signed-off-by: Adrian Edwards --- pyproject.toml | 2 +- .../test_util/{test_augur_uuid.py => test_contributor_uuid.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/test_tasks/test_task_utilities/test_util/{test_augur_uuid.py => test_contributor_uuid.py} (100%) diff --git a/pyproject.toml b/pyproject.toml index 5c155b7d7..ebe2b0043 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -147,7 +147,7 @@ testpaths = [ "tests/test_classes", "tests/test_application/test_cli/test_csv_utils.py", "tests/test_tasks/test_task_utilities/test_util/test_worker_util.py", - "tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py", + "tests/test_tasks/test_task_utilities/test_util/test_contributor_uuid.py", # "tests/test_routes", # runs, but needs a fixture for connecting to the web interface of Augur # "tests/test_metrics", # "tests/test_tasks", diff --git a/tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py b/tests/test_tasks/test_task_utilities/test_util/test_contributor_uuid.py similarity index 100% rename from tests/test_tasks/test_task_utilities/test_util/test_augur_uuid.py rename to tests/test_tasks/test_task_utilities/test_util/test_contributor_uuid.py From 1c23358d37ac25f3ce1186cb9d24ac3ab16dfe7a Mon Sep 17 00:00:00 2001 From: Adrian Edwards Date: Tue, 19 May 2026 10:04:37 -0400 Subject: [PATCH 15/15] configure and apply test markers to separate unit and integration tests Signed-off-by: Adrian Edwards --- pyproject.toml | 5 +++++ tests/test_application/test_cli/test_csv_utils.py | 12 +++++++----- tests/test_classes/test_config_stores.py | 1 + tests/test_classes/test_github_data_access.py | 2 +- .../test_util/test_contributor_uuid.py | 1 + .../test_util/test_worker_util.py | 1 + 6 files changed, 16 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ebe2b0043..d14c871f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -156,6 +156,11 @@ testpaths = [ # "tests/test_workers/worker_persistence/", # "tests/test_routes/runner.py" ] +markers = [ + "unit: pure logic tests with no external dependencies", + "integration: tests requiring a database, Redis, or network access", +] + [tool.mypy] files = ['collectoss/application/db/*.py'] diff --git a/tests/test_application/test_cli/test_csv_utils.py b/tests/test_application/test_cli/test_csv_utils.py index 395ed0936..d15a7f04b 100644 --- a/tests/test_application/test_cli/test_csv_utils.py +++ b/tests/test_application/test_cli/test_csv_utils.py @@ -14,7 +14,7 @@ MAX_FILE_SIZE_BYTES, ) - +@pytest.mark.unit class TestValidateGitUrl: """Tests for validate_git_url function""" @@ -40,7 +40,7 @@ def test_whitespace_handling(self): """Test that whitespace is properly stripped""" assert validate_git_url(" https://github.com/chaoss/collectoss ") - +@pytest.mark.unit class TestValidatePositiveInt: """Tests for validate_positive_int function""" @@ -71,7 +71,7 @@ def test_whitespace_handling(self): """Test that whitespace is properly stripped""" assert validate_positive_int(" 42 ") - +@pytest.mark.unit class TestDetectColumnOrder: """Tests for detect_column_order function""" @@ -153,7 +153,7 @@ def test_no_match_found_raises_error(self): with pytest.raises(ValueError, match="Could not detect column"): detect_column_order(sample_rows, validators) - +@pytest.mark.unit class TestProcessCsv: """Tests for process_csv function""" @@ -252,7 +252,7 @@ def test_whitespace_in_values(self, tmp_path): result = process_csv(str(csv_file), validators) assert result[0] == {"repo_url": "https://github.com/chaoss/collectoss", "repo_group_id": "10"} - +@pytest.mark.unit class TestProcessRepoCsv: """Tests for process_repo_csv function""" @@ -275,6 +275,7 @@ def test_process_repo_csv_without_headers(self, tmp_path): assert len(result) == 2 +@pytest.mark.unit class TestProcessRepoGroupCsv: """Tests for process_repo_group_csv function""" @@ -310,6 +311,7 @@ def test_empty_group_name_invalid(self, tmp_path): assert len(result) >= 1 +@pytest.mark.unit class TestEdgeCases: """Tests for edge cases and error conditions""" diff --git a/tests/test_classes/test_config_stores.py b/tests/test_classes/test_config_stores.py index 13fb6119d..cf23f646f 100644 --- a/tests/test_classes/test_config_stores.py +++ b/tests/test_classes/test_config_stores.py @@ -135,6 +135,7 @@ def test_get_section_incorporates_hierarchy(self): assert cfg.get_section("Section1") == expected_dict +@pytest.mark.unit def test_dict_to_config_table_happy_path(): input_dict = { "Section1": {"alpha": 1, "beta": "x"}, diff --git a/tests/test_classes/test_github_data_access.py b/tests/test_classes/test_github_data_access.py index 7a3064d8d..3ebd4db79 100644 --- a/tests/test_classes/test_github_data_access.py +++ b/tests/test_classes/test_github_data_access.py @@ -20,7 +20,7 @@ def gda(mock_key_manager, mock_logger): with patch("collectoss.tasks.github.util.github_data_access.KeyClient"): return GithubDataAccess(mock_key_manager, mock_logger) - +@pytest.mark.unit class TestEndpointUrl: def test_basic_path(self, gda): diff --git a/tests/test_tasks/test_task_utilities/test_util/test_contributor_uuid.py b/tests/test_tasks/test_task_utilities/test_util/test_contributor_uuid.py index b1ea766e7..40f5cdc27 100644 --- a/tests/test_tasks/test_task_utilities/test_util/test_contributor_uuid.py +++ b/tests/test_tasks/test_task_utilities/test_util/test_contributor_uuid.py @@ -3,6 +3,7 @@ from collectoss.tasks.util.ContributorUUID import ContributorUUID, GithubUUID, GitlabUUID, UnresolvableUUID # ContributorUUID tests +@pytest.mark.unit class TestContributorUUID: # this checks whether a brand new ContributorUUID object starts as 16 zero bytes def test_augur_uuid_initializes_with_16_zero_bytes(self): diff --git a/tests/test_tasks/test_task_utilities/test_util/test_worker_util.py b/tests/test_tasks/test_task_utilities/test_util/test_worker_util.py index da420a2ab..410c1ef70 100644 --- a/tests/test_tasks/test_task_utilities/test_util/test_worker_util.py +++ b/tests/test_tasks/test_task_utilities/test_util/test_worker_util.py @@ -6,6 +6,7 @@ logger = logging.getLogger(__name__) +@pytest.mark.unit def test_remove_duplicates_by_uniques(): data_1 = {"cntrb_login": "Bob", "gh_user_id": 4, "gh_login": "bob", "cntrb_id": "01003f7a-8500-0000-0000-000000000000"}