From 499b8587a86dadc9ed1b2953fc945f6f54b9fadb Mon Sep 17 00:00:00 2001 From: Yves Chevallier Date: Wed, 9 Oct 2024 13:27:59 +0200 Subject: [PATCH] Add doctests, coverage now 89% --- CHANGES.md | 1 + baygon/executable.py | 3 +- baygon/helpers.py | 39 +++++++++++++++++++++ baygon/str.py | 13 ------- pyproject.toml | 33 +++++++++++++---- tests/click/{add.py => add.exe.py} | 0 tests/click/foo.yaml | 8 +++++ tests/click/ignorespaces.yml | 2 +- tests/click/{main.py => main.exe.py} | 0 tests/click/points.yml | 21 +++++++++++ tests/click/test_click.py | 2 +- tests/executable/{args.py => args.exe.py} | 0 tests/executable/{dummy.py => dummy.exe.py} | 0 tests/executable/test_executable.py | 10 +++--- tests/full/__init__.py | 2 +- tests/full/{main.py => main.exe.py} | 0 16 files changed, 105 insertions(+), 29 deletions(-) delete mode 100644 baygon/str.py rename tests/click/{add.py => add.exe.py} (100%) create mode 100644 tests/click/foo.yaml rename tests/click/{main.py => main.exe.py} (100%) create mode 100644 tests/click/points.yml rename tests/executable/{args.py => args.exe.py} (100%) rename tests/executable/{dummy.py => dummy.exe.py} (100%) rename tests/full/{main.py => main.exe.py} (100%) diff --git a/CHANGES.md b/CHANGES.md index 87a281a..31e7792 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - '4 failed, 0 passed (0.0%% ok).' remove the duplicated pecentage sign - Fix output by adding quotes and `(empty)` for empty strings +- More tests (89% coverage), enabled doctests ### Deprecated diff --git a/baygon/executable.py b/baygon/executable.py index 8ad325f..6d3e154 100644 --- a/baygon/executable.py +++ b/baygon/executable.py @@ -34,11 +34,12 @@ class Executable: For example: >>> e = Executable('echo') + >>> e Executable >>> e('-n', 'Hello World') Outputs(exit_status=0, stdout='Hello World', stderr='') >>> e('-n', 'Hello World').stdout - 'Hello World!' + 'Hello World' """ def __new__(cls, filename): diff --git a/baygon/helpers.py b/baygon/helpers.py index 68a1b20..e7fbeef 100644 --- a/baygon/helpers.py +++ b/baygon/helpers.py @@ -1,10 +1,49 @@ +import re import shlex def escape_argument(arg): + """Escape a command line argument. + + >>> print(escape_argument("hello")) + hello + >>> print(escape_argument("hello world")) + 'hello world' + >>> print(escape_argument("hello'world'")) + 'hello'"'"'world'"'"'' + """ return shlex.quote(arg) def create_command_line(args): + """Create a command line from a list of arguments. + + >>> print(create_command_line(["echo", "hello world"])) + echo 'hello world' + """ escaped_args = [escape_argument(str(arg)) for arg in args] return " ".join(escaped_args) + + +class GreppableString(str): + """A string that can be parsed with regular expressions.""" + + def grep(self, pattern: str, *args) -> bool: + """Return True if the pattern is found in the string. + + >>> GreppableString("hello world").grep("w.{3}d") + ['world'] + >>> GreppableString("hello world").grep(r"\b[a-z]{4}\b") + [] + """ + return re.findall(pattern, self, *args) + + def contains(self, value: str) -> bool: + """Return True if the value is found in the string. + + >>> GreppableString("hello world").contains("world") + True + >>> GreppableString("hello world").contains("earth") + False + """ + return value in self diff --git a/baygon/str.py b/baygon/str.py deleted file mode 100644 index cf6ae81..0000000 --- a/baygon/str.py +++ /dev/null @@ -1,13 +0,0 @@ -import re - - -class GreppableString(str): - """A string that can be parsed with regular expressions.""" - - def grep(self, pattern: str, *args) -> bool: - """Return True if the pattern is found in the string.""" - return re.findall(pattern, self, *args) - - def contains(self, value: str) -> bool: - """Return True if the value is found in the string.""" - return value in self diff --git a/pyproject.toml b/pyproject.toml index 57ba2da..29dc7ee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,9 +35,21 @@ classifiers = [ "Topic :: Software Development :: Testing", "Topic :: Software Development :: Libraries", ] -exclude = [".editorconfig", "baygon/version.py", ".gitignore", - ".eggs", ".env", ".tox", ".vscode", ".vscode/settings.json", - "*.pyc", "*~", ".DS_Store", "__pycache__", "*.pyo", "node_modules" +exclude = [ + ".editorconfig", + "baygon/version.py", + ".gitignore", + ".eggs", + ".env", + ".tox", + ".vscode", + ".vscode/settings.json", + "*.pyc", + "*~", + ".DS_Store", + "__pycache__", + "*.pyo", + "node_modules", ] [tool.poetry.urls] @@ -60,7 +72,7 @@ black = "^24.10.0" tox = "^4.21.2" [tool.check-manifest] -ignore = [ "node_modules/*",] +ignore = ["node_modules/*"] [tool.poetry.scripts] baygon = "baygon.__main__:cli" @@ -76,8 +88,15 @@ select = ["E", "F", "W", "C", "I"] line-length = 88 [tool.pytest.ini_options] -testpaths = "tests" +testpaths = "baygon tests" +timeout = 2 python_files = "test_*.py" python_classes = "Test*" -norecursedirs = [ ".git", "_build",] -addopts = "--cov=baygon --cov-report term --cov-report xml --cov-fail-under=85" +norecursedirs = [".git", "_build"] +addopts = ''' + --doctest-modules + --ignore-glob='*.exe.py' + --cov=baygon --cov-report + term --cov-report + xml --cov-fail-under=85 +''' diff --git a/tests/click/add.py b/tests/click/add.exe.py similarity index 100% rename from tests/click/add.py rename to tests/click/add.exe.py diff --git a/tests/click/foo.yaml b/tests/click/foo.yaml new file mode 100644 index 0000000..518df25 --- /dev/null +++ b/tests/click/foo.yaml @@ -0,0 +1,8 @@ +failures: 2 +points: + earned: 4 + total: 10 +skipped: 0 +successes: 2 +time: 0.03 +total: 4 diff --git a/tests/click/ignorespaces.yml b/tests/click/ignorespaces.yml index 76e926f..9c33e08 100644 --- a/tests/click/ignorespaces.yml +++ b/tests/click/ignorespaces.yml @@ -4,6 +4,6 @@ filters: tests: - name: Stdout is the spaces are removed args: [4, 5] - executable: add.py + executable: add.exe.py stdout: - contains: "a+b=4+5" diff --git a/tests/click/main.py b/tests/click/main.exe.py similarity index 100% rename from tests/click/main.py rename to tests/click/main.exe.py diff --git a/tests/click/points.yml b/tests/click/points.yml new file mode 100644 index 0000000..f55aeb2 --- /dev/null +++ b/tests/click/points.yml @@ -0,0 +1,21 @@ +version: 1 +executable: ./main.exe.py +filters: + trim: true +tests: + - name: Foo + args: [4, 0] + stdout: [ equals: 4 ] + points: 1 + - name: Bar + args: [8, 0] + stdout: [ equals: 2 ] + points: 2 + - name: Baz + args: [15, 0] + stdout: [ equals: 15 ] + points: 3 + - name: Qux + args: [16, 0] + stdout: [ equals: 42 ] + points: 4 diff --git a/tests/click/test_click.py b/tests/click/test_click.py index 318096b..1f7f2fa 100644 --- a/tests/click/test_click.py +++ b/tests/click/test_click.py @@ -25,7 +25,7 @@ def directory(self): @property def executable(self): - return str(self.directory.joinpath("main.py")) + return str(self.directory.joinpath("main.exe.py")) def get_config(self, name): return self.directory.joinpath(name) diff --git a/tests/executable/args.py b/tests/executable/args.exe.py similarity index 100% rename from tests/executable/args.py rename to tests/executable/args.exe.py diff --git a/tests/executable/dummy.py b/tests/executable/dummy.exe.py similarity index 100% rename from tests/executable/dummy.py rename to tests/executable/dummy.exe.py diff --git a/tests/executable/test_executable.py b/tests/executable/test_executable.py index 4377fe9..cac4694 100644 --- a/tests/executable/test_executable.py +++ b/tests/executable/test_executable.py @@ -4,7 +4,7 @@ from baygon import Executable from baygon.error import InvalidExecutableError -from baygon.str import GreppableString +from baygon.helpers import GreppableString dir_path = Path(__file__).resolve(strict=True).parent @@ -21,13 +21,13 @@ def test_arg(self): self.assertEqual(output.stdout, test_string) def test_stdout(self): - e = Executable(dir_path.joinpath("dummy.py")) + e = Executable(dir_path.joinpath("dummy.exe.py")) output = e.run() print(output) self.assertEqual(output.stdout, "an apple\n") def test_stderr(self): - e = Executable(dir_path.joinpath("dummy.py")) + e = Executable(dir_path.joinpath("dummy.exe.py")) output = e.run() print(output) self.assertEqual(output.stderr, "an orange\n") @@ -40,13 +40,13 @@ def test_stdin(self): self.assertEqual(output.stdout, test_string) def test_exit_status(self): - e = Executable(dir_path.joinpath("dummy.py")) + e = Executable(dir_path.joinpath("dummy.exe.py")) output = e.run() print(output) self.assertEqual(output.exit_status, 42) def test_args(self): - e = Executable(dir_path.joinpath("args.py")) + e = Executable(dir_path.joinpath("args.exe.py")) test_string = "foobar" output = e.run(2, test_string) print(output) diff --git a/tests/full/__init__.py b/tests/full/__init__.py index df1c5a4..12dcd27 100644 --- a/tests/full/__init__.py +++ b/tests/full/__init__.py @@ -9,7 +9,7 @@ class TestDemo(TestCase): def setUp(self): - self.exe = baygon.Executable(dir_path.joinpath("main.py")) + self.exe = baygon.Executable(dir_path.joinpath("main.exe.py")) def test_minimal(self): print(dir_path) diff --git a/tests/full/main.py b/tests/full/main.exe.py similarity index 100% rename from tests/full/main.py rename to tests/full/main.exe.py