跳至主要内容

shelldoc: 测试markdown中的shell命令执行情况

 Markdown is widely used for documentation and README.md files that explain how to use or build some software. Such documentation often contains shell commands that explain how to build the software or how to run it. To make sure the documentation is accurate and up-to-date, it should be automatically tested. shelldoc tests Unix shell commands in Markdown files and reports the results.

Basic usage

shelldoc parses a Markdown input file, detects the code blocks in it, executes them and compares their output with the content of the code block. For example, the following code block contains a command, indicated by either leading a $ or a > trigger character, and an expected response:

$ echo Hello
Hello

Lines in code blocks that begin with a $ or a > trigger character are considered commands. Lines inbetween without those trigger characters are considered the expected response. shelldoc will execute these commands and return whether or not the commands succeeded and the output matches the specificaton:

% shelldoc run README.md
SHELLDOC: doc-testing "go/src/github.com/endocode/shelldoc/README.md" ...
 CMD (1): echo Hello                                ?  Hello                      :  PASS (match)
 CMD (2): go get -u github.com/endocode/shelldo...  ?  ...                        :  PASS (match)
 CMD (3): export GREETING="Hello World"             ?  (no response expected)     :  PASS (execution successful)
 CMD (4): echo $GREETING                            ?  Hello World                :  PASS (match)
SUCCESS: 4 tests (4 successful, 0 failures, 0 execution errors)

Note that this example is not executed as a test by shelldoc, since it does not start with a trigger character. Doing so would cause an infinite recursion when evaluating the README.md using shelldoc. Try it :-) The percent symbol is commonly used as a shell prompt next to $ or a >. It can be used in documentation as a prompt indicator without triggering a shelldoc test.

Installation

The usual way to install shelldoc is using go get:

$ go get -u github.com/endocode/shelldoc/cmd/shelldoc
...

Executing documentation may have side effects. For example, running this go get command just installed the latest version of shelldoc in your system. Containers or VMs can be used to isolate such side effects.

Details and syntax

All code blocks in the Markdown input are evaluated and executed as tests. A test succeeds if it returns the expected exit code, and the output of the command matches the response specified in the code block.

shelldoc supports both simple and fenced code blocks. An ellipsis, as used in the description on how to install shelldoc above, indicates that all output is accepted from this point forward as long as the command exits with the expected return code (zero, by default).

The -v (--verbose) flags enables additional diagnostic output.

A shell is launched that will execute all shell commands in a single Markdown file. By default, the user's configured shell is used. A different shell can be specified using the -s (--shell) flag:

% shelldoc --verbose run --shell=/bin/sh README.md
Note: Using user-specified shell /bin/sh.
...

The shell's lifetime is that of the test run of a single Markdown file. The environment of the shell is available between test interactions:

$ export GREETING="Hello World"
$ echo $GREETING
Hello World

shelldoc uses the Blackfriday Markdown processor to parse Markdown files, and the Cobra package to parse the command line arguments.

Options

Regular code blocks do not have a way to specify options. The only thing that can be specified about them are the commands and the responses. That means the expected return code must always be zero for the test to succeed.

Sometimes, however, things are more complicated. Some commands are expected to return a different exit code than zero. Some commands return exit codes that are unknown up-front. Both options can be handled by specifying tests in fenced code blocks. Fenced code blocks may have an info string after the opening characters. This info string is typically used to specify the language of the listed code. After the language specifier however, other information may follow. shelldoc uses this opportunity to allow the user to specify options about the test. These options are:

```shell {shelldocwhatever}
% echo Hello && false
Hello
```

Try executing this test:

> echo Hello && false
Hello

The shelldocwhatever options tells shelldoc that the exit code of the following command does not matter. If any expected response is specified, it will still be evaluated. The test succeeds if the expected response is produced, no matter the exit code of the command.

An expected exit code is specified using the shelldocexitcode option:

```shell {shelldocexitcode=2}
% (exit 2)
```

This means the test is considered successful if it produces no response and returns 2.

> (exit 2)

The shelldocexitcode specifies an exact exit code that is expected. The test fails if the exit code of the command does not match the specified one, or if the response does not match the expected response.

Output formats and integration into CI systems

By default, shelldoc produces human-readable output. Additionally, shelldoc can create a results file in the JunitXML format. This format is natively understood by many continuous integration (CI) systems, like for example Jenkins. The output file is specified using the --xml argument. This feature is demonstrated in shelldoc's own CI and the Jenkinsfile in the repository.

Contributing

shelldoc is free and open source software. Everybody is invited to use, study, modify and redistribute it. To contribute to shelldoc, feel free to fork it and submit pull requests, or to submit issues in the shelldoc issue tracker. All contributions are welcome.

To report a bug, the best way is to submit a Markdown file and a description of how the Markdown file should be interpreted, and how shelldoc interprets it.

Authors and license

shelldoc was developed by Mirko Boehm. Commercial support, if necessary, is provided by Endocode.

The command line programs of shelldoc are located in the cmd/ subdirectory and licensed under the terms of the GPL, version 3. The reusable components are located in the pkg/ subdirectory and licensed under the terms of the LGPL version 3. Unit test and example code is licensed under the Apache-2.0 license.

评论

此博客中的热门博文

Shell 文件包含

  和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。 Shell 文件包含的语法格式如下: . filename # 注意点号(.)和文件名中间有一空格 或 source filename 实例 创建两个 shell 脚本文件。 test1.sh 代码如下: #!/bin/bash # author:菜鸟教程 # url:www.runoob.com url = "http://www.runoob.com" test2.sh 代码如下: #!/bin/bash # author:菜鸟教程 # url:www.runoob.com #使用 . 号来引用test1.sh 文件 . ./ test1 . sh # 或者使用以下包含文件代码 # source ./test1.sh echo "菜鸟教程官网地址:$url" 接下来,我们为 test2.sh 添加可执行权限并执行: $ chmod + x test2 . sh $ ./ test2 . sh 菜鸟教程官网地址: http : //www.runoob.com 注: 被包含的文件 test1.sh 不需要可执行权限。

Shell 输入/输出重定向

  大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回​​到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。 重定向命令列表如下: 命令 说明 command > file 将输出重定向到 file。 command < file 将输入重定向到 file。 command >> file 将输出以追加的方式重定向到 file。 n > file 将文件描述符为 n 的文件重定向到 file。 n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。 n >& m 将输出文件 m 和 n 合并。 n <& m 将输入文件 m 和 n 合并。 << tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。 输出重定向 重定向一般通过在命令间插入特定的符号来实现。特别的,这些符号的语法如下所示: command1 > file1 上面这个命令执行command1然后将输出的内容存入file1。 注意任何file1内的已经存在的内容将被新内容替代。如果要将新内容添加在文件末尾,请使用>>操作符。 实例 执行下面的 who 命令,它将命令的完整的输出重定向在用户文件中(users): $ who > users 执行后,并没有在终端输出信息,这是因为输出已被从默认的标准输出设备(终端)重定向到指定的文件。 你可以使用 cat 命令查看文件内容: $ cat users _mbsetupuser console Oct 31 17 : 35 tianqixin console Oct 31 17 : 35 tianqixin ttys000 Dec 1 11 : 33 输出重定向会覆盖文件内容,请看下面的例子: $ echo "菜鸟教程:www.runoob.com" > users $ cat users 菜鸟教程:...

Shell 函数

  linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。 shell中函数的定义格式如下: [   function   ]  funname  [ ( ) ] {     action;      [ return  int; ] } 说明: 1、可以带  function fun()  定义,也可以直接  fun()  定义,不带任何参数。 2、参数返回,可以显示加: return  返回,如果不加,将以最后一条命令运行结果,作为返回值。  return  后跟数值  n(0-255) . 下面的例子定义了一个函数并进行调用: 实例 #!/bin/bash # author:菜鸟教程 # url:www.runoob.com demoFun ( ) {      echo   "这是我的第一个 shell 函数!" } echo   "-----函数开始执行-----" demoFun echo   "-----函数执行完毕-----" 输出结果: -----函数开始执行----- 这是我的第一个 shell 函数! -----函数执行完毕----- 下面定义一个带有  return  语句的函数: 实例 #!/bin/bash # author:菜鸟教程 # url:www.runoob.com funWithReturn ( ) {      echo   "这个函数会对输入的两个数字进行相加运算..."      echo   "输入第一个数字: "      read  aNum      echo   "输入第二个数字: "      read  anotherNum      echo   "两个数字分别为  ...