diff options
author | Lars Wirzenius <liw@liw.fi> | 2021-05-16 08:32:46 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2021-05-16 13:13:44 +0300 |
commit | 562e790c4f43879075140c559efe4e3ae66a4239 (patch) | |
tree | 5708d2e8fa89ef14f4cdea4f08a2e22d807a2e38 /examples | |
parent | 68c94031260e9ddafd50418fe7f495a51cd7ad48 (diff) | |
download | subplot-562e790c4f43879075140c559efe4e3ae66a4239.tar.gz |
docs: add tutorial for verifying a web site
Diffstat (limited to 'examples')
-rw-r--r-- | examples/website/website.md | 185 | ||||
-rw-r--r-- | examples/website/website.py | 35 | ||||
-rw-r--r-- | examples/website/website.yaml | 12 |
3 files changed, 232 insertions, 0 deletions
diff --git a/examples/website/website.md b/examples/website/website.md new file mode 100644 index 0000000..89b94bb --- /dev/null +++ b/examples/website/website.md @@ -0,0 +1,185 @@ +# Introduction + +This is a tutorial for the Subplot software. It is aimed at people who +want to see what using Subplot is like. + +This tutorial walks you through how to use Subplot to verify that the +Subplot web site, `subplot.liw.fi`, works and has the right kind of +content. The full source code of the tutorial is part of the Subplot +source tree, and is checked every time the software changes. + +The source code for this tutorial is at +<https://gitlab.com/subplot/subplot/-/tree/main/examples/website>. You +need to read the source code to understand everything. + + +# Installing Subplot + +First, you need to [install][] Subplot. The web site has instructions. + + +# Acceptance criteria + +The fundamental acceptance criteria for the Subplot web site is that +it exists, talks about Subplot, and doesn't talk about Obnam, the +backup program. + +To use Subplot to verify that you need to write a document that +explains everything to all the people involved in the project. The +document will contain semi-formal _scenarios_ that document how a +program would verify the home works. For this tutorial, that document +is this document, [website.md][]. It uses [website.yaml][] for +bindings, and [website.py][] for step implementations. Consult the +source code for how to mark up scenarios and the other files. + +Each scenario is placed under its own heading. This makes it easy to +refer to each scenario. + +## Web page talks about Subplot + +This scenario verifies the Subplot home page exists and talks about +Subplot. + +~~~scenario +given website https://subplot.liw.fi +when I look at the front page +then it mentions "Subplot" +then it mentions "acceptance criteria" +then it mentions "verified" +~~~ + +## Doesn't talk about Obnam + +This scenario verifies the Subplot home page doesn't talk about Obnam, +the backup program. + +~~~scenario +given website https://subplot.liw.fi +when I look at the front page +then it doesn't contain "Obnam" +~~~ + + +# Using Subplot + +In order to follow along with this tutorial, you should +download [website.md][], [website.yaml][], and [website.py][]. + +## Generate typeset documents + +To generate typeset versions of this document, run the following +commands: + +~~~ +$ subplot docgen website.md --o website.html +$ subplot docgen website.md --o website.pdf +~~~ + +Open up the file to see what they look like. + +## Generate and run test program + +To generate and run a test program from this document, run the +following command: + +~~~ +$ subplot codegen website.md --o test.py +$ python3 test.py ---log test.log +srcdir /home/liw/pers/subplot/git/examples/website +datadir /tmp/tmp30hj6kvb +scenario: Doesn’t talk about Obnam + step: given website https://subplot.liw.fi + step: when I look at the front page + step: then it doesn't contain "Obnam" +scenario: Web page talks about Subplot + step: given website https://subplot.liw.fi + step: when I look at the front page + step: then it mentions "Subplot" + step: then it mentions "acceptance criteria" + step: then it mentions "verified" +OK, all scenarios finished successfully +$ +~~~ + +Assuming you get similar output, then you know that everything is +working. + +Open `test.py` and `test.log`. The log file is useful if a scenario fails. + + +## Some explanations + +The [website.yaml][] file has a list of bindings. Each binding uses +one of the key words (given, when, then) and a pattern, and also a +function name. The pattern can be fixed text, or it can extract parts +of the scenario step and pass those to the function. + +Patterns which capture and extract parts of the scenario stesp +have the form `{name}` for single words, or `{name:text}` +for multiple words. This allows for an easy way to, for example, use +the same step for different web sites. + +The generated test program will call each function, with extracted +values, in the appropriate order. If the function finishes +successfully, the step succeeds. If the function raises an exception, +the step fails. + +The `assert` statement is typically used to verify things in a +step function. For more useful error messages, Subplot provides the +functions `assert_eq` and `assert_ne` that can be used as well. + +Extracted parts of steps are passed to functions a keyword arguments. +Such arguments must exist, which is why you will typically see them +added as `name=None` in the function definition. + +Each step function also gets a dict-like "context" variable. A new, +empty context is created for each scenario. This allows data to be +passed conveniently between step functions. + + + +# Changing the document + +We now have minimal verification of the Subplot web site, but it can +be improved. One possible improvement would be to verify that there is +a sub-page with contact information for the project, and a blog. To +achieve this, you should make the following changes: + +* change the "given a website" step to be called "given a web page", + by changing the bindings file, and the markdown file; then re-run + the commands to generate documentation and test program, and re-run + the test program: it should still pass + +* also change the "when I look at the front page" to say "when I look + at the page"; then re-run all the commands again; these changes are + not functional, but it's important to make sure everything is easily + understood by all the people involved + +* add a scenario to verify that there is a page + `https://subplot.liw.fi/contact` and that it contains "Lars" and + "Daniel" + +* add a new step that verifies the page content type is `text/html`: + add to the relevant scenario a step "then it has a content type + text/html", and the corresponding binding to the YAML file, and a + new function to the Python file + + - you can get the content type from the return value of + `requests.get` as `r.headers["content-type"]` + + + + +[install]: https://subplot.liw.fi/download/ +[website.md]: https://gitlab.com/subplot/subplot/-/tree/main/examples/website/website.md +[website.yaml]: https://gitlab.com/subplot/subplot/-/tree/main/examples/website/website.yaml +[website.py]: https://gitlab.com/subplot/subplot/-/tree/main/examples/website/website.py + + +--- +title: Subplot website tutorial +author: The Subplot project +template: python +bindings: website.yaml +functions: website.py +... diff --git a/examples/website/website.py b/examples/website/website.py new file mode 100644 index 0000000..2875d63 --- /dev/null +++ b/examples/website/website.py @@ -0,0 +1,35 @@ +# Use the Python requests library for fetching a page. +import logging +import requests + + +# Step: remember the URL of a web site we want to verify. +# +# The URL is extracted from the step using a pattern in the bindings file. The +# function gets the value via a keyword argument. +# +# Each step function also gets a "context" variable, which starts out as an +# empty dict-like object for each scenario. The same context variable is given +# to each function for the scenario. It's a convenient way to remember data +# between steps. +def remember_url(ctx, url=None): + ctx["url"] = url + + +# Step: fetch the remembered URL. +def fetch_url(ctx): + url = ctx["url"] + r = requests.get(url) + logging.debug(f"GET status {r.status_code}") + assert r.ok + ctx["page"] = r.text + + +# Step: page contains some specific text. +def page_contains(ctx, text=None): + assert text in ctx["page"] + + +# Step: page does NOT contain some specific text. +def page_doesnt_contain(ctx, text=None): + assert text not in ctx["page"] diff --git a/examples/website/website.yaml b/examples/website/website.yaml new file mode 100644 index 0000000..401b16e --- /dev/null +++ b/examples/website/website.yaml @@ -0,0 +1,12 @@ +- given: website {url} + function: remember_url + +- when: I look at the front page + function: fetch_url + +- then: it mentions "{text:text}" + function: page_contains + +- then: it doesn't contain "{text:text}" + function: page_doesnt_contain + |