Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change: switch to new test data loader based on tests.common.tdc #177

Merged
merged 12 commits into from
May 21, 2024
Merged
57 changes: 46 additions & 11 deletions tests/backend/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,81 @@
r"""Common functions for test cases of loaders and dumpers."""
from __future__ import annotations

import importlib
import pathlib
import re
import typing

import anyconfig.ioinfo
import pytest

from .. import common


NAMES: tuple[str, ...] = ("ipath", "opts", "exp")
PATH_PATTERN: re.Pattern = re.compile(
r".+[/\\:\.]test_([^_]+)_([^_]+).py"
)


def get_test_resdir(
testfile: str,
is_loader: bool = True,
pattern: re.Pattern = PATH_PATTERN
) -> pathlib.Path:
"""Get test resource dir for given test file path.
def get_name(testfile: str, pattern: re.Pattern = PATH_PATTERN) -> str:
"""Get the name of backend module.

ex. tests/backend/loaders/json/test_json_stdlib.py
-> tests/res/1/loaders/json.stdlib/
-> "json.stdlib"
"""
match = pattern.match(testfile)
if not match:
raise NameError(
f"Filename does not match expected pattern: {testfile}"
)

name = ".".join(match.groups())
subdir = "loaders" if is_loader else "dumpers"
return ".".join(match.groups())


def get_mod(testfile: str, pattern: re.Pattern = PATH_PATTERN):
"""Get the module to test."""
name = get_name(testfile, pattern=pattern)
mname = f"anyconfig.backend.{name}"
try:
return importlib.import_module(mname)
except ImportError:
pytest.skip(
f"Skip becuase it failed to import: {mname}",
allow_module_level=True
)

return None # To suppress inconsistent-return-statements.


def get_test_ids(*args, **opts):
return common.get_test_ids(*args, **opts)


def get_test_resdir(
testfile: str,
pattern: re.Pattern = PATH_PATTERN
) -> pathlib.Path:
"""Get test resource dir for given test file path.

ex. tests/backend/loaders/json/test_json_stdlib.py
-> tests/res/1/loaders/json.stdlib/
"""
subdir = pathlib.Path(testfile).parent.parent.name
name = get_name(testfile, pattern=pattern)

return common.RESOURCE_DIR / subdir / name


def load_data_for_testfile(
testfile: str,
is_loader: bool = True,
**opts
) -> list[tuple[pathlib.Path, dict[str, typing.Any], ...]]:
datadir = get_test_resdir(testfile, is_loader=is_loader)
datadir = get_test_resdir(testfile)
return common.load_data_for_testfile(
testfile, datadir=datadir, **opts
)


def ioinfo_from_path(path: pathlib.Path) -> anyconfig.ioinfo.IOInfo:
return anyconfig.ioinfo.make(path)
70 changes: 37 additions & 33 deletions tests/backend/dumpers/json/test_json_stdlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,57 @@
# Copyright (C) 2012 - 2024 Satoru SATOH <satoru.satoh gmail.com>
# SPDX-License-Identifier: MIT
#
# pylint: disable=missing-docstring,invalid-name,too-few-public-methods
# pylint: disable=ungrouped-imports
"""Test cases for the loader.
"""
# pylint: disable=missing-docstring
"""Test cases for the dumpers."""
from __future__ import annotations

import pathlib
import typing

import pytest

import tests.common.tdi_base
import tests.common.dumper
from ... import common

if typing.TYPE_CHECKING:
import pathlib

class TDI(tests.common.tdi_base.TDI):
_cid = tests.common.tdi_base.name_from_path(__file__)
_is_loader = False


(TT, DATA, DATA_IDS) = TDI().get_all()

if TT is None:
try:
DATA = common.load_data_for_testfile(__file__, load_idata=True)
except FileNotFoundError:
pytest.skip(
f"skipping tests: {TDI().cid()} as it's not available.",
f"Not found test data for: {__file__}",
allow_module_level=True
)

assert DATA
NAMES: tuple[str, ...] = ("ipath", "idata", "opts", "exp")
DATA_IDS: list[str] = common.get_test_ids(DATA)
Parser = getattr(common.get_mod(__file__), "Parser", None)

assert Parser is not None

class TestCase(tests.common.dumper.TestCase):
psr_cls = TT.Parser

@pytest.mark.parametrize(
("ipath", "aux"), DATA, ids=DATA_IDS,
)
def test_dumps(
self, ipath: pathlib.Path, aux: dict[str, typing.Any],
):
self._assert_dumps(ipath, aux)
@pytest.mark.parametrize(NAMES, DATA, ids=DATA_IDS)
def test_dumps(ipath: str, idata, opts: dict, exp: str) -> None:
psr = Parser()
content = psr.dumps(idata, **opts)

@pytest.mark.parametrize(
("ipath", "aux"), DATA, ids=DATA_IDS,
)
def test_dump(
self, ipath: pathlib.Path, aux: dict[str, typing.Any],
tmp_path: pathlib.Path
):
self._assert_dump(ipath, aux, tmp_path)
assert psr.loads(content, **opts) == idata
assert content == exp


@pytest.mark.parametrize(NAMES, DATA, ids=DATA_IDS)
def test_dump(
ipath: str, idata, opts: dict, exp: str, tmp_path: pathlib.Path
) -> None:
psr = Parser()

opath = tmp_path / f"{ipath.stem}.{psr.extensions()[0]}"
ioi = common.ioinfo_from_path(opath)

psr.dump(idata, ioi, **opts)

assert opath.exists()
assert psr.load(ioi, **opts) == idata

content = psr.ropen(str(opath)).read()
assert content == exp
73 changes: 41 additions & 32 deletions tests/backend/dumpers/toml/test_toml_tomllib.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,61 @@
# Copyright (C) 2012 - 2024 Satoru SATOH <satoru.satoh gmail.com>
# SPDX-License-Identifier: MIT
#
# pylint: disable=missing-docstring,invalid-name,too-few-public-methods
# pylint: disable=ungrouped-imports
"""Test cases for the loader.
"""
import pathlib
# pylint: disable=missing-docstring
"""Test cases for the dumper."""
from __future__ import annotations

import typing

import pytest

import tests.common.tdi_base
import tests.common.dumper
from ... import common

if typing.TYPE_CHECKING:
import pathlib

class TDI(tests.common.tdi_base.TDI):
_cid = tests.common.tdi_base.name_from_path(__file__)
_is_loader = False

try:
DATA = common.load_data_for_testfile(__file__, load_idata=True)
except FileNotFoundError:
pytest.skip(
f"Not found test data for: {__file__}",
allow_module_level=True
)

(TT, DATA, DATA_IDS) = TDI().get_all()
NAMES: tuple[str, ...] = ("ipath", "idata", "opts", "exp")
DATA_IDS: list[str] = common.get_test_ids(DATA)
Parser = getattr(common.get_mod(__file__), "Parser", None)

if TT is None:
if Parser is None:
pytest.skip(
f"skipping tests: {TDI().cid()} as it's not available.",
f"Skip test cases: {__file__}",
allow_module_level=True
)

assert DATA

@pytest.mark.parametrize(NAMES, DATA, ids=DATA_IDS)
def test_dumps(ipath: str, idata, opts: dict, exp: str) -> None:
psr = Parser()
content = psr.dumps(idata, **opts)

class TestCase(tests.common.dumper.TestCase):
psr_cls = TT.Parser
exact_match = False
assert psr.loads(content, **opts) == idata
# assert content == exp # This may fail.

@pytest.mark.parametrize(
("ipath", "aux"), DATA, ids=DATA_IDS,
)
def test_dumps(
self, ipath: pathlib.Path, aux: dict[str, typing.Any],
):
self._assert_dumps(ipath, aux)

@pytest.mark.parametrize(
("ipath", "aux"), DATA, ids=DATA_IDS,
)
def test_dump(
self, ipath: pathlib.Path, aux: dict[str, typing.Any],
tmp_path: pathlib.Path
):
self._assert_dump(ipath, aux, tmp_path)
@pytest.mark.parametrize(NAMES, DATA, ids=DATA_IDS)
def test_dump(
ipath: str, idata, opts: dict, exp: str, tmp_path: pathlib.Path
) -> None:
psr = Parser()

opath = tmp_path / f"{ipath.stem}.{psr.extensions()[0]}"
ioi = common.ioinfo_from_path(opath)

psr.dump(idata, ioi, **opts)

assert opath.exists()
assert psr.load(ioi, **opts) == idata

# content = psr.ropen(str(opath)).read().decode("utf-8")
# assert content == exp # This may fail.
57 changes: 23 additions & 34 deletions tests/backend/loaders/json/test_json_stdlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,40 @@
# Copyright (C) 2012 - 2024 Satoru SATOH <satoru.satoh gmail.com>
# SPDX-License-Identifier: MIT
#
# pylint: disable=missing-docstring,invalid-name,too-few-public-methods
# pylint: disable=ungrouped-imports
"""Test cases for the loader.
"""
# pylint: disable=missing-docstring,invalid-name
"""Test cases for the loader."""
from __future__ import annotations

import pathlib
import typing

import pytest

import tests.common.tdi_base
import tests.common.loader


class TDI(tests.common.tdi_base.TDI):
_cid = tests.common.tdi_base.name_from_path(__file__)
from ... import common


(TT, DATA, DATA_IDS) = TDI().get_all()

if TT is None:
try:
DATA = common.load_data_for_testfile(__file__)
except FileNotFoundError:
pytest.skip(
f"skipping tests: {TDI().cid()} as it's not available.",
f"Not found test data for: {__file__}",
allow_module_level=True
)

assert DATA
DATA_IDS: list[str] = common.get_test_ids(DATA)
Parser = getattr(common.get_mod(__file__), "Parser", None)

assert Parser is not None

class TestCase(tests.common.loader.TestCase):
psr_cls = TT.Parser

@pytest.mark.parametrize(
("ipath", "aux"), DATA, ids=DATA_IDS,
)
def test_loads(
self, ipath: pathlib.Path, aux: dict[str, typing.Any]
):
self._assert_loads(ipath, aux)
@pytest.mark.parametrize(common.NAMES, DATA, ids=DATA_IDS)
def test_loads(ipath: str, opts: dict, exp) -> None:
psr = Parser()
content = psr.ropen(ipath).read()

@pytest.mark.parametrize(
("ipath", "aux"), DATA, ids=DATA_IDS,
)
def test_load(
self, ipath: pathlib.Path, aux: dict[str, typing.Any]
):
self._assert_load(ipath, aux)
assert psr.loads(content, **opts) == exp


@pytest.mark.parametrize(common.NAMES, DATA, ids=DATA_IDS)
def test_load(ipath: str, opts: dict, exp) -> None:
psr = Parser()
ioi = common.ioinfo_from_path(ipath)

assert psr.load(ioi, **opts) == exp
Loading