Skip to content

Commit ceab5ea

Browse files
committed
scripts/test: Extract lib/bats-main
Been thinking about this for a while. Now that I'm beginning to write plugins that I want to test using the same command line interface to Bats, but without copying and pasting a ton of code, I finally became motivated to extract most of the logic from `scripts/test` into `lib/bats-main`, with some improvements. `tests/test.bats` required very few changes to stay up-to-date with the new architecture. `tests/vars.bats` was another story, since all the new `_GO_*` vars in `lib/bats-main` now show up in the output. There probably are a few more test cases that could be added to validate different configuration variable scenarios; I'll consider adding them in a future commit.
1 parent c92d0e3 commit ceab5ea

File tree

4 files changed

+280
-116
lines changed

4 files changed

+280
-116
lines changed

lib/bats-main

+224
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
#! /bin/bash
2+
#
3+
# Run automated tests written using Bats
4+
#
5+
# Exports:
6+
# @go.bats_main
7+
# Parses command-line flags and arguments and executes Bats and Kcov
8+
#
9+
# @go.bats_clone
10+
# Creates a shallow clone of the Bats repository at `_GO_BATS_DIR`
11+
#
12+
# @go.bats_tab_completion
13+
# Provides command line argument completion
14+
#
15+
# @go.bats_coverage
16+
# Reinvokes the test command script using kcov to collect test coverage data
17+
#
18+
# If a project keeps all of its bats tests in `$_GO_ROOTDIR/tests`, test
19+
# commands need contain at a minimum:
20+
#
21+
# . "$_GO_USE_MODULES" 'bats-main'
22+
# @go.bats_main "$@"
23+
#
24+
# As a more realistic example, to enable tab completion and automatic coverage
25+
# collection on Travis CI that gets sent to Coveralls:
26+
#
27+
# declare _GO_COVERAGE_INCLUDE
28+
# _GO_COVERAGE_INCLUDE=('go' 'bin/' 'lib/' 'scripts/')
29+
# declare _GO_COVERALLS_URL='https://coveralls.io/github/USER/PROJECT'
30+
#
31+
# . "$_GO_USE_MODULES" 'bats-main'
32+
# # Tab completions
33+
# @go.bats_main "$@"
34+
#
35+
# There are many other variables that are available for fine-tuning, but
36+
# sticking to the above should cover most cases.
37+
#
38+
# Note that `@go.bats_main` will call `@go.bats_clone` to clone the Bats
39+
# repository if `_GO_BATS_DIR` doesn't yet exist. This means there's no need to
40+
# make the Bats repository a submodule if so desired. The Bats version so cloned
41+
# may be set by overriding `_GO_BATS_VERSION`.
42+
43+
# Directory containing Bats tests, relative to `_GO_ROOTDIR`
44+
export _GO_TEST_DIR="${_GO_TEST_DIR:-tests}"
45+
46+
# Directory in which kcov will be built
47+
export _GO_KCOV_DIR="${_GO_KCOV_DIR:-$_GO_TEST_DIR/kcov}"
48+
49+
# Directory in which coverage results are written
50+
export _GO_BATS_COVERAGE_DIR="${_GO_BATS_COVERAGE_DIR:-$_GO_TEST_DIR/coverage}"
51+
52+
# Directory containing the Bats testing framework sources
53+
export _GO_BATS_DIR="${_GO_BATS_DIR:-$_GO_TEST_DIR/bats}"
54+
55+
# Path to the main Bats executable
56+
export _GO_BATS_PATH="$_GO_BATS_DIR/libexec/bats"
57+
58+
# Version of Bats to fetch if `_GO_BATS_DIR` is missing
59+
export _GO_BATS_VERSION="${_GO_BATS_VERSION:-master}"
60+
61+
# URL of the Bats git repository to clone to `_GO_BATS_DIR`
62+
export _GO_BATS_URL="${_GO_BATS_URL:-https://github.com/sstephenson/bats.git}"
63+
64+
# Set this to nonempty if you wish to collect coverage using kcov by default
65+
export _GO_COLLECT_BATS_COVERAGE="$_GO_COLLECT_BATS_COVERAGE"
66+
67+
# Array of patterns identifying sources to include in the coverage report
68+
export _GO_BATS_COVERAGE_INCLUDE
69+
_GO_BATS_COVERAGE_INCLUDE=("${_GO_BATS_COVERAGE_INCLUDE[@]}")
70+
71+
# Array of patterns identifying sources to exclude from the coverage report
72+
export _GO_BATS_COVERAGE_EXCLUDE
73+
_GO_BATS_COVERAGE_EXCLUDE=('/tmp/' "${_GO_BATS_COVERAGE_EXCLUDE[@]}")
74+
75+
# URL of the project's coverage statistics on Coveralls.io
76+
export _GO_COVERALLS_URL="${_GO_COVERALLS_URL}"
77+
78+
# Collect coverage on Travis. Doesn't seem to slow anything down substantially.
79+
if [[ -n "$_GO_COVERALLS_URL" && "$TRAVIS_OS_NAME" == 'linux' ]]; then
80+
declare _GO_COLLECT_BATS_COVERAGE='true'
81+
fi
82+
83+
# Array of `./go glob` arguments to select Bats test files in `_GO_TEST_DIR`
84+
export _GO_BATS_GLOB_ARGS
85+
_GO_BATS_GLOB_ARGS=("${_GO_BATS_GLOB_ARGS[@]}")
86+
87+
# Set _GO_BATS_GLOB_ARGS if the caller hasn't already done so. There should be
88+
# little need for the caller ever to do so, so long as the conventions encoded
89+
# in the above variables are followed.
90+
if [[ "${#_GO_BATS_GLOB_ARGS[@]}" -eq '0' ]]; then
91+
_GO_BATS_GLOB_ARGS+=("$_GO_TEST_DIR" '.bats')
92+
93+
declare __go_bats_d="${_GO_BATS_DIR#$_GO_TEST_DIR/}"
94+
if [[ "$__go_bats_d" != "$_GO_BATS_DIR" ]]; then
95+
_GO_BATS_GLOB_ARGS=('--ignore' "${__go_bats_d}" "${_GO_BATS_GLOB_ARGS[@]}")
96+
_GO_BATS_COVERAGE_EXCLUDE+=("${_GO_BATS_DIR}/")
97+
fi
98+
unset '__go_bats_d'
99+
fi
100+
101+
# Parses command-line flags and arguments and executes Bats and Kcov
102+
#
103+
# The first argument can be one of the following flags:
104+
#
105+
# --complete Perform tab completion; see `{{go}} help complete` for details
106+
# --coverage Collect test coverage data using kcov (Linux only)
107+
# --edit Open matching test files using `{{go}} edit`
108+
# --list List test suite names without executing them
109+
#
110+
# If the argument list following is empty, or if it is only one of the flags
111+
# above (aside from `--complete`), all Bats test files are matched.
112+
#
113+
# Globals:
114+
# _GO_BATS_GLOB_ARGS: Array of arguments to '@go glob' to select Bats tests
115+
# _GO_BATS_PATH: The path to your project's Bats installation
116+
# _GO_COLLECT_BATS_COVERAGE: If set, collect coverage using kcov if available
117+
# Also see `@go.bats_clone` and `@go.bats_coverage`
118+
#
119+
# Arguments:
120+
# $1: One of the flags defined above, or the first test glob pattern
121+
# ...: Remaining test glob patterns
122+
@go.bats_main() {
123+
if [[ "$1" == '--complete' ]]; then
124+
shift
125+
@go.bats_tab_completion "$@"
126+
return
127+
fi
128+
@go.bats_clone
129+
130+
if [[ "$1" == '--coverage' && -z "$__GO_COVERAGE_RUN" ]]; then
131+
shift
132+
export __GO_COVERAGE_RUN='true'
133+
@go.bats_coverage "$@"
134+
elif [[ "$1" == '--edit' ]]; then
135+
shift
136+
local tests=($(@go 'glob' "${_GO_BATS_GLOB_ARGS[@]}" "$@"))
137+
@go 'edit' "${tests[@]}"
138+
elif [[ "$1" == '--list' ]]; then
139+
shift
140+
@go 'glob' '--trim' "${_GO_BATS_GLOB_ARGS[@]}" "$@"
141+
elif [[ -z "$__GO_COVERAGE_RUN" && -n "$_GO_COLLECT_BATS_COVERAGE" ]]; then
142+
@go.bats_main '--coverage' "$@"
143+
else
144+
local tests=($(@go 'glob' "${_GO_BATS_GLOB_ARGS[@]}" "$@"))
145+
time "$BASH" "$_GO_BATS_PATH" "${tests[@]}"
146+
fi
147+
}
148+
149+
# Creates a shallow clone of the Bats repository at `_GO_BATS_DIR`
150+
#
151+
# Does nothing if `_GO_BATS_DIR` is already present.
152+
#
153+
# Globals:
154+
# _GO_BATS_DIR: Location of the Bats sources
155+
# _GO_BATS_URL: URL of the Bats git repository to clone
156+
# _GO_BATS_VERSION: Tag or branch to clone from _GO_BATS_URL
157+
@go.bats_clone() {
158+
if [[ ! -d "$_GO_BATS_DIR" ]]; then
159+
@go get git-repo "$_GO_BATS_URL" "$_GO_BATS_VERSION" "$_GO_BATS_DIR"
160+
fi
161+
}
162+
163+
# Provides command line argument completion
164+
#
165+
# Emits the standard --coverage, --edit, and --list flags and uses '@go glob' to
166+
# produce a list of test name completions based on test file names.
167+
#
168+
# See './go help complete' for information on the argument completion protocol.
169+
#
170+
# Globals:
171+
# _GO_BATS_GLOB_ARGS: Array of arguments to '@go glob' to select Bats tests
172+
#
173+
# Arguments:
174+
# word_index: Zero-based index of the command line argument to be completed
175+
# ...: Array of remaining command line arguments
176+
@go.bats_tab_completion() {
177+
local word_index="$1"
178+
shift
179+
180+
# Skip over completing the initial `@go glob` args themselves.
181+
local test_word_index="$((word_index + ${#_GO_BATS_GLOB_ARGS[@]}))"
182+
183+
if [[ "$word_index" -eq '0' ]]; then
184+
echo '--coverage' '--edit' '--list'
185+
if [[ "${1:0:1}" == '-' ]]; then
186+
return
187+
fi
188+
fi
189+
@go 'glob' '--complete' "$test_word_index" "${_GO_BATS_GLOB_ARGS[@]}" "$@"
190+
}
191+
192+
# Reinvokes the test command script using kcov to collect test coverage data
193+
#
194+
# Currently only supported on Ubuntu Linux, via the core lib/kcov-ubuntu module.
195+
#
196+
# If the test suite passes and results are sent to Coveralls,
197+
# `_GO_COVERALLS_URL` is output to the console.
198+
#
199+
# Globals:
200+
# _GO_KCOV_DIR: Directory in which kcov will be built
201+
# _GO_BATS_COVERAGE_DIR: Directory in which coverage results are written
202+
# _GO_COVERAGE_INCLUDE: Patterns of files to include in the coverage report
203+
# _GO_COVERAGE_EXCLUDE: Patterns of files to include in the coverage report
204+
# _GO_COVERALLS_URL: The project's Coveralls URL
205+
# _GO_SCRIPT: Path to the `./go` script
206+
# _GO_CMD_NAME: Array comprising the `./go` command name
207+
#
208+
# Arguments:
209+
# ...: Command line arguments for the command script run under kcov
210+
@go.bats_coverage() {
211+
local include_paths
212+
local exclude_paths
213+
214+
. "$_GO_USE_MODULES" 'kcov-ubuntu'
215+
printf -v include_paths '%s,' "${_GO_BATS_COVERAGE_INCLUDE[@]}"
216+
printf -v exclude_paths '%s,' "${_GO_BATS_COVERAGE_EXCLUDE[@]}"
217+
218+
time run_kcov "$_GO_KCOV_DIR" \
219+
"$_GO_BATS_COVERAGE_DIR" \
220+
"${include_paths%,}" \
221+
"${exclude_paths%,}" \
222+
"$_GO_COVERALLS_URL" \
223+
"$_GO_SCRIPT" "${_GO_CMD_NAME[@]}" "$@"
224+
}

scripts/test

+8-99
Original file line numberDiff line numberDiff line change
@@ -23,111 +23,20 @@
2323
# This command script can serve as a template for your own project's test
2424
# script. Copy it into your project's script directory and customize as needed.
2525

26-
# These variables are documented in the comments of the functions that use them
27-
# below.
28-
declare -r _GO_TEST_DIR='tests'
29-
declare -r _GO_TEST_GLOB_ARGS=('--ignore' 'bats' "$_GO_TEST_DIR" '.bats')
30-
declare -r _GO_BATS_DIR="$_GO_TEST_DIR/bats"
31-
declare -r _GO_BATS_PATH="$_GO_BATS_DIR/libexec/bats"
32-
declare -r _GO_COVERALLS_URL='https://coveralls.io/github/mbland/go-script-bash'
26+
declare _GO_BATS_COVERAGE_INCLUDE
27+
_GO_BATS_COVERAGE_INCLUDE=('go' 'go-core.bash' 'lib/' 'libexec/' 'scripts/')
28+
declare _GO_COVERALLS_URL='https://coveralls.io/github/mbland/go-script-bash'
3329

34-
# Provides command line argument completion
35-
#
36-
# Emits the standard --coverage, --edit, and --list flags and uses '@go glob' to
37-
# produce a list of test name completions based on test file names.
38-
#
39-
# See './go help complete' for information on the argument completion protocol.
40-
#
41-
# Globals:
42-
# _GO_TEST_GLOB_ARGS An array of arguments to '@go glob' to select Bats tests
43-
#
44-
# Arguments:
45-
# $1: Zero-based index of the word to be completed from the remaining args
46-
# ...: Array of remaining command line arguments
47-
_test_tab_completion() {
48-
local word_index="$1"
49-
shift
50-
if [[ "$word_index" -eq '0' ]]; then
51-
echo '--coverage' '--edit' '--list'
52-
if [[ "${1:0:1}" == '-' ]]; then
53-
return
54-
fi
55-
fi
56-
@go 'glob' '--complete' "$((word_index + ${#_GO_TEST_GLOB_ARGS[@]}))" \
57-
"${_GO_TEST_GLOB_ARGS[@]}" "$@"
58-
}
59-
60-
# Reinvokes the test command script using kcov to collect test coverage data
61-
#
62-
# Currently only supported on Ubuntu Linux, via the core kcov-ubuntu module.
63-
#
64-
# Globals:
65-
# _GO_COVERALLS_URL The project's Coveralls URL; appears in Travis output
66-
#
67-
# Arguments:
68-
# $@: Command line arguments for the command script run under kcov
69-
_test_coverage() {
70-
. "$_GO_USE_MODULES" 'kcov-ubuntu'
71-
run_kcov "$_GO_TEST_DIR/kcov" \
72-
"$_GO_TEST_DIR/coverage" \
73-
'go,go-core.bash,lib/,libexec/,scripts/' \
74-
"/tmp,$_GO_TEST_DIR/bats/" \
75-
"$_GO_COVERALLS_URL" \
76-
"$_GO_SCRIPT" "${_GO_CMD_NAME[@]}" "$@"
77-
}
78-
79-
# Parses command-line flags and arguments and executes Bats and Kcov
80-
#
81-
# The first argument can be one of the following flags:
82-
#
83-
# --complete Perform tab completion; see `{{go}} help complete` for details
84-
# --coverage Collect test coverage data using kcov (Linux only)
85-
# --list List test suite names without executing them
86-
# --edit Open matching test files using `{{go}} edit`
87-
#
88-
# If the argument list following is empty, or if it is only one of the flags
89-
# above (aside from `--complete`), all Bats test files are matched.
90-
#
91-
# Globals:
92-
# _GO_TEST_DIR Test directory, relative to _GO_ROOTDIR
93-
# _GO_TEST_GLOB_ARGS An array of arguments to '@go glob' to select Bats tests
94-
# _GO_BATS_DIR Bats submodule path, relative to _GO_ROOTDIR
95-
# _GO_BATS_PATH The path to your project's Bats installation
96-
#
97-
# Arguments:
98-
# $1: One of the flags defined above, or the first test glob pattern
99-
# ...: Remaining test glob patterns
30+
# Passes all arguments through to `@go.bats_main` from `lib/bats-main`.
10031
_test_main() {
101-
if [[ "$1" == '--complete' ]]; then
102-
# Tab completions
103-
shift
104-
_test_tab_completion "$@"
105-
return
106-
fi
32+
. "$_GO_USE_MODULES" 'bats-main'
10733

108-
if [[ ! -f "$_GO_BATS_PATH" ]]; then
34+
if [[ ! -d "$_GO_BATS_DIR" ]]; then
10935
git submodule update --init "$_GO_BATS_DIR"
11036
fi
11137

112-
if [[ "$1" == '--coverage' && "$__COVERAGE_RUN" != 'true' ]]; then
113-
shift
114-
local -x __COVERAGE_RUN='true'
115-
_test_coverage "$@"
116-
elif [[ "$1" == '--list' ]]; then
117-
shift
118-
@go 'glob' '--trim' "${_GO_TEST_GLOB_ARGS[@]}" "$@"
119-
elif [[ "$1" == '--edit' ]]; then
120-
shift
121-
local tests=($(@go 'glob' "${_GO_TEST_GLOB_ARGS[@]}" "$@"))
122-
@go 'edit' "${tests[@]}"
123-
elif [[ "$__COVERAGE_RUN" != 'true' && "$TRAVIS_OS_NAME" == 'linux' ]]; then
124-
# Collect coverage by default on Travis. Doesn't seem to slow anything down
125-
# substantially.
126-
_test_main '--coverage' "$@"
127-
else
128-
local tests=($(@go 'glob' "${_GO_TEST_GLOB_ARGS[@]}" "$@"))
129-
time "$BASH" "$_GO_BATS_PATH" "${tests[@]}"
130-
fi
38+
# Tab completions
39+
@go.bats_main "$@"
13140
}
13241

13342
_test_main "$@"

0 commit comments

Comments
 (0)