Skip to content

Commit

Permalink
Merge pull request #30 from ikalnytskyi/chore/test-improvements
Browse files Browse the repository at this point in the history
few test improvements
  • Loading branch information
ikalnytskyi authored May 8, 2024
2 parents 88e6191 + 721f807 commit fd35ef6
Show file tree
Hide file tree
Showing 7 changed files with 273 additions and 197 deletions.
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ target-version = "py38"

[tool.ruff.lint]
select = ["ALL"]
ignore = ["ANN", "D", "PTH", "PLR", "PT005", "ISC001", "INP001", "S603", "S607", "COM812"]
ignore = ["D", "PTH", "PLR", "PT005", "ISC001", "INP001", "S603", "S607", "COM812", "FA100", "ANN101"]

[tool.ruff.lint.per-file-ignores]
"src/*" = ["ANN"]
"src/httpie_credential_store/_keychain.py" = ["S602"]
"tests/*" = ["S101", "INP001"]

Expand Down
4 changes: 2 additions & 2 deletions src/httpie_credential_store/_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ def get_auth_for(self, url, credential_id=None):
raise LookupError(message)


def get_credential_store(name, directory=httpie.config.DEFAULT_CONFIG_DIR):
def get_credential_store(name, directory=None):
"""Returns a credential store that can be used to lookup credentials."""

credentials = []
credential_file = os.path.join(directory, name)
credential_file = os.path.join(directory or httpie.config.DEFAULT_CONFIG_DIR, name)

if not os.path.exists(credential_file):
error_message = (
Expand Down
20 changes: 0 additions & 20 deletions tests/conftest.py

This file was deleted.

22 changes: 10 additions & 12 deletions tests/test_keychain_password_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
import sys
import tempfile
import textwrap
import typing

import pytest

from httpie_credential_store._keychain import PasswordStoreKeychain


_is_macos = sys.platform == "darwin"

Expand All @@ -29,13 +32,13 @@
# override 'tmp_path' fixture to return much shorter path to a temporary
# directory.
@pytest.fixture()
def tmp_path():
def tmp_path() -> typing.Generator[pathlib.Path, None, None]:
with tempfile.TemporaryDirectory() as path:
yield pathlib.Path(path)


@pytest.fixture()
def gpg_key_id(monkeypatch, tmp_path):
def gpg_key_id(monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path) -> str:
"""Return a Key ID of just generated GPG key."""

gpghome = tmp_path.joinpath(".gnupg")
Expand Down Expand Up @@ -68,7 +71,7 @@ def gpg_key_id(monkeypatch, tmp_path):


@pytest.fixture(autouse=True)
def password_store_dir(monkeypatch, tmp_path):
def password_store_dir(monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path) -> pathlib.Path:
"""Set password-store home directory to a temporary one."""

passstore = tmp_path.joinpath(".password-store")
Expand All @@ -77,18 +80,13 @@ def password_store_dir(monkeypatch, tmp_path):


@pytest.fixture()
def testkeychain():
def testkeychain() -> PasswordStoreKeychain:
"""Keychain instance under test."""

# For the same reasons as in tests/test_plugin.py, all imports that trigger
# HTTPie importing must be postponed till one of our fixtures is evaluated
# and patched a path to HTTPie configuration.
from httpie_credential_store import _keychain

return _keychain.PasswordStoreKeychain()
return PasswordStoreKeychain()


def test_secret_retrieved(testkeychain, gpg_key_id):
def test_secret_retrieved(testkeychain: PasswordStoreKeychain, gpg_key_id: str) -> None:
"""The keychain returns stored secret, no bullshit."""

subprocess.check_call(["pass", "init", gpg_key_id])
Expand All @@ -97,7 +95,7 @@ def test_secret_retrieved(testkeychain, gpg_key_id):
assert testkeychain.get(name="service/user") == "f00b@r"


def test_secret_not_found(testkeychain):
def test_secret_not_found(testkeychain: PasswordStoreKeychain) -> None:
"""LookupError is raised when no secrets are found in the keychain."""

with pytest.raises(LookupError) as excinfo:
Expand Down
25 changes: 14 additions & 11 deletions tests/test_keychain_shell.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
"""Tests shell keychain provider."""

import os
import pathlib
import typing

import pytest

from httpie_credential_store._keychain import ShellKeychain


@pytest.fixture()
def testkeychain():
def testkeychain() -> ShellKeychain:
"""Keychain instance under test."""

# For the same reasons as in tests/test_plugin.py, all imports that trigger
# HTTPie importing must be postponed till one of our fixtures is evaluated
# and patched a path to HTTPie configuration.
from httpie_credential_store import _keychain

return _keychain.ShellKeychain()
return ShellKeychain()


def test_secret_retrieved(testkeychain, tmp_path):
def test_secret_retrieved(testkeychain: ShellKeychain, tmp_path: pathlib.Path) -> None:
"""The keychain returns stored secret, no bullshit."""

secrettxt = tmp_path.joinpath("secret.txt")
secrettxt.write_text("p@ss", encoding="UTF-8")
assert testkeychain.get(command=f"cat {secrettxt}") == "p@ss"


def test_secret_retrieved_pipe(testkeychain, tmp_path):
def test_secret_retrieved_pipe(testkeychain: ShellKeychain, tmp_path: pathlib.Path) -> None:
"""The keychain returns stored secret even when pipes are used."""

secrettxt = tmp_path.joinpath("secret.txt")
Expand All @@ -35,7 +34,7 @@ def test_secret_retrieved_pipe(testkeychain, tmp_path):
assert testkeychain.get(command=command) == "p@ss"


def test_secret_not_found(testkeychain, tmp_path):
def test_secret_not_found(testkeychain: ShellKeychain, tmp_path: pathlib.Path) -> None:
"""LookupError is raised when no secrets are found in the keychain."""

secrettxt = tmp_path.joinpath("secret.txt")
Expand All @@ -49,6 +48,10 @@ def test_secret_not_found(testkeychain, tmp_path):


@pytest.mark.parametrize(("args", "kwargs"), [pytest.param(["echo p@ss"], {}, id="args")])
def test_keywords_only_arguments(testkeychain, args, kwargs):
def test_keywords_only_arguments(
testkeychain: ShellKeychain,
args: typing.List[str],
kwargs: typing.Mapping[str, str],
) -> None:
with pytest.raises(TypeError):
testkeychain.get(*args, **kwargs)
41 changes: 26 additions & 15 deletions tests/test_keychain_system.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,34 @@
"""Tests system keychain provider."""

import typing

import keyring
import keyring.backend
import keyring.compat
import pytest

from httpie_credential_store._keychain import SystemKeychain


class _InmemoryKeyring(keyring.backend.KeyringBackend):
"""Keyring backend that stores secrets in-memory."""

priority = 1
@keyring.compat.properties.classproperty
def priority(self) -> float:
return 1.0

def __init__(self):
def __init__(self) -> None:
self._keyring = {}

def get_password(self, service, username):
def get_password(self, service: str, username: str) -> typing.Optional[str]:
return self._keyring.get((service, username))

def set_password(self, service, username, password):
def set_password(self, service: str, username: str, password: str) -> None:
self._keyring[(service, username)] = password


@pytest.fixture(autouse=True)
def keyring_backend():
def keyring_backend() -> typing.Generator[keyring.backend.KeyringBackend, None, None]:
"""Temporary set in-memory keyring as current backend."""

prev_backend = keyring.get_keyring()
Expand All @@ -30,25 +38,23 @@ def keyring_backend():


@pytest.fixture()
def testkeychain():
def testkeychain() -> SystemKeychain:
"""Keychain instance under test."""

# For the same reasons as in tests/test_plugin.py, all imports that trigger
# HTTPie importing must be postponed till one of our fixtures is evaluated
# and patched a path to HTTPie configuration.
from httpie_credential_store import _keychain

return _keychain.SystemKeychain()
return SystemKeychain()


def test_secret_retrieved(testkeychain, keyring_backend):
def test_secret_retrieved(
testkeychain: SystemKeychain,
keyring_backend: keyring.backend.KeyringBackend,
) -> None:
"""The keychain returns stored secret, no bullshit."""

keyring_backend.set_password("testsvc", "testuser", "p@ss")
assert testkeychain.get(service="testsvc", username="testuser") == "p@ss"


def test_secret_not_found(testkeychain):
def test_secret_not_found(testkeychain: SystemKeychain) -> None:
"""LookupError is raised when no secrets are found in the keychain."""

with pytest.raises(LookupError) as excinfo:
Expand All @@ -66,7 +72,12 @@ def test_secret_not_found(testkeychain):
pytest.param(["testsvc"], {"username": "testuser"}, id="args-kwargs"),
],
)
def test_keywords_only_arguments(testkeychain, keyring_backend, args, kwargs):
def test_keywords_only_arguments(
testkeychain: SystemKeychain,
keyring_backend: keyring.backend.KeyringBackend,
args: typing.List[str],
kwargs: typing.Mapping[str, str],
) -> None:
keyring_backend.set_password("testsvc", "testuser", "p@ss")

with pytest.raises(TypeError):
Expand Down
Loading

0 comments on commit fd35ef6

Please sign in to comment.