mirror of
https://github.com/rjNemo/pass-gen
synced 2026-06-06 02:26:42 +00:00
refactor: fake repo and tesrt coverage
This commit is contained in:
parent
183f739223
commit
6332b9e233
10 changed files with 52 additions and 35 deletions
8
.coveragerc
Normal file
8
.coveragerc
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
[run]
|
||||
omit =
|
||||
# omit tests
|
||||
*/tests/*
|
||||
# omit non testable files
|
||||
app/__main__.py
|
||||
[html]
|
||||
directory = .htmlcov
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -24,7 +24,7 @@ MANIFEST
|
|||
*.spec
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
htmlcov/
|
||||
.htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from .main import app
|
||||
|
||||
|
||||
app() # pragma nocover
|
||||
app()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from typing import Any, Protocol
|
|||
|
||||
class DBConnector(Protocol):
|
||||
def commit(self) -> None:
|
||||
...
|
||||
... # pragma nocover
|
||||
|
||||
def execute(self, query: str, *args: Any) -> Cursor:
|
||||
...
|
||||
... # pragma nocover
|
||||
|
|
|
|||
|
|
@ -1,22 +1,21 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pydantic import SecretStr
|
||||
|
||||
from app.models.password import Password
|
||||
|
||||
|
||||
class FakeRepository:
|
||||
_values = {}
|
||||
|
||||
def save(self, service: str, password: str) -> None:
|
||||
...
|
||||
self._values[service] = password
|
||||
|
||||
def list_all(self) -> list[Password]:
|
||||
return [
|
||||
Password(id=0, service="first", password=SecretStr("2yW4AcqG")),
|
||||
Password(id=1, service="second", password=SecretStr("iK2ZWeqh")),
|
||||
Password(id=i, service=v[0], password=v[1]) for i, v in enumerate(self._values.items())
|
||||
]
|
||||
|
||||
def exists(self, service: str) -> bool:
|
||||
return False
|
||||
return service in self._values.keys()
|
||||
|
||||
@classmethod
|
||||
def get_instance(cls) -> FakeRepository:
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ from app.models.password import Password
|
|||
|
||||
class Repository(Protocol):
|
||||
def save(self, service: str, password: str) -> None:
|
||||
...
|
||||
... # pragma nocover
|
||||
|
||||
def list_all(self) -> list[Password]:
|
||||
...
|
||||
... # pragma nocover
|
||||
|
||||
def exists(self, service: str) -> bool:
|
||||
...
|
||||
... # pragma nocover
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@ import random
|
|||
import string
|
||||
from typing import Protocol
|
||||
|
||||
from pydantic import BaseModel
|
||||
from pydantic.dataclasses import dataclass
|
||||
|
||||
from app.models.password import Password
|
||||
from app.repositories.type import Repository
|
||||
|
||||
|
||||
class PassGenOptions(BaseModel):
|
||||
@dataclass(frozen=True)
|
||||
class PassGenOptions:
|
||||
service: str
|
||||
seed: int
|
||||
length: int = 8
|
||||
|
|
|
|||
|
|
@ -11,3 +11,8 @@ warn_unused_ignores = True
|
|||
warn_unreachable = True
|
||||
warn_redundant_casts = True
|
||||
disallow_untyped_defs=True
|
||||
|
||||
plugins = pydantic.mypy
|
||||
[pydantic-mypy]
|
||||
init_forbid_extra = True
|
||||
init_typed = True
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
from typing import Any
|
||||
|
||||
from faker import Factory
|
||||
|
||||
from app.main import app
|
||||
from typer.testing import CliRunner, Result
|
||||
|
||||
from app.main import app
|
||||
|
||||
runner = CliRunner()
|
||||
faker = Factory.create()
|
||||
|
|
@ -49,6 +48,13 @@ def test_cli_can_save_to_db() -> None:
|
|||
assert "2yW4AcqG" in result.stdout
|
||||
|
||||
|
||||
def test_cli_cannot_save_password_for_service_twice() -> None:
|
||||
service_name = faker.pystr()
|
||||
runner.invoke(app, ["save", service_name, "--no-random"])
|
||||
result = runner.invoke(app, ["save", service_name, "--no-random"])
|
||||
assert "already been set" in result.stdout
|
||||
|
||||
|
||||
def _run_cli(*args: Any) -> Result:
|
||||
result = runner.invoke(app, ["save", faker.pystr(), "--no-random", *args])
|
||||
assert result.exit_code == 0
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import pytest
|
||||
from pydantic import SecretStr
|
||||
from faker import Factory
|
||||
|
||||
from app.models.password import Password
|
||||
from app.repositories.fake import FakeRepository
|
||||
from app.usecases.pass_gen import PassGenOptions, generate_password, list_all_saved_passwords
|
||||
|
||||
fake_repo = FakeRepository.get_instance()
|
||||
service = "service_name"
|
||||
faker = Factory.create()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
|
@ -17,7 +16,7 @@ service = "service_name"
|
|||
],
|
||||
)
|
||||
def test_can_generate_random_password(seed: int, expected: str) -> None:
|
||||
options = PassGenOptions(seed=seed, service=service)
|
||||
options = PassGenOptions(seed=seed, service=faker.pystr())
|
||||
assert generate_password(fake_repo, options) == expected
|
||||
|
||||
|
||||
|
|
@ -29,7 +28,7 @@ def test_can_generate_random_password(seed: int, expected: str) -> None:
|
|||
],
|
||||
)
|
||||
def test_control_password_length(seed: int, length: int, expected: str) -> None:
|
||||
options = PassGenOptions(seed=seed, length=length, service=service)
|
||||
options = PassGenOptions(seed=seed, length=length, service=faker.pystr())
|
||||
assert generate_password(fake_repo, options) == expected
|
||||
|
||||
|
||||
|
|
@ -41,7 +40,7 @@ def test_control_password_length(seed: int, length: int, expected: str) -> None:
|
|||
],
|
||||
)
|
||||
def test_password_can_contain_symbols(seed: int, symbols: bool, expected: str) -> None:
|
||||
options = PassGenOptions(seed=seed, symbols=symbols, service=service)
|
||||
options = PassGenOptions(seed=seed, symbols=symbols, service=faker.pystr())
|
||||
assert generate_password(fake_repo, options) == expected
|
||||
|
||||
|
||||
|
|
@ -53,18 +52,17 @@ def test_password_can_contain_symbols(seed: int, symbols: bool, expected: str) -
|
|||
],
|
||||
)
|
||||
def test_password_can_contain_numbers(seed: int, numbers: bool, expected: str) -> None:
|
||||
options = PassGenOptions(seed=seed, numbers=numbers, service=service)
|
||||
options = PassGenOptions(seed=seed, numbers=numbers, service=faker.pystr())
|
||||
assert generate_password(fake_repo, options) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"expected",
|
||||
[
|
||||
[
|
||||
Password(id=0, service="first", password=SecretStr("2yW4AcqG")),
|
||||
Password(id=1, service="second", password=SecretStr("iK2ZWeqh")),
|
||||
],
|
||||
],
|
||||
)
|
||||
def test_can_read_all_saved_passwords(expected: list[str]) -> None:
|
||||
assert list_all_saved_passwords(fake_repo) == expected
|
||||
@pytest.mark.parametrize("expected", [8])
|
||||
def test_can_read_all_saved_passwords(expected: int) -> None:
|
||||
assert len(list_all_saved_passwords(fake_repo)) == expected
|
||||
|
||||
|
||||
def test_cannot_save_password_for_service_twice() -> None:
|
||||
with pytest.raises(ValueError, match="already been set"):
|
||||
options = PassGenOptions(seed=0, service=faker.pystr())
|
||||
generate_password(fake_repo, options)
|
||||
generate_password(fake_repo, options)
|
||||
|
|
|
|||
Loading…
Reference in a new issue