urban-meal-delivery/tests/test_version.py
Alexander Hess 9fc5b4816a
Add a testing tool chain
- use pytest as the base, measure coverage with pytest-cov
  + configure coverage to include branches and specify source locations
  + configure pytest to enforce explicit markers
- add a package for the test suite under tests/
- add a `__version__` identifier at the package's root
  + it is dynamically assigned the version of the installed package
  + the version is PEP440 compliant and follows a strict subset of
    semantic versioning: x.y.z[.devN] where x, y, z, and N are all
    non-negative integers
  + add module with tests for the __version__
- add a nox session "test" that runs the test suite
- use flake8 to lint pytest for consistent style
2020-08-04 00:09:29 +02:00

116 lines
3.4 KiB
Python

"""Test the package's version identifier.
This packaged version identifier must adhere to PEP440
and a strict subset of semantic versioning:
- version identifiers must follow the x.y.z format
where x.y.z are non-negative integers
- non-final versions are only allowed with a .devN suffix
where N is also a non-negative integer
"""
import re
import pytest
from packaging import version as pkg_version
from packaging.version import Version
import urban_meal_delivery
@pytest.fixture
def parsed_version() -> str:
"""The packaged version."""
return pkg_version.Version(urban_meal_delivery.__version__) # noqa:WPS609
class TestPEP404Compliance:
"""Packaged version identifier is PEP440 compliant."""
# pylint:disable=no-self-use
def test_parsed_version_has_no_epoch(self, parsed_version: Version) -> None:
"""PEP440 compliant subset of semantic versioning: no epoch."""
assert parsed_version.epoch == 0
def test_parsed_version_is_non_local(self, parsed_version: Version) -> None:
"""PEP440 compliant subset of semantic versioning: no local version."""
assert parsed_version.local is None
def test_parsed_version_is_no_post_release(self, parsed_version: Version) -> None:
"""PEP440 compliant subset of semantic versioning: no post releases."""
assert parsed_version.is_postrelease is False
def test_parsed_version_is_all_public(self, parsed_version: Version) -> None:
"""PEP440 compliant subset of semantic versioning: all public parts."""
assert parsed_version.public == urban_meal_delivery.__version__ # noqa:WPS609
class TestSemanticVersioning:
"""Packaged version follows a strict subset of semantic versioning."""
# pylint:disable=no-self-use
version_pattern = re.compile(
r'^(0|([1-9]\d*))\.(0|([1-9]\d*))\.(0|([1-9]\d*))(\.dev(0|([1-9]\d*)))?$',
)
def test_version_is_semantic(self) -> None:
"""Packaged version follows semantic versioning."""
result = self.version_pattern.fullmatch(
urban_meal_delivery.__version__, # noqa:WPS609
)
assert result is not None
# The next two test cases are sanity checks to validate the version_pattern.
@pytest.mark.parametrize(
'version',
[
'0.1.0',
'1.0.0',
'1.2.3',
'1.23.456',
'123.4.56',
'10.11.12',
'1.2.3.dev0',
'1.2.3.dev1',
'1.2.3.dev10',
],
)
def test_valid_semantic_versioning(self, version: str) -> None:
"""Versions follow the x.y.z or x.y.z.devN format."""
result = self.version_pattern.fullmatch(version)
assert result is not None
@pytest.mark.parametrize(
'version',
[
'1',
'1.2',
'-1.2.3',
'01.2.3',
'1.02.3',
'1.2.03',
'1.2.3.4',
'1.2.3.abc',
'1.2.3-dev0',
'1.2.3+dev0',
'1.2.3.d0',
'1.2.3.develop0',
'1.2.3.dev-1',
'1.2.3.dev01',
'1.2.3..dev0',
'1-2-3',
'1,2,3',
'1..2.3',
'1.2..3',
],
)
def test_invalid_semantic_versioning(self, version: str) -> None:
"""Versions follow the x.y.z or x.y.z.devN format."""
result = self.version_pattern.fullmatch(version)
assert result is None