Skip to main content

CI for tesh (main branch) Test coverage (main branch) Test coverage (main branch) latest version of tesh on PyPI Supported Python versions License: MIT Built by these great folks!

tesh [tɛʃ] - TEstable SHell sessions in Markdown

Showing shell interactions how to run a tool is useful for teaching and explaining.

Making sure that example still works over the years is painfully hard.

Not anymore.

$ tesh demo/
📄 Checking demo/happy.md
  ✨ Running foo  ✅ Passed
  ✨ Running bar  ✅ Passed
📄 Checking demo/sad.md
  ✨ Running foo  ❌ Failed
         Command: echo "foo"

         Expected:
sad panda
         Got:
foo

Taking you into the shell ...

Enter `!!` to rerun the last command.

$

Syntax

To mark a code block as testable, append tesh-session="NAME" to the header line.

You can use any syntax highlighting directive, such as bash, shell, shell-session, console or others.

```console tesh-session="hello"
$ echo "Hello World!"
Hello World!
```

Linking multiple code blocks into a single shell session

Besides marking a code block as testable, tesh-session is a unique identifier that allows for multiple code blocks to share the same session.

```console tesh-session="multiple_blocks"
$ export NAME=Earth

```
```console tesh-session="multiple_blocks"
$ echo "Hello $NAME!"
Hello Earth!
```

Ignoring parts of the output

Parts of the inline output can be ignored with ...:

```console tesh-session="ignore"
$ echo "Hello from Space!"
Hello ... Space!
```

Multiline support

The same can be done for multiple lines of output. Note that trailing whitespace in every line is trimmed.

```console tesh-session="ignore"
$ printf "Hello \nthere \nfrom \nSpace!"
Hello
...
Space!
```

Commands can continue across multiple lines by prefixing lines with > .

```console tesh-session="multiline"
$ echo "Hello from" \
>   "another" \
>   "line!"
Hello from another line!
```

Advanced directives

You can set a few other optional directives in the header line:

  • tesh-exitcodes: a list of exit codes in the order of commands executed inside the code block,
  • tesh-setup: a filename of a script to run before running the commands in the code block,
  • tesh-ps1: allow an additional PS1 prompt besides the default $,
  • tesh-platform: specify on which platforms this session block should be tested (linux, darwin, windows),
  • tesh-fixture: a filename to save the current snippet,
  • tesh-timeout: number of seconds before a command timeouts (defaults to 30s),
  • tesh-long-running: set to true to showcase long-running commands such as docker compose up.

Let's look at all of these through examples!

Testing exit codes

tesh-exitcodes accepts a list of integers, which represent the exit code for every command in the block.

```console tesh-session="exitcodes" tesh-exitcodes="1 0"
$ false

$ true

```

Test setup

Sometimes you need to do some test setup before running the examples in your code blocks. Put those in a file and point to it with the tesh-setup directive.

```console tesh-session="setup" tesh-setup="readme.sh"
$ echo "Hello $NAME!"
Hello Gaea!
```

Custom prompts

Every so often you need to drop into a virtualenv or similar shell that changes the prompt. tesh supports this via test-ps1 directive.

```console tesh-session="prompt" tesh-ps1="(foo) $"
$ PS1="(foo) $ "


(foo) $ echo "hello"
hello
```

Only run on certain platforms

Some examples should only run on certain platforms, use tesh-platform to declare them as such.

```console tesh-session="platform" tesh-platform="linux"
$ uname
...Linux...
```
```console tesh-session="platform" tesh-platform="darwin"
$ uname
...Darwin...
```

Dump file to disk

Occasionally your examples consist of first showing contents of a file, then executing a command that uses said file. This is supported, use the tesh-fixture directive.

```bash tesh-session="fixture" tesh-fixture="foo.sh"
echo "foo"
```
```console tesh-session="fixture"
$ chmod +x foo.sh

$ ./foo.sh
foo
```

Custom timeout

By default, tesh will fail if an example command does not finish in 30 seconds. This number can be modified using the tesh-timeout directive.

```console tesh-session="timeout" tesh-timeout="3"
$ sleep 1

```

Long running processes

Some processes that you want to show examples for are long-running processes, like docker compose up. They are supported in tesh blocks using the tesh-long-running directive. Note that they need to be the last command in the block.

```console tesh-session="long-running" tesh-timeout="1" tesh-long-running="true"
$ nmap 1.1.1.1
Starting Nmap ...
```

Installation

The best way to install tesh is with your favorite Python package manager.

$ pip install tesh

Design decisions

  • Supports Linux / macOS.
  • Not tied to a specific markdown flavor or tooling.
  • Renders reasonably well on GitHub.

Comparison with other tools

tesh mdsh pandoc filters
Execute shell session ✔️ ✔️ ✔️
Modify markdown file with the new output 🚧[1] ✔️ ✔️
Shared session between code blocks ✔️ ✖️ ✖️
Custom PS1 prompts ✔️ ✖️ ✖️
Assert non-zero exit codes ✔️ ✖️ ✖️
Setup the shell environment ✔️ ✖️ ✖️
Reference fixtures from other snippets ✔️ ✖️ ✖️
Wildcard matching of the command output ✔️ ✖️ ✖️
Starts the shell in debugging mode ✔️ ✖️ ✖️
Specify timeout ✔️ ✖️ ✖️
Support long-running commands ✔️ ✖️ ✖️
  • ✔️: Supported
  • C: Possible but you have to write some code yourself
  • 🚧: Under development
  • ✖️: Not supported
  • ?: I don't know.

Developing tesh

We provide two development environments for people working on this project, one based on Nix and one based on Docker.

For Nix, run nix develop to enter the development environment, where everything is ready for use.

For Docker, run docker build -t tesh . && docker run --rm -v .:/tesh -it tesh to enter the development environment, where everything is ready for use.

Then you can run make tests to run all tests & checks.

Additional make commands are available to run just a subset of tests or checks.

# run tesh on all Markdown files
$ make tesh

# run flake8 linters on changed files only
$ make lint

# run flake8 linters on all files
$ make lint all=true

# run mypy type checker
$ make types

# run unit tests
$ make unit

# run a subset of unit tests (regex find)
$ make unit filter=foo

Multiple Python versions

By default, the development environment uses the latest supported Python version. This is how you drop into an environment with an older Python

On Linux:

$ nix develop .#devShells.x86_64-linux.default-python39

On macOS:

$ nix develop .#devShells.aarch64-darwin.default-python39

On CI, all supported versions of Python are tested.

Metadata

Release files for tesh 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tesh 0.3.2
File Size Uploaded
tesh-0.3.2.tar.gz 17.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tesh 0.3.2
File Interpreter ABI Platform
tesh-0.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 37.5 kB

Release files / tesh-0.3.2.tar.gz

Download URL tesh-0.3.2.tar.gz
Size 17.4 kB
Tags Source
SHA-256 checksum
How to use checksums
5026902b60a8b14967f549152f14c8bc97b2d8caec8bbd1b6662b91138142a5d
BLAKE2b-256 checksum
How to use checksums
df9772077590613900b6c2bebc4f37eb7608a59d14999a7ebf741877a2c8a4a1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.2 CPython/3.11.6

Release files / tesh-0.3.2-py3-none-any.whl

Download URL tesh-0.3.2-py3-none-any.whl
Size 20.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a1e829d61f58afaf9450a3bb95ca2780e945771b881c3080ee4906778daf33df
BLAKE2b-256 checksum
How to use checksums
42b3762bb6c5dccf0206edeb1c1064dedfc0616df147944881a67a9cc70d911b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.2 CPython/3.11.6

Release history Release notifications | RSS feed

This release

0.3.2 This release

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page