shellspec
The atago project wrote these specs on its own initiative and runs them in its own CI, to exercise atago against a real program. They are not shellspec’s official test suite, and the shellspec project is not affiliated with atago.
Summary #
4 suites · 39 scenarios
Contents #
- shellspec (what a specfile can do) — 10 scenarios
- hooks run around every example, and once around them all
- a script is included and its functions are called or run
- a data block is the example’s standard input
- parameters turn one example into one per row
- a mock replaces a command only inside the group that declares it
- the sandbox takes PATH away so an unmocked command cannot be reached
- the scaffold init writes is runnable, and writing it twice changes nothing
- support commands are generated as executables under the helper directory
- the options file is read on every run
- the report is colored on a terminal and plain when colors are refused
- shellspec (formatters, report files, and tracing) — 10 scenarios
- the default formatter is dots, a count, and the failure in full
- the documentation formatter nests the names as written
- the failures formatter is one line an editor can jump to
- the null formatter reports nothing and still returns the verdict
- the JUnit formatter carries the counts, the message, and the output
- report files are written beside the console report, where asked
- profiling ranks the slowest examples
- tracing writes the evaluated commands to a log file
- running in parallel does not change the report
- randomizing the order keeps the verdict and breaks the TAP plan line
- shellspec (choosing which examples run) — 8 scenarios
- counting and listing report the suite without running it
- a dry run prints the report a run would print, and runs nothing
- the name filter matches each name as a pattern, not as a substring
- tags select by name and by value
- a focused example narrows the run only when focus is asked for
- a specfile can be addressed by line number or by example id
- which files count as specfiles is a pattern
- quick mode remembers what did not pass and forgets it once it does
- shellspec (the verdict and the exit contract) — 11 scenarios
- the version and the help text are answered on stdout
- a passing suite is TAP on stdout, exit 0, and no droppings
- a failing example is exit 101 and hands back the command that reruns it
- the failure exit code is the caller’s to choose
- a command line it cannot use is exit 1, before any spec is read
- a specfile that does not parse is a fatal error at its own exit code
- the syntax check reports the same mistake without running anything
- finding no examples is success unless it is declared a failure
- an example that asserts nothing fails, unless warnings are demoted
- skipped, pending, and excluded examples keep the run green
- the same specfile gets the same verdict in sh and in bash
shellspec (what a specfile can do) #
The parts of ShellSpec a specfile author leans on:
the hooks around each example, Include and the difference between calling a
function and running it, Data for standard input, Parameters for one
example per row, command mocks and their scope, and the sandbox that takes
PATH away so an unmocked command cannot be reached by accident.
Ordering and “did this even run” are pinned with an append-only log the
specfile writes, so a hook that stops firing is a diff rather than a missing
line nobody reads. The last scenarios cover the project side — the scaffold
--init writes, the support commands --gen-bin generates, the options file
every run reads — and the colors the reports are drawn in, checked on a real
terminal because that is the only place they exist.
Source: test/e2e/thirdparty/shellspec/features.atago.yaml
Scenario: hooks run around every example, and once around them all #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/hooks_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/hooks_spec.sh:
Describe 'hooks'
BeforeAll 'echo before_all >> hooks.log'
AfterAll 'echo after_all >> hooks.log'
BeforeEach 'echo before_each >> hooks.log'
AfterEach 'echo after_each >> hooks.log'
It 'first'
When call echo first
The output should equal first
echo body_first >> hooks.log
End
It 'second'
When call echo second
The output should equal second
echo body_second >> hooks.log
End
End
When #
shellspec --format tap
Then #
- exit code is
0 - stdout equals an exact value
- the step changed exactly created
hooks.log, modified nothing, deleted nothing - file
hooks.logequals exact bytes
Expected output #
expected stdout:
1..2
ok 1 - hooks first
ok 2 - hooks second
Scenario: a script is included and its functions are called or run #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
mylib.shis created. - Fixture file
spec/mylib_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture mylib.sh:
greet() {
echo "hello, $1"
}
bail_out() {
echo "boom" >&2
exit 3
}
Fixture spec/mylib_spec.sh:
Describe 'mylib.sh'
Include ./mylib.sh
It 'calls a function in the current shell'
When call greet world
The output should equal "hello, world"
The status should be success
End
It 'runs a function that exits, in a subshell'
When run bail_out
The status should equal 3
The stderr should equal boom
The output should be blank
End
End
When #
shellspec --format tap
Then #
- exit code is
0 - stdout equals an exact value
Expected output #
expected stdout:
1..2
ok 1 - mylib.sh calls a function in the current shell
ok 2 - mylib.sh runs a function that exits, in a subshell
Scenario: a data block is the example’s standard input #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/data_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/data_spec.sh:
Describe 'standard input'
Data
#|first line
#|second line
#|third line
End
It 'reads the block'
When call wc -l
The output should match pattern '*3*'
End
It 'sees the lines in order'
When call head -n 1
The output should equal 'first line'
End
End
When #
shellspec --format tap
Then #
- exit code is
0 - stdout equals an exact value
Expected output #
expected stdout:
1..2
ok 1 - standard input reads the block
ok 2 - standard input sees the lines in order
Scenario: parameters turn one example into one per row #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/params_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/params_spec.sh:
Describe 'addition'
Parameters
1 2 3
4 5 9
10 20 30
End
It "adds $1 and $2"
When call expr "$1" + "$2"
The output should equal "$3"
End
End
When #
shellspec --format tap
Then #
- exit code is
0 - stdout equals an exact value
Expected output #
expected stdout:
1..3
ok 1 - addition adds 1 and 2
ok 2 - addition adds 4 and 5
ok 3 - addition adds 10 and 20
Scenario: a mock replaces a command only inside the group that declares it #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/mock_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/mock_spec.sh:
Describe 'mocking'
Describe 'inside the group'
Mock date
echo "2001-02-03"
End
It 'sees the mock'
When call date
The output should equal "2001-02-03"
End
End
It 'sees the real command outside it'
When call date +%Y
The output should match pattern '[0-9][0-9][0-9][0-9]'
End
End
When #
shellspec --format tap
Then #
- exit code is
0 - stdout equals an exact value
Expected output #
expected stdout:
1..2
ok 1 - mocking inside the group sees the mock
ok 2 - mocking sees the real command outside it
Scenario: the sandbox takes PATH away so an unmocked command cannot be reached #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/sandbox_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/sandbox_spec.sh:
Describe 'an external command'
It 'is reachable without the sandbox'
When run command uname
The status should be success
The output should not be blank
End
End
When #
shellspec --format tap
shellspec --sandbox --format tap
Then #
- after
shellspec --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --sandbox --format tap:- exit code is
101 - stdout contains
not ok 1 - an external command is reachable without the sandbox # FAILED,got: failure (non-zero) [status: 127]
- exit code is
Expected output #
expected stdout:
1..1
ok 1 - an external command is reachable without the sandbox
Scenario: the scaffold init writes is runnable, and writing it twice changes nothing #
only when shellspec --version succeeds · skipped on Windows
Given #
- The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
When #
shellspec --init spec git
shellspec --format tap
shellspec --init spec git
Then #
- after
shellspec --init spec git:- exit code is
0 - the step changed exactly created
.shellspec,spec/spec_helper.sh,spec/*_spec.sh,.gitignore, modified nothing, deleted nothing - file
.gitignorecontains/.shellspec-quick.log,/report/
- exit code is
- after
shellspec --format tap:- exit code is
0 - stdout matches
/^1\.\.1\nnot ok 1 - .* # TODO You should implement hello function\n/
- exit code is
- after
shellspec --init spec git:- exit code is
0 - stdout contains
exist - the step changed exactly created nothing, modified nothing, deleted nothing
- exit code is
Scenario: support commands are generated as executables under the helper directory #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - Fixture file
spec/spec_helper.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
When #
shellspec --gen-bin @true @cat
shellspec --gen-bin @true @cat
Then #
- after
shellspec --gen-bin @true @cat:- exit code is
1 - stdout is empty
- stderr matches
/^shellspec helper directory not found: .*/spec\n$/ - the step changed exactly created nothing, modified nothing, deleted nothing
- exit code is
- after
shellspec --gen-bin @true @cat:- exit code is
0 - stdout contains
Generate @true (spec/support/bin/@true),Generate @cat (spec/support/bin/@cat) - the step changed exactly created
spec/support/bin/@true,spec/support/bin/@cat, modified nothing, deleted nothing - file
spec/support/bin/@catis executable
- exit code is
Scenario: the options file is read on every run #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/simple_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture .shellspec:
--format tap
Fixture spec/simple_spec.sh:
Describe 'options file'
It 'is applied without being asked for'
When call true
The status should be success
End
End
When #
shellspec
shellspec --format failures
Then #
- after
shellspec:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --format failures:- exit code is
0 - stdout is empty
- exit code is
Expected output #
expected stdout:
1..1
ok 1 - options file is applied without being asked for
Scenario: the report is colored on a terminal and plain when colors are refused #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/simple_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/simple_spec.sh:
Describe 'colors'
It 'passes'
When call true
The status should be success
End
End
When #
# interactive (pty): shellspec
# interactive (pty): shellspec
Then #
- after
interactive (pty): shellspec:- rendered screen is checked and shows “1 example, 0 failures” in green
- after
interactive (pty): shellspec:- rendered screen contains
1 example, 0 failuresand shows “1 example, 0 failures” in default
- rendered screen contains
shellspec (formatters, report files, and tracing) #
One suite — a passing example and a failing one — reported in every shape
ShellSpec offers: progress dots, nested
documentation, JUnit XML, the editor-oriented failures lines, and null,
which prints nothing and still returns the verdict. Alongside the console
formatter, --output writes report files, --profile ranks the slowest
examples, and --xtrace writes an evaluation trace to a log file.
The last two scenarios are about what a report is worth: parallel jobs must
not change the verdict, and --random must not change it either — though it
does damage the TAP plan line, which is pinned here as it behaves.
Source: test/e2e/thirdparty/shellspec/reporting.atago.yaml
Scenario: the default formatter is dots, a count, and the failure in full #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/mixed_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/mixed_spec.sh:
Describe 'mixed'
It 'passes'
When call expr 2 + 2
The output should equal 4
End
It 'fails'
When call expr 2 + 2
The output should equal 5
End
End
When #
shellspec
Then #
- exit code is
101 - stdout contains
Running:,.F,1.1) The output should equal 5,expected: 5,got: 4,2 examples, 1 failure
Scenario: the documentation formatter nests the names as written #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/nested_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/nested_spec.sh:
Describe 'outer'
Describe 'inner'
It 'passes'
When call true
The status should be success
End
End
End
When #
shellspec --format documentation
Then #
- exit code is
0 - stdout contains
"outer\n inner\n passes\n"
Scenario: the failures formatter is one line an editor can jump to #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/mixed_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/mixed_spec.sh:
Describe 'mixed'
It 'passes'
When call true
The status should be success
End
It 'fails'
When call true
The status should equal 9
End
End
When #
shellspec --format failures
Then #
- exit code is
101 - stdout equals an exact value
Expected output #
expected stdout:
./spec/mixed_spec.sh:7:FAILED:mixed fails
Scenario: the null formatter reports nothing and still returns the verdict #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/mixed_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/mixed_spec.sh:
Describe 'mixed'
It 'fails'
When call true
The status should equal 9
End
End
When #
shellspec --format null
Then #
- exit code is
101 - stdout is empty
Scenario: the JUnit formatter carries the counts, the message, and the output #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/mixed_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/mixed_spec.sh:
Describe 'mixed'
It 'passes'
When call true
The status should be success
End
It 'fails'
When call echo unexpected
The output should equal expected
End
End
When #
shellspec --format junit
Then #
- exit code is
101 - stdout contains
<?xml version="1.0" encoding="UTF-8"?>,tests="2",failures="1",<testcase time="0" classname="spec/mixed_spec.sh" name="mixed fails">,<failure message="The output should equal expected">,<![CDATA[expected: "expected",got: "unexpected"
Scenario: report files are written beside the console report, where asked #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/mixed_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/mixed_spec.sh:
Describe 'mixed'
It 'passes'
When call true
The status should be success
End
End
When #
shellspec --output tap --output junit --format progress
shellspec --output tap --reportdir elsewhere --format null
Then #
- after
shellspec --output tap --output junit --format progress:- exit code is
0 - stdout contains
1 example, 0 failures - the step changed exactly created
report/results.tap,report/results_junit.xml, modified nothing, deleted nothing - file
report/results.tapequals exact bytes - file
report/results_junit.xmlcontainsname="mixed passes"
- exit code is
- after
shellspec --output tap --reportdir elsewhere --format null:- exit code is
0 - the step changed exactly created
elsewhere/results.tap, modified nothing, deleted nothing
- exit code is
Scenario: profiling ranks the slowest examples #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/two_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/two_spec.sh:
Describe 'two'
It 'first'
When call true
The status should be success
End
It 'second'
When call true
The status should be success
End
End
When #
shellspec --profile --profile-limit 1
Then #
- exit code is
0 - stdout contains
# Top 1 slowest examples of the 2 examples, matches/#\s+1 [0-9]+\.[0-9]+ spec/two_spec\.sh:[0-9]+-[0-9]+/
Scenario: tracing writes the evaluated commands to a log file #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/traced_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/traced_spec.sh:
Describe 'traced'
greet() { echo "hello, $1"; }
It 'greets'
When call greet world
The output should equal "hello, world"
End
End
When #
shellspec --xtrace --log-file trace.log --format tap
Then #
- exit code is
0 - stderr contains
Fall back to trace-only mode. All expectations will be skipped. - the step changed exactly created
trace.log, modified nothing, deleted nothing - file
trace.logcontains[spec/traced_spec.sh:5] When call greet world,+ greet world,+ echo hello, world
Scenario: running in parallel does not change the report #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/a_spec.shis created. - Fixture file
spec/b_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/a_spec.sh:
Describe 'a'
It 'passes'
When call true
The status should be success
End
End
Fixture spec/b_spec.sh:
Describe 'b'
It 'fails'
When call true
The status should equal 9
End
End
When #
shellspec --format tap
shellspec --jobs 2 --format tap
Then #
- after
shellspec --format tap:- exit code is
101 - stdout contains
1..2,ok 1 - a passes,not ok 2 - b fails # FAILED
- exit code is
- after
shellspec --jobs 2 --format tap:- exit code is
101 - stdout contains
1..2,ok 1 - a passes,not ok 2 - b fails # FAILED
- exit code is
Scenario: randomizing the order keeps the verdict and breaks the TAP plan line #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/a_spec.shis created. - Fixture file
spec/b_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/a_spec.sh:
Describe 'a'
It 'passes'
When call true
The status should be success
End
End
Fixture spec/b_spec.sh:
Describe 'b'
It 'also passes'
When call true
The status should be success
End
End
When #
shellspec --random specfiles --format tap
shellspec --random none --format tap
Then #
- after
shellspec --random specfiles --format tap:- exit code is
0 - stdout contains
ok 1 -,ok 2 - - stderr matches
/^Randomized with seed [0-9]+/ - stdout matches
/^1\.\.spec/[ab]_spec\.sh\n/
- exit code is
- after
shellspec --random none --format tap:- exit code is
0 - stdout matches
/^1\.\.2\n/
- exit code is
shellspec (choosing which examples run) #
Every way ShellSpec narrows a run: counting and
listing without running, --dry-run, the name filter, tags, focus, line and
id ranges, the file pattern, and quick mode — which remembers what did not
pass last time in a ledger on disk.
A selection flag is asserted on both halves here. The plan line says what ran; a specfile whose examples write a file says what did not, so “counted but not executed” is proven rather than assumed. Quick mode gets the full state machine: the ledger appearing, the replay narrowing to what failed, the ledger emptying once it passes, and the next run going wide again.
Source: test/e2e/thirdparty/shellspec/selection.atago.yaml
Scenario: counting and listing report the suite without running it #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/side_effect_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/side_effect_spec.sh:
Describe 'side effects'
It 'writes a file'
When call touch ran.txt
The status should be success
End
It 'writes another'
When call touch ran-too.txt
The status should be success
End
End
When #
shellspec --count
shellspec --list examples
shellspec --list examples:lineno
Then #
- after
shellspec --count:- exit code is
0 - stdout equals an exact value
- the step changed exactly created nothing, modified nothing, deleted nothing
- exit code is
- after
shellspec --list examples:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --list examples:lineno:- exit code is
0 - stdout equals an exact value
- file
ran.txtdoes not exist - file
ran-too.txtdoes not exist
- exit code is
Expected output #
expected stdout:
1 2
expected stdout:
spec/side_effect_spec.sh:@1-1
spec/side_effect_spec.sh:@1-2
expected stdout:
spec/side_effect_spec.sh:2
spec/side_effect_spec.sh:7
Scenario: a dry run prints the report a run would print, and runs nothing #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/side_effect_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/side_effect_spec.sh:
Describe 'side effects'
It 'writes a file and would fail'
When call touch ran.txt
The status should equal 9
End
End
When #
shellspec --dry-run --format tap
Then #
- exit code is
0 - stdout equals an exact value
- the step changed exactly created nothing, modified nothing, deleted nothing
- file
ran.txtdoes not exist
Expected output #
expected stdout:
1..1
ok 1 - side effects writes a file and would fail
Scenario: the name filter matches each name as a pattern, not as a substring #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/names_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/names_spec.sh:
Describe 'arithmetic'
It 'adds numbers'
When call expr 2 + 2
The output should equal 4
End
It 'subtracts numbers'
When call expr 4 - 2
The output should equal 2
End
End
When #
shellspec --example 'adds numbers' --format tap
shellspec --example adds --format tap
shellspec --example '*adds*' --format tap
shellspec --example 'arithmetic adds numbers' --format tap
Then #
- after
shellspec --example 'adds numbers' --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --example adds --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --example '*adds*' --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --example 'arithmetic adds numbers' --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
Expected output #
expected stdout:
1..1
ok 1 - arithmetic adds numbers
expected stdout:
1..0
expected stdout:
1..1
ok 1 - arithmetic adds numbers
expected stdout:
1..0
Scenario: tags select by name and by value #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/tagged_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/tagged_spec.sh:
Describe 'tagged'
It 'fast one' speed:fast
When call true
The status should be success
End
It 'slow one' speed:slow
When call true
The status should be success
End
End
When #
shellspec --tag speed --format tap
shellspec --tag speed:fast --format tap
shellspec --tag never-used --format tap
Then #
- after
shellspec --tag speed --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --tag speed:fast --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --tag never-used --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
Expected output #
expected stdout:
1..2
ok 1 - tagged fast one
ok 2 - tagged slow one
expected stdout:
1..1
ok 1 - tagged fast one
expected stdout:
1..0
Scenario: a focused example narrows the run only when focus is asked for #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/focused_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/focused_spec.sh:
Describe 'focus'
fIt 'the one being worked on'
When call true
The status should be success
End
It 'the other one'
When call true
The status should be success
End
End
When #
shellspec --focus --format tap
shellspec --format tap
Then #
- after
shellspec --focus --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --format tap:- exit code is
0 - stdout contains
1..2,ok 1 - focus the one being worked on,ok 2 - focus the other one,You need to specify --focus option to run focused (underlined) example(s) only.
- exit code is
Expected output #
expected stdout:
1..1
ok 1 - focus the one being worked on
Scenario: a specfile can be addressed by line number or by example id #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/ranges_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/ranges_spec.sh:
Describe 'ranges'
It 'first'
When call true
The status should be success
End
It 'second'
When call true
The status should be success
End
End
When #
shellspec --format tap spec/ranges_spec.sh:7
shellspec --format tap spec/ranges_spec.sh:@1-1
shellspec --format tap spec/ranges_spec.sh:1
Then #
- after
shellspec --format tap spec/ranges_spec.sh:7:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --format tap spec/ranges_spec.sh:@1-1:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --format tap spec/ranges_spec.sh:1:- exit code is
0 - stdout equals an exact value
- exit code is
Expected output #
expected stdout:
1..1
ok 1 - ranges second
expected stdout:
1..1
ok 1 - ranges first
expected stdout:
1..2
ok 1 - ranges first
ok 2 - ranges second
Scenario: which files count as specfiles is a pattern #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/normal_spec.shis created. - Fixture file
spec/unusual_test.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/normal_spec.sh:
Describe 'normal'
It 'is collected by default'
When call true
The status should be success
End
End
Fixture spec/unusual_test.sh:
Describe 'unusual'
It 'is collected only under a matching pattern'
When call true
The status should be success
End
End
When #
shellspec --format tap
shellspec --pattern '*_test.sh' --format tap
Then #
- after
shellspec --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --pattern '*_test.sh' --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
Expected output #
expected stdout:
1..1
ok 1 - normal is collected by default
expected stdout:
1..1
ok 1 - unusual is collected only under a matching pattern
Scenario: quick mode remembers what did not pass and forgets it once it does #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/quick_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - Fixture file
spec/quick_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/quick_spec.sh:
Describe 'quick'
It 'always passes'
When call true
The status should be success
End
It 'fails at first'
When call expr 2 + 2
The output should equal 5
End
End
Fixture spec/quick_spec.sh:
Describe 'quick'
It 'always passes'
When call true
The status should be success
End
It 'fails at first'
When call expr 2 + 2
The output should equal 4
End
End
When #
shellspec --quick --format tap
shellspec --quick --format tap
shellspec --quick --format tap
shellspec --quick --format tap
Then #
- after
shellspec --quick --format tap:- exit code is
101 - stdout contains
1..2,not ok 2 - quick fails at first # FAILED - the step changed exactly created
.shellspec-quick.log, modified nothing, deleted nothing - file
.shellspec-quick.logequals exact bytes
- exit code is
- after
shellspec --quick --format tap:- exit code is
101 - stdout equals an exact value
- exit code is
- after
shellspec --quick --format tap:- exit code is
0 - stdout contains
1..1,ok 1 - quick fails at first,All examples have been passed. Rerun to prevent regression. - file
.shellspec-quick.logequals exact bytes
- exit code is
- after
shellspec --quick --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
Expected output #
expected stdout:
1..1
not ok 1 - quick fails at first # FAILED
# (in specfile spec/quick_spec.sh, line 9)
# When call expr 2 + 2
# The output should equal 5
#
# expected: 5
# got: 4
#
expected stdout:
1..2
ok 1 - quick always passes
ok 2 - quick fails at first
shellspec (the verdict and the exit contract) #
ShellSpec is a BDD test framework for POSIX shells, and its own test suite is written in ShellSpec. What that suite checks from the inside is pinned here from the outside: what the runner reports, and what it returns to whatever started it.
ShellSpec answers with three levels rather than the usual two — 1 for a command line it cannot use, 101 for specs that failed, 102 for a fatal error while loading them — and both spec-level codes can be overridden, which is the whole reason to separate them. Each level is asserted here, together with the TAP the run prints, the rerun command a failure hands back, and the two defaults worth knowing about: an example that asserts nothing is a failure, and finding no examples at all is not.
Every specfile is written by the scenario that runs it. Nothing upstream is copied.
Source: test/e2e/thirdparty/shellspec/shellspec.atago.yaml
Scenario: the version and the help text are answered on stdout #
only when shellspec --version succeeds · skipped on Windows
Given #
- The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
When #
shellspec --version
shellspec --help
Then #
- after
shellspec --version:- exit code is
0 - stdout matches
/^[0-9]+\.[0-9]+\.[0-9]+/ - stderr is empty
- exit code is
- after
shellspec --help:- exit code is
0 - stdout contains
Usage: shellspec,-f, --format FORMATTER,--failure-exit-code CODE
- exit code is
Scenario: a passing suite is TAP on stdout, exit 0, and no droppings #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/arithmetic_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/arithmetic_spec.sh:
Describe 'arithmetic'
It 'adds numbers'
When call expr 2 + 2
The output should equal 4
The status should be success
End
End
When #
shellspec --format tap
Then #
- exit code is
0 - stdout equals an exact value
- the step changed exactly created nothing, modified nothing, deleted nothing
Expected output #
expected stdout:
1..1
ok 1 - arithmetic adds numbers
Scenario: a failing example is exit 101 and hands back the command that reruns it #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/arithmetic_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/arithmetic_spec.sh:
Describe 'arithmetic'
It 'adds numbers'
When call expr 2 + 2
The output should equal 5
End
End
When #
shellspec --format tap
shellspec
Then #
- after
shellspec --format tap:- exit code is
101 - stdout equals an exact value
- exit code is
- after
shellspec:- exit code is
101 - stdout contains
1 example, 1 failure,shellspec spec/arithmetic_spec.sh:2 # 1) arithmetic adds numbers FAILED
- exit code is
Expected output #
expected stdout:
1..1
not ok 1 - arithmetic adds numbers # FAILED
# (in specfile spec/arithmetic_spec.sh, line 4)
# When call expr 2 + 2
# The output should equal 5
#
# expected: 5
# got: 4
#
Scenario: the failure exit code is the caller’s to choose #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/failing_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/failing_spec.sh:
Describe 'failing'
It 'does not hold'
When call true
The status should equal 9
End
End
When #
shellspec --failure-exit-code 42 --format tap
Then #
- exit code is
42 - stdout contains
not ok 1 - failing does not hold # FAILED
Scenario: a command line it cannot use is exit 1, before any spec is read #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/arithmetic_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/arithmetic_spec.sh:
Describe 'arithmetic'
It 'adds numbers'
When call expr 2 + 2
The output should equal 4
End
End
When #
shellspec --bogus
shellspec spec/missing_spec.sh
Then #
- after
shellspec --bogus:- exit code is
1 - stdout is empty
- stderr equals an exact value
- exit code is
- after
shellspec spec/missing_spec.sh:- exit code is
1 - stdout is empty
- stderr equals an exact value
- exit code is
Expected output #
expected stderr:
Unrecognized option: --bogus
expected stderr:
Not found a path: spec/missing_spec.sh.
Scenario: a specfile that does not parse is a fatal error at its own exit code #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/broken_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/broken_spec.sh:
Describe 'broken'
It 'never closes'
When #
shellspec
shellspec --error-exit-code 77
Then #
- after
shellspec:- exit code is
102 - stdout contains
Example aborted (exit status: 102) - stderr contains
Syntax error: Unexpected end of file (expecting 'End') in spec/broken_spec.sh line 2,Fatal error occurred, terminated with exit status 102.
- exit code is
- after
shellspec --error-exit-code 77:- exit code is
77 - stdout contains
Example aborted (exit status: 77) - stderr contains
Fatal error occurred, terminated with exit status 77.
- exit code is
Scenario: the syntax check reports the same mistake without running anything #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/good_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - Fixture file
spec/broken_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/good_spec.sh:
Describe 'good'
It 'passes'
When call true
The status should be success
End
End
Fixture spec/broken_spec.sh:
Describe 'broken'
It 'never closes'
When #
shellspec --syntax-check
shellspec --syntax-check
Then #
- after
shellspec --syntax-check:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --syntax-check:- exit code is
1 - stdout contains
spec/broken_spec.sh,spec/good_spec.sh - stderr matches
/Syntax error: Unexpected end of file \(expecting 'End'\) in spec/broken_spec.sh line 2/
- exit code is
Expected output #
expected stdout:
spec/good_spec.sh
Scenario: finding no examples is success unless it is declared a failure #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/notes.txtis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/notes.txt:
no specfile matches the default pattern
When #
shellspec
shellspec --fail-no-examples
Then #
- after
shellspec:- exit code is
0 - stdout contains
0 examples, 0 failures
- exit code is
- after
shellspec --fail-no-examples:- exit code is
101 - stdout contains
0 examples, 0 failures, no examples found
- exit code is
Scenario: an example that asserts nothing fails, unless warnings are demoted #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/silent_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/silent_spec.sh:
Describe 'no expectation'
It 'checks nothing'
When call true
End
End
When #
shellspec --format tap
shellspec --no-warning-as-failure --format tap
Then #
- after
shellspec --format tap:- exit code is
101 - stdout contains
not ok 1 - no expectation checks nothing # WARNED,# Not found any expectation
- exit code is
- after
shellspec --no-warning-as-failure --format tap:- exit code is
0 - stdout contains
ok 1 - no expectation checks nothing # WARNED,# Not found any expectation
- exit code is
Scenario: skipped, pending, and excluded examples keep the run green #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/states_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/states_spec.sh:
Describe 'states'
It 'is skipped'
Skip 'not applicable here'
When call false
The status should be success
End
It 'is pending'
Pending 'not implemented yet'
When call false
The status should be success
End
xIt 'is excluded'
When call false
The status should be success
End
End
When #
shellspec --format tap
Then #
- exit code is
0 - stdout contains
ok 1 - states is skipped # SKIP not applicable here,not ok 2 - states is pending # TODO not implemented yet,ok 3 - states is excluded # SKIP Temporarily skipped
Scenario: the same specfile gets the same verdict in sh and in bash #
only when shellspec --version succeeds · skipped on Windows
Given #
- Fixture file
.shellspecis created. - Fixture file
spec/portable_spec.shis created. - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected). - The command runs with an isolated home under
${workdir}/.atago-home(HOME/XDG or APPDATA redirected).
Inputs #
Fixture spec/portable_spec.sh:
Describe 'portable shell'
It 'expands parameters the same way everywhere'
greet() { echo "hello, $1"; }
When call greet world
The output should equal "hello, world"
End
End
When #
shellspec --shell sh --format tap
shellspec --shell bash --format tap
shellspec --shell bash
Then #
- after
shellspec --shell sh --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --shell bash --format tap:- exit code is
0 - stdout equals an exact value
- exit code is
- after
shellspec --shell bash:- exit code is
0 - stdout matches
/^Running: .*bash \[bash /
- exit code is
Expected output #
expected stdout:
1..1
ok 1 - portable shell expands parameters the same way everywhere
expected stdout:
1..1
ok 1 - portable shell expands parameters the same way everywhere