mirror of
https://github.com/fhswf/aki_prj23_transparenzregister.git
synced 2025-06-22 07:03:56 +02:00
test: Adding unit tests
This commit is contained in:
7828
poetry.lock
generated
7828
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
223
pyproject.toml
223
pyproject.toml
@ -1,111 +1,112 @@
|
|||||||
[build-system]
|
[build-system]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "poetry.core.masonry.api"
|
||||||
requires = ["poetry-core"]
|
requires = ["poetry-core"]
|
||||||
|
|
||||||
[tookl.mypy]
|
[tookl.mypy]
|
||||||
disallow_untyped_defs = true
|
disallow_untyped_defs = true
|
||||||
follow_imports = "silent"
|
follow_imports = "silent"
|
||||||
python_version = "3.11"
|
python_version = "3.11"
|
||||||
warn_redudant_casts = true
|
warn_redudant_casts = true
|
||||||
warn_unused_ignores = true
|
warn_unused_ignores = true
|
||||||
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
target-version = ["py311"]
|
target-version = ["py311"]
|
||||||
|
|
||||||
[tool.coverage.run]
|
[tool.coverage.run]
|
||||||
branch = true
|
branch = true
|
||||||
dynamic_context = "test_function"
|
dynamic_context = "test_function"
|
||||||
relative_files = true
|
relative_files = true
|
||||||
source = ["src"]
|
source = ["src"]
|
||||||
|
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
authors = ["AKI Projektgruppe 23"]
|
authors = ["AKI Projektgruppe 23"]
|
||||||
description = "A project analysing the german transparenzregister and other data sources to find shared business interests and shared personal and other links for lots of companies."
|
description = "A project analysing the german transparenzregister and other data sources to find shared business interests and shared personal and other links for lots of companies."
|
||||||
name = "aki-prj23-transparenzregister"
|
name = "aki-prj23-transparenzregister"
|
||||||
packages = [{include = "aki_prj23_transparenzregister", from = "src"}]
|
packages = [{include = "aki_prj23_transparenzregister", from = "src"}]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
loguru = "^0.7.0"
|
loguru = "^0.7.0"
|
||||||
matplotlib = "^3.7.1"
|
matplotlib = "^3.7.1"
|
||||||
plotly = "^5.14.1"
|
plotly = "^5.14.1"
|
||||||
python = "^3.11"
|
pymongo = "^4.4.1"
|
||||||
seaborn = "^0.12.2"
|
python = "^3.11"
|
||||||
selenium = "^4.10.0"
|
seaborn = "^0.12.2"
|
||||||
tqdm = "^4.65.0"
|
selenium = "^4.10.0"
|
||||||
|
tqdm = "^4.65.0"
|
||||||
[tool.poetry.group.develop.dependencies]
|
|
||||||
black = {extras = ["jupyter"], version = "^23.3.0"}
|
[tool.poetry.group.develop.dependencies]
|
||||||
jupyterlab = "^4.0.0"
|
black = {extras = ["jupyter"], version = "^23.3.0"}
|
||||||
nbconvert = "^7.4.0"
|
jupyterlab = "^4.0.0"
|
||||||
pre-commit = "^3.3.2"
|
nbconvert = "^7.4.0"
|
||||||
rise = "^5.7.1"
|
pre-commit = "^3.3.2"
|
||||||
|
rise = "^5.7.1"
|
||||||
[tool.poetry.group.doc.dependencies]
|
|
||||||
jupyter = "^1.0.0"
|
[tool.poetry.group.doc.dependencies]
|
||||||
myst-parser = "^1.0.0"
|
jupyter = "^1.0.0"
|
||||||
nbsphinx = "^0.9.2"
|
myst-parser = "^1.0.0"
|
||||||
sphinx = "^6.0.0"
|
nbsphinx = "^0.9.2"
|
||||||
sphinx-copybutton = "^0.5.2"
|
sphinx = "^6.0.0"
|
||||||
sphinx-rtd-theme = "^1.2.1"
|
sphinx-copybutton = "^0.5.2"
|
||||||
sphinx_autodoc_typehints = "*"
|
sphinx-rtd-theme = "^1.2.1"
|
||||||
sphinxcontrib-mermaid = "^0.9.2"
|
sphinx_autodoc_typehints = "*"
|
||||||
sphinxcontrib-napoleon = "^0.7"
|
sphinxcontrib-mermaid = "^0.9.2"
|
||||||
|
sphinxcontrib-napoleon = "^0.7"
|
||||||
[tool.poetry.group.lint.dependencies]
|
|
||||||
black = "^23.3.0"
|
[tool.poetry.group.lint.dependencies]
|
||||||
mypy = "^1.3.0"
|
black = "^23.3.0"
|
||||||
pandas-stubs = "^2.0.1.230501"
|
mypy = "^1.3.0"
|
||||||
ruff = "^0.0.270"
|
pandas-stubs = "^2.0.1.230501"
|
||||||
types-requests = "^2.31.0.1"
|
ruff = "^0.0.270"
|
||||||
|
types-requests = "^2.31.0.1"
|
||||||
[tool.poetry.group.test.dependencies]
|
|
||||||
pytest = "^7.3.1"
|
[tool.poetry.group.test.dependencies]
|
||||||
pytest-clarity = "^1.0.1"
|
pytest = "^7.3.1"
|
||||||
pytest-cov = "^4.1.0"
|
pytest-clarity = "^1.0.1"
|
||||||
pytest-mock = "^3.10.0"
|
pytest-cov = "^4.1.0"
|
||||||
pytest-repeat = "^0.9.1"
|
pytest-mock = "^3.10.0"
|
||||||
|
pytest-repeat = "^0.9.1"
|
||||||
[tool.ruff]
|
|
||||||
exclude = [
|
[tool.ruff]
|
||||||
".bzr",
|
exclude = [
|
||||||
".direnv",
|
".bzr",
|
||||||
".eggs",
|
".direnv",
|
||||||
".git",
|
".eggs",
|
||||||
".git-rewrite",
|
".git",
|
||||||
".hg",
|
".git-rewrite",
|
||||||
".mypy_cache",
|
".hg",
|
||||||
".nox",
|
".mypy_cache",
|
||||||
".pants.d",
|
".nox",
|
||||||
".pytype",
|
".pants.d",
|
||||||
".ruff_cache",
|
".pytype",
|
||||||
".svn",
|
".ruff_cache",
|
||||||
".tox",
|
".svn",
|
||||||
".venv",
|
".tox",
|
||||||
"__pypackages__",
|
".venv",
|
||||||
"_build",
|
"__pypackages__",
|
||||||
"buck-out",
|
"_build",
|
||||||
"build",
|
"buck-out",
|
||||||
"dist",
|
"build",
|
||||||
"node_modules",
|
"dist",
|
||||||
"venv"
|
"node_modules",
|
||||||
]
|
"venv"
|
||||||
# Never enforce `E501` (line length violations).
|
]
|
||||||
ignore = ["E501"]
|
# Never enforce `E501` (line length violations).
|
||||||
line-length = 88
|
ignore = ["E501"]
|
||||||
# Enable flake8-bugbear (`B`) rules.
|
line-length = 88
|
||||||
select = ["E", "F", "B", "I", "S", "RSE", "RET", "SLF", "SIM", "TID", "PD", "PL", "PLE", "PLR", "PLW", "NPY", "UP", "D", "N", "A", "C4", "T20", "PT"]
|
# Enable flake8-bugbear (`B`) rules.
|
||||||
src = ["src"]
|
select = ["E", "F", "B", "I", "S", "RSE", "RET", "SLF", "SIM", "TID", "PD", "PL", "PLE", "PLR", "PLW", "NPY", "UP", "D", "N", "A", "C4", "T20", "PT"]
|
||||||
target-version = "py311"
|
src = ["src"]
|
||||||
# Avoid trying to fix flake8-bugbear (`B`) violations.
|
target-version = "py311"
|
||||||
unfixable = ["B"]
|
# Avoid trying to fix flake8-bugbear (`B`) violations.
|
||||||
|
unfixable = ["B"]
|
||||||
[tool.ruff.flake8-builtins]
|
|
||||||
builtins-ignorelist = ["id"]
|
[tool.ruff.flake8-builtins]
|
||||||
|
builtins-ignorelist = ["id"]
|
||||||
[tool.ruff.per-file-ignores]
|
|
||||||
"tests/*.py" = ["S101"]
|
[tool.ruff.per-file-ignores]
|
||||||
|
"tests/*.py" = ["S101", "D100", "D101", "D107", "D103"]
|
||||||
[tool.ruff.pydocstyle]
|
|
||||||
convention = "google"
|
[tool.ruff.pydocstyle]
|
||||||
|
convention = "google"
|
||||||
|
@ -1,54 +1,49 @@
|
|||||||
"""CompanyMongoService."""
|
"""CompanyMongoService."""
|
||||||
from models.company import Company
|
from aki_prj23_transparenzregister.models.company import Company, CompanyID
|
||||||
from utils.company_service_interface import CompanyServiceInterface
|
from aki_prj23_transparenzregister.utils.mongo import MongoConnector
|
||||||
from utils.mongo import MongoConnector
|
|
||||||
|
|
||||||
|
class CompanyMongoService:
|
||||||
class CompanyMongoService(CompanyServiceInterface):
|
"""_summary_."""
|
||||||
"""_summary_.
|
|
||||||
|
def __init__(self, connector: MongoConnector):
|
||||||
Args:
|
"""_summary_.
|
||||||
CompanyServiceInterface (_type_): _description_
|
|
||||||
"""
|
Args:
|
||||||
|
connector (MongoConnector): _description_
|
||||||
def __init__(self, connector: MongoConnector):
|
"""
|
||||||
"""_summary_.
|
self.collection = connector.database["companies"]
|
||||||
|
|
||||||
Args:
|
def get_all(self) -> list[Company]:
|
||||||
connector (MongoConnector): _description_
|
"""_summary_.
|
||||||
"""
|
|
||||||
self.collection = connector.database["companies"]
|
Returns:
|
||||||
|
list[Company]: _description_
|
||||||
def get_all(self) -> list[Company]:
|
"""
|
||||||
"""_summary_.
|
result = self.collection.find()
|
||||||
|
return list(result)
|
||||||
Returns:
|
|
||||||
list[Company]: _description_
|
def get_by_id(self, id: CompanyID) -> Company | None:
|
||||||
"""
|
"""_summary_.
|
||||||
result = self.collection.find()
|
|
||||||
return list(result)
|
Args:
|
||||||
|
id (str): _description_
|
||||||
def get_by_id(self, id: str) -> Company | None:
|
|
||||||
"""_summary_.
|
Returns:
|
||||||
|
Company | None: _description_
|
||||||
Args:
|
"""
|
||||||
id (str): _description_
|
result = list(self.collection.find({"id": id}))
|
||||||
|
if len(result) == 1:
|
||||||
Returns:
|
return result[0]
|
||||||
Company | None: _description_
|
return None
|
||||||
"""
|
|
||||||
result = list(self.collection.find({"id": id}))
|
def insert(self, company: Company):
|
||||||
if len(result) == 1:
|
"""_summary_.
|
||||||
return result[0]
|
|
||||||
return None
|
Args:
|
||||||
|
company (Company): _description_
|
||||||
def insert(self, company: Company):
|
|
||||||
"""_summary_.
|
Returns:
|
||||||
|
_type_: _description_
|
||||||
Args:
|
"""
|
||||||
company (Company): _description_
|
return self.collection.insert_one(company.to_dict())
|
||||||
|
|
||||||
Returns:
|
|
||||||
_type_: _description_
|
|
||||||
"""
|
|
||||||
return self.collection.insert_one(company.to_dict())
|
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
"""CompanyServiceInterface."""
|
|
||||||
import abc
|
|
||||||
|
|
||||||
from models import Company
|
|
||||||
|
|
||||||
|
|
||||||
class CompanyServiceInterface(abc.ABC):
|
|
||||||
"""Generic abstract interface for CRUD operations of a Company.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
ABC (_type_): Abstract class
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def get_all(self) -> list[Company.Company]:
|
|
||||||
"""_summary_.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
NotImplementedError: _description_
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[Company.Company]: _description_
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def get_by_id(self, id: Company.CompayID) -> Company.Company | None:
|
|
||||||
"""_summary_.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
id (Company.CompayID): _description_
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
NotImplementedError: _description_
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Company.Company | None: _description_
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def insert(self, company: Company.Company):
|
|
||||||
"""_summary_.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
company (Company.Company): _description_
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
NotImplementedError: _description_
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
@ -1,155 +1,60 @@
|
|||||||
"""Mongo Wrapper."""
|
"""Mongo Wrapper."""
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
import pymongo
|
import pymongo
|
||||||
from models.news import News
|
|
||||||
from utils.news_service_interface import (
|
|
||||||
NewsServiceInterface,
|
@dataclass
|
||||||
)
|
class MongoConnection:
|
||||||
|
"""_summary_."""
|
||||||
|
|
||||||
@dataclass
|
hostname: str
|
||||||
class MongoConnection:
|
database: str
|
||||||
"""_summary_."""
|
port: int | None
|
||||||
|
username: str | None
|
||||||
hostname: str
|
password: str | None
|
||||||
database: str
|
|
||||||
port: int | None
|
|
||||||
username: str | None
|
class MongoConnector:
|
||||||
password: str | None
|
"""Wrapper for establishing a connection to a MongoDB instance."""
|
||||||
|
|
||||||
|
def __init__(self, connection: MongoConnection):
|
||||||
class MongoConnector:
|
"""_summary_.
|
||||||
"""Wrapper for establishing a connection to a MongoDB instance."""
|
|
||||||
|
Args:
|
||||||
def __init__(self, connection: MongoConnection):
|
connection (MongoConnection): Wrapper for connection string
|
||||||
"""_summary_.
|
"""
|
||||||
|
self.client = self.connect(
|
||||||
Args:
|
connection.hostname,
|
||||||
connection (MongoConnection): Wrapper for connection string
|
connection.port,
|
||||||
"""
|
connection.username,
|
||||||
self.client = self.connect(
|
connection.password,
|
||||||
connection.hostname,
|
)
|
||||||
connection.port,
|
self.database = self.client[connection.database]
|
||||||
connection.username,
|
|
||||||
connection.password,
|
def connect(
|
||||||
)
|
self,
|
||||||
self.database = self.client[connection.database]
|
hostname: str,
|
||||||
|
port: int | None,
|
||||||
def connect(
|
username: str | None,
|
||||||
self,
|
password: str | None,
|
||||||
hostname: str,
|
) -> pymongo.MongoClient:
|
||||||
port: int | None,
|
"""_summary_.
|
||||||
username: str | None,
|
|
||||||
password: str | None,
|
Args:
|
||||||
) -> pymongo.MongoClient:
|
hostname (str): hostname
|
||||||
"""_summary_.
|
port (int): port
|
||||||
|
username (str): Username
|
||||||
Args:
|
password (str): Password
|
||||||
hostname (str): hostname
|
|
||||||
port (int): port
|
Returns:
|
||||||
username (str): Username
|
pymongo.MongoClient: MongoClient connect to the DB
|
||||||
password (str): Password
|
"""
|
||||||
|
if username is not None and password is not None:
|
||||||
Returns:
|
connection_string = f"mongodb+srv://{username}:{password}@{hostname}"
|
||||||
pymongo.MongoClient: MongoClient connect to the DB
|
else:
|
||||||
"""
|
connection_string = f"mongodb+srv://{hostname}"
|
||||||
if username is not None and password is not None:
|
if port is not None:
|
||||||
connection_string = f"mongodb+srv://{username}:{password}@{hostname}"
|
connection_string += f":{port}"
|
||||||
else:
|
connection_string = connection_string.replace("mongodb+srv", "mongodb")
|
||||||
connection_string = f"mongodb+srv://{hostname}"
|
return pymongo.MongoClient(connection_string)
|
||||||
if port is not None:
|
|
||||||
connection_string += f":{port}"
|
|
||||||
connection_string = connection_string.replace("mongodb+srv", "mongodb")
|
|
||||||
return pymongo.MongoClient(connection_string)
|
|
||||||
|
|
||||||
|
|
||||||
class MongoNewsService(NewsServiceInterface):
|
|
||||||
"""_summary_.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
NewsServiceInterface (_type_): _description_
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, connector: MongoConnector):
|
|
||||||
"""_summary_.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
connector (MongoConnector): _description_
|
|
||||||
"""
|
|
||||||
self.collection = connector.database["news"]
|
|
||||||
|
|
||||||
def get_all(self) -> list[News]:
|
|
||||||
"""_summary_.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[News]: _description_
|
|
||||||
"""
|
|
||||||
result = self.collection.find()
|
|
||||||
return [MongoEntryTransformer.transform_outgoing(elem) for elem in result]
|
|
||||||
|
|
||||||
def get_by_id(self, id: str) -> News | None:
|
|
||||||
"""_summary_.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
id (str): _description_
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
News | None: _description_
|
|
||||||
"""
|
|
||||||
result = list(self.collection.find({"_id": id}))
|
|
||||||
if len(result) == 1:
|
|
||||||
return MongoEntryTransformer.transform_outgoing(list(result)[0])
|
|
||||||
return None
|
|
||||||
|
|
||||||
def insert(self, news: News):
|
|
||||||
"""_summary_.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
news (News): _description_
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
_type_: _description_
|
|
||||||
"""
|
|
||||||
return self.collection.insert_one(MongoEntryTransformer.transform_ingoing(news))
|
|
||||||
|
|
||||||
|
|
||||||
class MongoEntryTransformer:
|
|
||||||
"""_summary_.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
_type_: _description_
|
|
||||||
"""
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def transform_ingoing(news: News) -> dict:
|
|
||||||
"""Convert a News object to a dictionary compatible with a MongoDB entry.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
news (News): News object to be transformed
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict: Transformed data with added _id field
|
|
||||||
"""
|
|
||||||
transport_object = news.to_dict()
|
|
||||||
transport_object["_id"] = news.id
|
|
||||||
del transport_object["id"]
|
|
||||||
return transport_object
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def transform_outgoing(data: dict) -> News:
|
|
||||||
"""Reverse the transform_ingoing method.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
data (dict): dict from the MongoDB to be transformed
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
News: News entry based on MongoDB document
|
|
||||||
"""
|
|
||||||
return News(
|
|
||||||
id=data["_id"],
|
|
||||||
title=data["title"],
|
|
||||||
date=data["date"],
|
|
||||||
text=data["text"],
|
|
||||||
source_url=data["source_url"],
|
|
||||||
)
|
|
||||||
|
@ -0,0 +1,94 @@
|
|||||||
|
"""MongoNewsService."""
|
||||||
|
from aki_prj23_transparenzregister.models.news import News
|
||||||
|
from aki_prj23_transparenzregister.utils.mongo import MongoConnector
|
||||||
|
|
||||||
|
|
||||||
|
class MongoNewsService:
|
||||||
|
"""_summary_.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
NewsServiceInterface (_type_): _description_
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, connector: MongoConnector):
|
||||||
|
"""_summary_.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
connector (MongoConnector): _description_
|
||||||
|
"""
|
||||||
|
self.collection = connector.database["news"]
|
||||||
|
|
||||||
|
def get_all(self) -> list[News]:
|
||||||
|
"""_summary_.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list[News]: _description_
|
||||||
|
"""
|
||||||
|
result = self.collection.find()
|
||||||
|
return [MongoEntryTransformer.transform_outgoing(elem) for elem in result]
|
||||||
|
|
||||||
|
def get_by_id(self, id: str) -> News | None:
|
||||||
|
"""_summary_.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
id (str): _description_
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
News | None: _description_
|
||||||
|
"""
|
||||||
|
result = list(self.collection.find({"_id": id}))
|
||||||
|
if len(result) == 1:
|
||||||
|
return MongoEntryTransformer.transform_outgoing(list(result)[0])
|
||||||
|
return None
|
||||||
|
|
||||||
|
def insert(self, news: News):
|
||||||
|
"""_summary_.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
news (News): _description_
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
_type_: _description_
|
||||||
|
"""
|
||||||
|
return self.collection.insert_one(MongoEntryTransformer.transform_ingoing(news))
|
||||||
|
|
||||||
|
|
||||||
|
class MongoEntryTransformer:
|
||||||
|
"""_summary_.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
_type_: _description_
|
||||||
|
"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def transform_ingoing(news: News) -> dict:
|
||||||
|
"""Convert a News object to a dictionary compatible with a MongoDB entry.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
news (News): News object to be transformed
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: Transformed data with added _id field
|
||||||
|
"""
|
||||||
|
transport_object = news.to_dict()
|
||||||
|
transport_object["_id"] = news.id
|
||||||
|
del transport_object["id"]
|
||||||
|
return transport_object
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def transform_outgoing(data: dict) -> News:
|
||||||
|
"""Reverse the transform_ingoing method.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (dict): dict from the MongoDB to be transformed
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
News: News entry based on MongoDB document
|
||||||
|
"""
|
||||||
|
return News(
|
||||||
|
id=data["_id"],
|
||||||
|
title=data["title"],
|
||||||
|
date=data["date"],
|
||||||
|
text=data["text"],
|
||||||
|
source_url=data["source_url"],
|
||||||
|
)
|
@ -1,63 +0,0 @@
|
|||||||
"""NewsServiceInterface."""
|
|
||||||
import abc
|
|
||||||
|
|
||||||
from models.news import News
|
|
||||||
|
|
||||||
|
|
||||||
class NewsServiceInterface(abc.ABC):
|
|
||||||
"""Generic abstract interface for a NewsService handling CRUD operations.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
ABC (_type_): Abstract class
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def get_all(self) -> list[News]:
|
|
||||||
"""Get a list of all News articles.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
NotImplementedError: To be defined by child classes
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[News]: Results
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def get_by_id(self, id: str) -> News | None:
|
|
||||||
"""Get an entry by an ID.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
id (str): ID identifying the entry
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
NotImplementedError: To be defined by child classes
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
News | None: Found object or None if no entry with ID found
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def insert(self, news: News):
|
|
||||||
"""Insert a News entry into the DB.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
news (News): News object to be saved
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
NotImplementedError: To be defined by child classes
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def insert_many(self, news: list[News]):
|
|
||||||
"""Inserts many documents at once.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
news (list[News]): List of News entries to be saved
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
NotImplementedError: To be defined by child classes
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
@ -1,4 +1,4 @@
|
|||||||
"""Test Models.nes."""
|
"""Test Models.nesws."""
|
||||||
|
|
||||||
|
|
||||||
from aki_prj23_transparenzregister.models.news import News
|
from aki_prj23_transparenzregister.models.news import News
|
||||||
|
103
tests/utils/company_mongo_service_test.py
Normal file
103
tests/utils/company_mongo_service_test.py
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
"""Test utils.company_mongo_service."""
|
||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from aki_prj23_transparenzregister.models.company import Company
|
||||||
|
from aki_prj23_transparenzregister.utils.company_mongo_service import (
|
||||||
|
CompanyMongoService,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def mock_mongo_connector(mocker) -> Mock:
|
||||||
|
"""Mock MongoConnector class.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
mocker (any): Library mocker
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Mock: Mocked MongoConnector
|
||||||
|
"""
|
||||||
|
mock = Mock()
|
||||||
|
mocker.patch(
|
||||||
|
"aki_prj23_transparenzregister.utils.mongo.MongoConnector", return_value=mock
|
||||||
|
)
|
||||||
|
return mock
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def mock_collection() -> Mock:
|
||||||
|
"""Mock mongo collection.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Mock: Mock object
|
||||||
|
"""
|
||||||
|
return Mock()
|
||||||
|
|
||||||
|
|
||||||
|
def test_init(mock_mongo_connector, mock_collection):
|
||||||
|
"""Test CompanyMongoService constructor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
mock_mongo_connector (Mock): Mocked MongoConnector library
|
||||||
|
mock_collection (Mock): Mocked pymongo collection
|
||||||
|
"""
|
||||||
|
mock_mongo_connector.database = {"companies": mock_collection}
|
||||||
|
service = CompanyMongoService(mock_mongo_connector)
|
||||||
|
assert service.collection == mock_collection
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_all(mock_mongo_connector, mock_collection):
|
||||||
|
"""Test CompanyMongoService get_all method.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
mock_mongo_connector (Mock): Mocked MongoConnector library
|
||||||
|
mock_collection (Mock): Mocked pymongo collection
|
||||||
|
"""
|
||||||
|
mock_mongo_connector.database = {"companies": mock_collection}
|
||||||
|
service = CompanyMongoService(mock_mongo_connector)
|
||||||
|
mock_result = [{"id": "42"}]
|
||||||
|
mock_collection.find.return_value = mock_result
|
||||||
|
assert service.get_all() == mock_result
|
||||||
|
|
||||||
|
|
||||||
|
def test_by_id_no_result(mock_mongo_connector, mock_collection):
|
||||||
|
"""Test CompanyMongoService get_by_id with no result.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
mock_mongo_connector (Mock): Mocked MongoConnector library
|
||||||
|
mock_collection (Mock): Mocked pymongo collection
|
||||||
|
"""
|
||||||
|
mock_mongo_connector.database = {"companies": mock_collection}
|
||||||
|
service = CompanyMongoService(mock_mongo_connector)
|
||||||
|
mock_collection.find.return_value = []
|
||||||
|
assert service.get_by_id("Does not exist") is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_by_id_result(mock_mongo_connector, mock_collection):
|
||||||
|
"""Test CompanyMongoService get_by_id with result.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
mock_mongo_connector (Mock): Mocked MongoConnector library
|
||||||
|
mock_collection (Mock): Mocked pymongo collection
|
||||||
|
"""
|
||||||
|
mock_mongo_connector.database = {"companies": mock_collection}
|
||||||
|
service = CompanyMongoService(mock_mongo_connector)
|
||||||
|
mock_entry = {"id": "Does exist", "vaue": 42}
|
||||||
|
mock_collection.find.return_value = [mock_entry]
|
||||||
|
assert service.get_by_id("Does exist") == mock_entry
|
||||||
|
|
||||||
|
|
||||||
|
def test_insert(mock_mongo_connector, mock_collection):
|
||||||
|
"""Test CompanyMongoService insert method.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
mock_mongo_connector (Mock): Mocked MongoConnector library
|
||||||
|
mock_collection (Mock): Mocked pymongo collection
|
||||||
|
"""
|
||||||
|
mock_mongo_connector.database = {"companies": mock_collection}
|
||||||
|
service = CompanyMongoService(mock_mongo_connector)
|
||||||
|
mock_result = 42
|
||||||
|
mock_collection.insert_one.return_value = mock_result
|
||||||
|
assert service.insert(Company(None, None, "", "", [])) == mock_result
|
44
tests/utils/news_mongo_service_test.py
Normal file
44
tests/utils/news_mongo_service_test.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from aki_prj23_transparenzregister.utils.news_mongo_service import MongoNewsService
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def mock_mongo_connector(mocker) -> Mock:
|
||||||
|
"""Mock MongoConnector class.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
mocker (any): Library mocker
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Mock: Mocked MongoConnector
|
||||||
|
"""
|
||||||
|
mock = Mock()
|
||||||
|
mocker.patch(
|
||||||
|
"aki_prj23_transparenzregister.utils.mongo.MongoConnector", return_value=mock
|
||||||
|
)
|
||||||
|
return mock
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def mock_collection() -> Mock:
|
||||||
|
"""Mock mongo collection.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Mock: Mock object
|
||||||
|
"""
|
||||||
|
return Mock()
|
||||||
|
|
||||||
|
|
||||||
|
def test_init(mock_mongo_connector, mock_collection):
|
||||||
|
"""Test CompanyMongoService constructor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
mock_mongo_connector (Mock): Mocked MongoConnector library
|
||||||
|
mock_collection (Mock): Mocked pymongo collection
|
||||||
|
"""
|
||||||
|
mock_mongo_connector.database = {"news": mock_collection}
|
||||||
|
service = MongoNewsService(mock_mongo_connector)
|
||||||
|
assert service.collection == mock_collection
|
Reference in New Issue
Block a user