summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2020-05-16 10:04:53 +0300
committerLars Wirzenius <liw@liw.fi>2020-05-17 12:11:02 +0300
commitf276c028dd4869a97129140cea28f02f3889ac47 (patch)
treef354dde229b1cd41e75e3aaa76c9487766bce7c6
parent0402565f12623fb56da54e9a9a764edb39129186 (diff)
downloadsubplot-f276c028dd4869a97129140cea28f02f3889ac47.tar.gz
feat(subplot.md): add acceptance criteria for cleanup functionality
Add acceptance checks for the cleanup functionality, for Python and Bash templates.
-rw-r--r--subplot.md185
-rw-r--r--subplot.py30
-rw-r--r--subplot.yaml16
3 files changed, 225 insertions, 6 deletions
diff --git a/subplot.md b/subplot.md
index 05b9341..f0dfa9b 100644
--- a/subplot.md
+++ b/subplot.md
@@ -691,6 +691,191 @@ then bar was done
~~~~
+## Automatic cleanup in scenarios
+
+A binding can define a cleanup function, which gets called at the end
+of the scenario in reverse order for the successful steps. If a step
+fails, all the cleanups for the successful steps are still called. We
+test this for every language templat we support.
+
+~~~{#cleanup.yaml .file .yaml .numberLines}
+- given: foo
+ function: foo
+ cleanup: foo_cleanup
+- given: bar
+ function: bar
+ cleanup: bar_cleanup
+- given: failure
+ function: failure
+ cleanup: failure_cleanup
+~~~
+
+~~~{#cleanup.py .file .python .numberLines}
+def foo(ctx):
+ pass
+def foo_cleanup(ctx):
+ pass
+def bar(ctx):
+ pass
+def bar_cleanup(ctx):
+ pass
+def failure(ctx):
+ assert 0
+def failure_cleanup(ctx):
+ pass
+~~~
+
+~~~{#cleanup.sh .file .bash .numberLines}
+foo() {
+ true
+}
+foo_cleanup() {
+ true
+}
+bar() {
+ true
+}
+bar_cleanup() {
+ true
+}
+failure() {
+ return 1
+}
+failure_cleanup() {
+ true
+}
+~~~
+
+
+### Cleanup functions gets called on success (Python)
+
+~~~scenario
+given file cleanup-success-python.md
+and file cleanup.yaml
+and file cleanup.py
+when I run sp-codegen --run cleanup-success-python.md -o test.py
+then scenario "Cleanup" was run
+and step "given foo" was run, and then step "given bar"
+and cleanup for "given bar" was run, and then for "given foo"
+and program finished successfully
+~~~
+
+
+~~~~~{#cleanup-success-python.md .file .markdown .numberLines}
+---
+title: Cleanup
+bindings: cleanup.yaml
+functions: cleanup.py
+template: python
+...
+
+# Cleanup
+
+~~~scenario
+given foo
+given bar
+~~~
+~~~~~
+
+
+### Cleanup functions get called on failure (Python)
+
+~~~scenario
+given file cleanup-fail-python.md
+and file cleanup.yaml
+and file cleanup.py
+when I try to run sp-codegen --run cleanup-fail-python.md -o test.py
+then scenario "Cleanup" was run
+and step "given foo" was run, and then step "given bar"
+and cleanup for "given bar" was run, and then for "given foo"
+and cleanup for "given failure" was not run
+and exit code is non-zero
+~~~
+
+~~~~~{#cleanup-fail-python.md .file .markdown .numberLines}
+---
+title: Cleanup
+bindings: cleanup.yaml
+functions: cleanup.py
+template: python
+...
+
+# Cleanup
+
+~~~scenario
+given foo
+given bar
+given failure
+~~~
+~~~~~
+
+
+### Cleanup functions gets called on success (Bash)
+
+~~~scenario
+given file cleanup-success-bash.md
+and file cleanup.yaml
+and file cleanup.sh
+when I run sp-codegen --run cleanup-success-bash.md -o test.sh
+then scenario "Cleanup" was run
+and step "given foo" was run, and then step "given bar"
+and cleanup for "given bar" was run, and then for "given foo"
+and program finished successfully
+~~~
+
+~~~~~{#cleanup-success-bash.md .file .markdown .numberLines}
+---
+title: Cleanup
+bindings: cleanup.yaml
+functions: cleanup.sh
+template: bash
+...
+
+# Cleanup
+
+~~~scenario
+given foo
+given bar
+~~~
+~~~~~
+
+
+### Cleanup functions get called on failure (Bash)
+
+If a step fails, all the cleanups for the preceding steps are still
+called, in reverse order.
+
+~~~scenario
+given file cleanup-fail-bash.md
+and file cleanup.yaml
+and file cleanup.sh
+when I try to run sp-codegen --run cleanup-fail-bash.md -o test.sh
+then scenario "Cleanup" was run
+and step "given foo" was run, and then step "given bar"
+and cleanup for "given bar" was run, and then for "given foo"
+and cleanup for "given failure" was not run
+and exit code is non-zero
+~~~
+
+~~~~~{#cleanup-fail-bash.md .file .markdown .numberLines}
+---
+title: Cleanup
+bindings: cleanup.yaml
+functions: cleanup.sh
+template: bash
+...
+
+# Cleanup
+
+~~~scenario
+given foo
+given bar
+given failure
+~~~
+~~~~~
+
+
+
## Capturing parts of steps for functions
A scenario step binding can capture parts of a scenario step, to be
diff --git a/subplot.py b/subplot.py
index 1495553..e586b53 100644
--- a/subplot.py
+++ b/subplot.py
@@ -35,14 +35,14 @@ def run_docgen_with_date(ctx, md=None, output=None, date=None):
exit_code_zero(ctx)
-def try_codegen_and_program(ctx, filename=None):
+def try_codegen_and_program(ctx, filename=None, testprog=None):
codegen = binary("sp-codegen")
tmpldir = os.path.join(srcdir, "templates")
- runcmd(ctx, [codegen, filename, "-o", "test.py", "--run", "--templates", tmpldir])
+ runcmd(ctx, [codegen, filename, "-o", testprog, "--run", "--templates", tmpldir])
-def run_codegen_and_program(ctx, filename=None):
- try_codegen_and_program(ctx, filename=filename)
+def run_codegen_and_program(ctx, filename=None, testprog=None):
+ try_codegen_and_program(ctx, filename=filename, testprog=testprog)
exit_code_zero(ctx)
@@ -111,6 +111,28 @@ def step_was_run(ctx, keyword=None, name=None):
stdout_matches(ctx, pattern="\n step: {} {}\n".format(keyword, name))
+def step_was_run_and_then(ctx, keyword1=None, name1=None, keyword2=None, name2=None):
+ stdout_matches(
+ ctx,
+ pattern="\n step: {} {}\n step: {} {}".format(
+ keyword1, name1, keyword2, name2
+ ),
+ )
+
+
+def cleanup_was_run(ctx, keyword1=None, name1=None, keyword2=None, name2=None):
+ stdout_matches(
+ ctx,
+ pattern="\n cleanup: {} {}\n cleanup: {} {}\n".format(
+ keyword1, name1, keyword2, name2
+ ),
+ )
+
+
+def cleanup_was_not_run(ctx, keyword=None, name=None):
+ stdout_does_not_match(ctx, pattern="\n cleanup: {} {}\n".format(keyword, name))
+
+
def exit_code_zero(ctx):
if ctx.get("exit") != 0:
print("context:", ctx.as_dict())
diff --git a/subplot.yaml b/subplot.yaml
index 607e361..8d4187f 100644
--- a/subplot.yaml
+++ b/subplot.yaml
@@ -17,13 +17,13 @@
- when: I try to run sp-docgen {md} -o {output}
function: try_docgen
-- when: I run sp-codegen --run {filename} -o test.py
+- when: I run sp-codegen --run {filename} -o {testprog}
function: run_codegen_and_program
- when: I run sp-codegen {filename} -o {testprog}
function: run_codegen
-- when: I try to run sp-codegen --run {filename} -o test.py
+- when: I try to run sp-codegen --run {filename} -o {testprog}
function: try_codegen_and_program
- when: I run python3 {testprog} {pattern}
@@ -84,6 +84,18 @@
function: step_was_run
regex: true
+- then: step "(?P<keyword1>given|when|then) (?P<name1>.+)" was run, and then step "(?P<keyword2>given|when|then) (?P<name2>.+)"
+ function: step_was_run_and_then
+ regex: true
+
+- then: cleanup for "(?P<keyword1>given|when|then) (?P<name1>.+)" was run, and then for "(?P<keyword2>given|when|then) (?P<name2>.+)"
+ function: cleanup_was_run
+ regex: true
+
+- then: cleanup for "(?P<keyword>given|when|then) (?P<name>.+)" was not run
+ function: cleanup_was_not_run
+ regex: true
+
- then: program finished successfully
function: exit_code_zero