From c1f4384d9bc811f6b55e2df31d5f64db01aab6dc Mon Sep 17 00:00:00 2001 From: Eduardo Blancas Reyes Date: Sun, 2 Jan 2022 18:33:48 -0600 Subject: [PATCH] adds testing.docker module to test docker tutorials --- src/pkgmt/cli.py | 2 +- src/pkgmt/testing/docker.py | 73 +++++++++++++++++++++++ src/pkgmt/testing/rst.py | 18 ++++-- tests/testing/test_docker.py | 108 +++++++++++++++++++++++++++++++++++ tests/testing/test_rst.py | 4 +- 5 files changed, 196 insertions(+), 9 deletions(-) create mode 100644 src/pkgmt/testing/docker.py create mode 100644 tests/testing/test_docker.py diff --git a/src/pkgmt/cli.py b/src/pkgmt/cli.py index 0e286cf..2a05c8f 100644 --- a/src/pkgmt/cli.py +++ b/src/pkgmt/cli.py @@ -32,7 +32,7 @@ def execute(path, output): """Execute rst files """ from pkgmt.testing import rst - code = rst.parse_from_path(path) + code = rst.to_script_from_path(path) if output: click.echo(f'Writing script to {output}') diff --git a/src/pkgmt/testing/docker.py b/src/pkgmt/testing/docker.py new file mode 100644 index 0000000..e234341 --- /dev/null +++ b/src/pkgmt/testing/docker.py @@ -0,0 +1,73 @@ +""" +Testing rst files that call "docker run" +""" +from pathlib import Path + +from pkgmt.testing import rst + +_template = """\ +# exit on error and print each command +set -e +set -x +ROOT=$(pwd) + +{code}\ +""" + + +# NOTE: should I modify the command to have the --rm flag? +def _find_docker_run_idx(snippets): + for i, snippet in enumerate(snippets): + if 'docker run' in snippet: + return i + + raise ValueError('Did not find "docker run" command') + + +def _patch_docker_run(snippet): + lines = snippet.splitlines() + idx = None + + for i, line in enumerate(lines): + if line.startswith('docker run'): + idx = i + + if idx is None: + raise ValueError('Failed to find a line starting with ' + f'"docker run", got lines: {lines}') + + docker_run_line = lines[idx] + + if '-t' not in docker_run_line: + raise ValueError('Expected -t flag to be in the "docker run"' + f' command, got: {docker_run_line!r}') + + # cd to $ROOT because the script may have some "cd" commands, and + # we're saving run-in-docker.sh in the initial working directory + lines[idx] = ('cd $ROOT && cat run-in-docker.sh | ' + + docker_run_line.replace('-t ', '')) + + return '\n'.join(lines) + + +def to_script(text): + snippets = rst.to_snippets(text) + + idx = _find_docker_run_idx(snippets) + + pre, post = snippets[:idx + 1], snippets[idx + 1:] + + return pre, post + + +def to_testing_files(text): + pre, post = to_script(text) + pre[-1] = _patch_docker_run(pre[-1]) + + Path('test.sh').write_text(_template.format(code='\n\n'.join(pre))) + Path('run-in-docker.sh').write_text( + _template.format(code='\n\n'.join(post))) + + +def to_testing_files_from_path(path): + to_testing_files(Path(path).read_text()) diff --git a/src/pkgmt/testing/rst.py b/src/pkgmt/testing/rst.py index af3aee4..cbfe2b2 100644 --- a/src/pkgmt/testing/rst.py +++ b/src/pkgmt/testing/rst.py @@ -34,11 +34,11 @@ """ -def parse_from_path(path): - return parse(Path(path).read_text()) +def to_script_from_path(path): + return to_script(Path(path).read_text()) -def parse(content): +def to_snippets(text): # maybe use sphinx's parser - it should be configured with the custom # directives doc = new_document('doc.rst') @@ -46,7 +46,7 @@ def parse(content): doc.settings.rfc_references = None # doc.settings.tab_width = None - _parser.parse(content, doc) + _parser.parse(text, doc) elements = doc.traverse() @@ -70,12 +70,18 @@ def previous_not_comment(idx, elements): return prev.astext() == 'skip-next' snippets = [ - s for i, s in enumerate(selected) + s.astext() for i, s in enumerate(selected) if not previous_not_comment(i, selected) and not isinstance(s, nodes.comment) ] - code_user = '\n\n'.join(s.astext() for s in snippets) + return snippets + + +def to_script(text): + snippets = to_snippets(text) + + code_user = '\n\n'.join(snippets) code_script = _template.format(code=code_user) return code_script diff --git a/tests/testing/test_docker.py b/tests/testing/test_docker.py new file mode 100644 index 0000000..3ee1b9c --- /dev/null +++ b/tests/testing/test_docker.py @@ -0,0 +1,108 @@ +from pathlib import Path + +import pytest + +from pkgmt.testing import docker + +simple_in = """\ + +Some text + +.. code-block:: bash + + git clone some-repository + cd some-repository + +.. code-block:: bash + + docker run -i -t some-image /bin/bash + +.. code-block:: sh + + echo 'hello from docker' + +""" + +simple_test = """\ +# exit on error and print each command +set -e +set -x +ROOT=$(pwd) + +git clone some-repository +cd some-repository + +cd $ROOT && cat run-in-docker.sh | docker run -i some-image /bin/bash\ +""" + +simple_run_in_docker = """\ +# exit on error and print each command +set -e +set -x +ROOT=$(pwd) + +echo 'hello from docker'\ +""" + +multicommand_in = """\ + +.. code-block:: bash + + git clone some-repository + cd some-repository + +.. code-block:: bash + + echo hello + docker run -i -t some-image /bin/bash + +.. code-block:: sh + + echo 'hello from docker' + +""" + +multicommand_test = """\ +# exit on error and print each command +set -e +set -x +ROOT=$(pwd) + +git clone some-repository +cd some-repository + +echo hello +cd $ROOT && cat run-in-docker.sh | docker run -i some-image /bin/bash\ +""" + +multicommand_run_in_docker = """\ +# exit on error and print each command +set -e +set -x +ROOT=$(pwd) + +echo 'hello from docker'\ +""" + + +def test_to_script(): + pre, post = docker.to_script(simple_in) + assert pre == [ + 'git clone some-repository\ncd some-repository', + 'docker run -i -t some-image /bin/bash', + ] + assert post == ["echo 'hello from docker'"] + + +@pytest.mark.parametrize('in_, test, run_in_docker', [ + [simple_in, simple_test, simple_run_in_docker], + [multicommand_in, multicommand_test, multicommand_run_in_docker], +]) +def test_to_testing_files(tmp_empty, in_, test, run_in_docker): + docker.to_testing_files(in_) + + test_out = Path('test.sh').read_text() + run_in_docker_out = Path('run-in-docker.sh').read_text() + + assert test_out == test + assert run_in_docker_out == run_in_docker diff --git a/tests/testing/test_rst.py b/tests/testing/test_rst.py index 1b48b5c..66e3939 100644 --- a/tests/testing/test_rst.py +++ b/tests/testing/test_rst.py @@ -56,5 +56,5 @@ [simple_in, simple_out], [skip_in, skip_out], ]) -def test_parse(in_, out): - assert rst.parse(in_) == out +def test_to_script(in_, out): + assert rst.to_script(in_) == out