chore: enhance API test coverage reporting and update dependencies

This commit is contained in:
swve 2025-07-27 20:12:23 +02:00
parent 7b220e8883
commit fa3a3be151
9 changed files with 48 additions and 46 deletions

View file

@ -42,6 +42,13 @@ jobs:
- name: Run security tests with coverage
run: |
cd apps/api
uv run pytest src/tests/security/ --cov=src.security --cov-report=xml --cov-report=term-missing
uv run pytest src/tests/security/ --cov=src.security --cov-report=html --cov-report=term-missing
env:
TESTING: "true"
- name: Upload coverage report to GitHub
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: apps/api/htmlcov/
retention-days: 30

View file

@ -21,6 +21,7 @@ dependencies = [
"psycopg2-binary>=2.9.9",
"pydantic[email]>=1.8.0,<2.0.0",
"pytest>=8.2.2",
"pytest-cov>=4.1.0",
"python-dotenv>=1.0.0",
"python-multipart>=0.0.9",
"pyyaml>=6.0.1",

View file

@ -11,7 +11,6 @@ from src.security.auth import (
Token,
TokenData,
Settings,
get_config,
)
from src.db.users import User, AnonymousUser, PublicUser
from datetime import datetime, timedelta, timezone

View file

@ -1,12 +1,11 @@
import pytest
from unittest.mock import Mock, patch, MagicMock
from unittest.mock import Mock, patch
from fastapi import HTTPException
from sqlmodel import Session, select
from sqlmodel import Session
from src.security.features_utils.usage import (
check_limits_with_usage,
increase_feature_usage,
decrease_feature_usage,
FeatureSet,
)
from src.db.organization_config import OrganizationConfig

View file

@ -1,7 +1,7 @@
import pytest
from unittest.mock import Mock, AsyncMock, patch
from fastapi import HTTPException, Request
from sqlmodel import Session, select
from sqlmodel import Session
from src.security.rbac.rbac import (
authorization_verify_if_element_is_public,
authorization_verify_if_user_is_author,
@ -14,7 +14,6 @@ from src.db.courses.courses import Course
from src.db.collections import Collection
from src.db.resource_authors import ResourceAuthor, ResourceAuthorshipEnum, ResourceAuthorshipStatusEnum
from src.db.roles import Role
from src.db.user_organizations import UserOrganization
class TestRBAC:

View file

@ -1,5 +1,4 @@
import pytest
from unittest.mock import AsyncMock, patch
from fastapi import HTTPException
from src.security.rbac.utils import (
check_element_type,

View file

@ -1,4 +1,3 @@
import pytest
from src.security.security import (
security_hash_password,
security_verify_password,

View file

@ -10,7 +10,6 @@ of the security functionality including:
- Authorization utilities
"""
import pytest
from src.tests.security.test_security import TestSecurity
from src.tests.security.test_auth import TestAuth
from src.tests.security.test_rbac import TestRBAC
@ -24,49 +23,14 @@ class TestSecurityComprehensive:
def test_security_module_imports(self):
"""Test that all security modules can be imported successfully"""
# Test core security imports
from src.security.security import (
security_hash_password,
security_verify_password,
ACCESS_TOKEN_EXPIRE_MINUTES,
SECRET_KEY,
ALGORITHM,
)
# Test auth imports
from src.security.auth import (
authenticate_user,
create_access_token,
get_current_user,
non_public_endpoint,
Token,
TokenData,
Settings,
)
# Test RBAC imports
from src.security.rbac.rbac import (
authorization_verify_if_element_is_public,
authorization_verify_if_user_is_author,
authorization_verify_based_on_roles,
authorization_verify_based_on_org_admin_status,
authorization_verify_based_on_roles_and_authorship,
authorization_verify_if_user_is_anon,
)
# Test RBAC utils imports
from src.security.rbac.utils import (
check_element_type,
get_singular_form_of_element,
get_id_identifier_of_element,
)
# Test features utils imports
from src.security.features_utils.usage import (
check_limits_with_usage,
increase_feature_usage,
decrease_feature_usage,
FeatureSet,
)
# Verify all imports succeeded
assert True
@ -83,7 +47,6 @@ class TestSecurityComprehensive:
def test_feature_set_definition(self):
"""Test that FeatureSet includes all expected features"""
from src.security.features_utils.usage import FeatureSet
expected_features = [
"ai", "analytics", "api", "assignments", "collaboration",

36
apps/api/uv.lock generated
View file

@ -339,6 +339,26 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", size = 46018 },
]
[[package]]
name = "coverage"
version = "7.10.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/87/0e/66dbd4c6a7f0758a8d18044c048779ba21fb94856e1edcf764bd5403e710/coverage-7.10.1.tar.gz", hash = "sha256:ae2b4856f29ddfe827106794f3589949a57da6f0d38ab01e24ec35107979ba57", size = 819938 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a5/3f/b051feeb292400bd22d071fdf933b3ad389a8cef5c80c7866ed0c7414b9e/coverage-7.10.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6b7dc7f0a75a7eaa4584e5843c873c561b12602439d2351ee28c7478186c4da4", size = 214934 },
{ url = "https://files.pythonhosted.org/packages/f8/e4/a61b27d5c4c2d185bdfb0bfe9d15ab4ac4f0073032665544507429ae60eb/coverage-7.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:607f82389f0ecafc565813aa201a5cade04f897603750028dd660fb01797265e", size = 215173 },
{ url = "https://files.pythonhosted.org/packages/8a/01/40a6ee05b60d02d0bc53742ad4966e39dccd450aafb48c535a64390a3552/coverage-7.10.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f7da31a1ba31f1c1d4d5044b7c5813878adae1f3af8f4052d679cc493c7328f4", size = 246190 },
{ url = "https://files.pythonhosted.org/packages/11/ef/a28d64d702eb583c377255047281305dc5a5cfbfb0ee36e721f78255adb6/coverage-7.10.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:51fe93f3fe4f5d8483d51072fddc65e717a175490804e1942c975a68e04bf97a", size = 248618 },
{ url = "https://files.pythonhosted.org/packages/6a/ad/73d018bb0c8317725370c79d69b5c6e0257df84a3b9b781bda27a438a3be/coverage-7.10.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3e59d00830da411a1feef6ac828b90bbf74c9b6a8e87b8ca37964925bba76dbe", size = 250081 },
{ url = "https://files.pythonhosted.org/packages/2d/dd/496adfbbb4503ebca5d5b2de8bed5ec00c0a76558ffc5b834fd404166bc9/coverage-7.10.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:924563481c27941229cb4e16eefacc35da28563e80791b3ddc5597b062a5c386", size = 247990 },
{ url = "https://files.pythonhosted.org/packages/18/3c/a9331a7982facfac0d98a4a87b36ae666fe4257d0f00961a3a9ef73e015d/coverage-7.10.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ca79146ee421b259f8131f153102220b84d1a5e6fb9c8aed13b3badfd1796de6", size = 246191 },
{ url = "https://files.pythonhosted.org/packages/62/0c/75345895013b83f7afe92ec595e15a9a525ede17491677ceebb2ba5c3d85/coverage-7.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2b225a06d227f23f386fdc0eab471506d9e644be699424814acc7d114595495f", size = 247400 },
{ url = "https://files.pythonhosted.org/packages/e2/a9/98b268cfc5619ef9df1d5d34fee408ecb1542d9fd43d467e5c2f28668cd4/coverage-7.10.1-cp312-cp312-win32.whl", hash = "sha256:5ba9a8770effec5baaaab1567be916c87d8eea0c9ad11253722d86874d885eca", size = 217338 },
{ url = "https://files.pythonhosted.org/packages/fe/31/22a5440e4d1451f253c5cd69fdcead65e92ef08cd4ec237b8756dc0b20a7/coverage-7.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:9eb245a8d8dd0ad73b4062135a251ec55086fbc2c42e0eb9725a9b553fba18a3", size = 218125 },
{ url = "https://files.pythonhosted.org/packages/d6/2b/40d9f0ce7ee839f08a43c5bfc9d05cec28aaa7c9785837247f96cbe490b9/coverage-7.10.1-cp312-cp312-win_arm64.whl", hash = "sha256:7718060dd4434cc719803a5e526838a5d66e4efa5dc46d2b25c21965a9c6fcc4", size = 216523 },
{ url = "https://files.pythonhosted.org/packages/0f/64/922899cff2c0fd3496be83fa8b81230f5a8d82a2ad30f98370b133c2c83b/coverage-7.10.1-py3-none-any.whl", hash = "sha256:fa2a258aa6bf188eb9a8948f7102a83da7c430a0dce918dbd8b60ef8fcb772d7", size = 206597 },
]
[[package]]
name = "dataclasses-json"
version = "0.6.7"
@ -1033,6 +1053,7 @@ dependencies = [
{ name = "pydantic", extra = ["email"] },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "pytest-cov" },
{ name = "python-dotenv" },
{ name = "python-jose" },
{ name = "python-multipart" },
@ -1070,6 +1091,7 @@ requires-dist = [
{ name = "pydantic", extras = ["email"], specifier = ">=1.8.0,<2.0.0" },
{ name = "pytest", specifier = ">=8.2.2" },
{ name = "pytest-asyncio", specifier = ">=1.1.0" },
{ name = "pytest-cov", specifier = ">=4.1.0" },
{ name = "python-dotenv", specifier = ">=1.0.0" },
{ name = "python-jose", specifier = ">=3.3.0" },
{ name = "python-multipart", specifier = ">=0.0.9" },
@ -1728,6 +1750,20 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c7/9d/bf86eddabf8c6c9cb1ea9a869d6873b46f105a5d292d3a6f7071f5b07935/pytest_asyncio-1.1.0-py3-none-any.whl", hash = "sha256:5fe2d69607b0bd75c656d1211f969cadba035030156745ee09e7d71740e58ecf", size = 15157 },
]
[[package]]
name = "pytest-cov"
version = "6.2.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "coverage" },
{ name = "pluggy" },
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/18/99/668cade231f434aaa59bbfbf49469068d2ddd945000621d3d165d2e7dd7b/pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2", size = 69432 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/bc/16/4ea354101abb1287856baa4af2732be351c7bee728065aed451b678153fd/pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5", size = 24644 },
]
[[package]]
name = "python-dateutil"
version = "2.9.0.post0"