busser-bats 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/publish.yml +22 -0
  3. data/.gitignore +0 -1
  4. data/.release-please-manifest.json +1 -1
  5. data/.rubocop.yml +1 -4
  6. data/CHANGELOG.md +11 -0
  7. data/CONTRIBUTING.md +86 -0
  8. data/Gemfile +7 -5
  9. data/README.md +100 -28
  10. data/Rakefile +42 -15
  11. data/config/features/support/env.rb +0 -5
  12. data/features/support/env.rb +0 -12
  13. data/features/test_command.feature +31 -31
  14. data/lib/busser/bats/version.rb +3 -1
  15. data/lib/busser/runner_plugin/bats.rb +27 -3
  16. data/spec/busser/runner_plugin/bats_spec.rb +41 -0
  17. data/spec/spec_helper.rb +2 -0
  18. data/vendor/bats/LICENSE.md +53 -0
  19. data/vendor/bats/README.md +84 -242
  20. data/vendor/bats/VERSION.txt +1 -1
  21. data/vendor/bats/bin/bats +75 -0
  22. data/vendor/bats/install.sh +20 -28
  23. data/vendor/bats/lib/bats-core/common.bash +278 -0
  24. data/vendor/bats/lib/bats-core/formatter.bash +151 -0
  25. data/vendor/bats/lib/bats-core/preprocessing.bash +19 -0
  26. data/vendor/bats/lib/bats-core/semaphore.bash +113 -0
  27. data/vendor/bats/lib/bats-core/test_functions.bash +539 -0
  28. data/vendor/bats/lib/bats-core/tracing.bash +425 -0
  29. data/vendor/bats/lib/bats-core/validator.bash +37 -0
  30. data/vendor/bats/lib/bats-core/warnings.bash +44 -0
  31. data/vendor/bats/libexec/bats-core/bats +549 -0
  32. data/vendor/bats/libexec/bats-core/bats-exec-file +402 -0
  33. data/vendor/bats/libexec/bats-core/bats-exec-suite +342 -0
  34. data/vendor/bats/libexec/bats-core/bats-exec-test +383 -0
  35. data/vendor/bats/libexec/bats-core/bats-format-cat +6 -0
  36. data/vendor/bats/libexec/bats-core/bats-format-junit +293 -0
  37. data/vendor/bats/libexec/bats-core/bats-format-pretty +360 -0
  38. data/vendor/bats/libexec/bats-core/bats-format-tap +55 -0
  39. data/vendor/bats/libexec/bats-core/bats-format-tap13 +89 -0
  40. data/vendor/bats/libexec/bats-core/bats-gather-tests +402 -0
  41. data/vendor/bats/libexec/bats-core/bats-preprocess +118 -0
  42. data/vendor/bats/man/Makefile +16 -3
  43. data/vendor/bats/man/bats.1 +100 -58
  44. data/vendor/bats/man/bats.1.ronn +102 -12
  45. data/vendor/bats/man/bats.7 +205 -83
  46. data/vendor/bats/man/bats.7.ronn +262 -14
  47. data/vendor/bats/uninstall.sh +63 -0
  48. metadata +25 -6
  49. data/.tool-versions +0 -1
  50. data/vendor/bats/.gitattributes +0 -3
  51. data/vendor/bats/.travis.yml +0 -5
  52. data/vendor/bats/LICENSE +0 -20
  53. data/vendor/bats/bin/bats +0 -1
  54. data/vendor/bats/package.json +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b09420f04af698ba3b08210baee66053b30fb8ca42be2a96c2d6d0fa0b0af957
4
- data.tar.gz: a997d8bec61c2d19360bc02474299d05145d0cabcc6719ddb51fb15b6e22751b
3
+ metadata.gz: 50827f7c53a1bce1a7ddc9bda08aacd3d7a2388fefc183b7bdc3cbdd23bac07f
4
+ data.tar.gz: 3a22e249cc415c99bdfd3f922b0a4d13665f267eb14216f2c1d226f76354ade3
5
5
  SHA512:
6
- metadata.gz: 3ec7470327ddb5a43d1901b04ada64ff762c3a818e03fed8bf2d51dd539114c5311d8e3e72e3a94b967929daba61aca7251f49fbca0fbd041ff7d52b0a4ec18c
7
- data.tar.gz: f803cb57196ba7cb19c386d080ef54cae9573227c8c34f834f1d1d6b2bfd9a8ff8754db592a4be907b24a83a5f36ab14ef309f7bc76bfe285731cd35e2ff932b
6
+ metadata.gz: c00aef02c07f8518d484107f04165d2e320cc0a822c36b7e74350795c84ce5e3b7d7a221cf75e0e679a9623995db2f2ee44a058b729a73a73442b8a56c38855f
7
+ data.tar.gz: 65749c81f7d399d2a2ce2c64eda0bc3235c815e7e1a7c6a2b0beef4756d8db414589140cdfc8df02d00da757d426eaf2f61bbcf3ab0c2cdb0f122401d96593fd
@@ -43,3 +43,25 @@ jobs:
43
43
  uses: actionshub/publish-gem-to-rubygems@f9126f7a2d36a4fd31a13e78fde5fbdcc4b7b251 # v2.0.6
44
44
  with:
45
45
  token: ${{ secrets.RUBYGEMS_API_KEY }}
46
+
47
+ # actionshub/publish-gem-to-rubygems logs a rejected push and still exits
48
+ # 0, so a release that never reached RubyGems shows up as a green job.
49
+ # Ask RubyGems directly instead of trusting the step. The v2 endpoint is
50
+ # 404 until the exact version is indexed, so -f turns "not there" into a
51
+ # non-zero exit rather than a substring match on `gem list` output.
52
+ - name: Verify the release reached RubyGems
53
+ if: ${{ steps.release.outputs.release_created }}
54
+ env:
55
+ VERSION: ${{ steps.release.outputs.version }}
56
+ run: |
57
+ set -euo pipefail
58
+ name="$(basename "$(ls ./*.gemspec)" .gemspec)"
59
+ for _ in $(seq 1 12); do
60
+ if curl -fsS -o /dev/null "https://rubygems.org/api/v2/rubygems/${name}/versions/${VERSION}.json"; then
61
+ echo "${name} ${VERSION} is on RubyGems"
62
+ exit 0
63
+ fi
64
+ sleep 15
65
+ done
66
+ echo "::error::${name} ${VERSION} never reached RubyGems. A permissions failure in the push step above does not fail that step -- read its log."
67
+ exit 1
data/.gitignore CHANGED
@@ -6,7 +6,6 @@
6
6
  Gemfile.lock
7
7
  InstalledFiles
8
8
  _yardoc
9
- coverage
10
9
  doc/
11
10
  lib/bundler/man
12
11
  pkg
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "0.6.0"
2
+ ".": "0.7.0"
3
3
  }
data/.rubocop.yml CHANGED
@@ -3,7 +3,4 @@ require:
3
3
  - cookstyle/chefstyle
4
4
 
5
5
  AllCops:
6
- TargetRubyVersion: 3.1
7
- Exclude:
8
- - "vendor/**/*"
9
- - "spec/**/*"
6
+ TargetRubyVersion: 3.2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # busser-bats Changelog
2
2
 
3
+ ## [0.7.0](https://github.com/test-kitchen/busser-bats/compare/v0.6.0...v0.7.0) (2026-08-28)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * the vendored bats goes from 0.4.0 to 1.14.0. Suites relying on bats 0.4 behaviour may need updating; see the bats-core changelog.
9
+
10
+ ### Features
11
+
12
+ * vendor bats-core instead of the archived sstephenson/bats ([#59](https://github.com/test-kitchen/busser-bats/issues/59)) ([377240c](https://github.com/test-kitchen/busser-bats/commit/377240cbf04dee7bdec158fc306bbc5a7e7fe509))
13
+
3
14
  ## [0.6.0](https://github.com/test-kitchen/busser-bats/compare/v0.5.0...v0.6.0) (2026-08-28)
4
15
 
5
16
 
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,86 @@
1
+ # Contributing to busser-bats
2
+
3
+ Thanks for taking the time to contribute. This document covers how to get the
4
+ project running locally, how to check your work before opening a pull request,
5
+ and the commit convention releases depend on.
6
+
7
+ ## Getting set up
8
+
9
+ This plugin requires **Ruby 3.2 or newer**. Clone the repository and install the
10
+ development dependencies:
11
+
12
+ ```bash
13
+ git clone https://github.com/test-kitchen/busser-bats.git
14
+ cd busser-bats
15
+ bundle install
16
+ ```
17
+
18
+ ## Running the tests
19
+
20
+ `rake` runs the whole suite:
21
+
22
+ ```bash
23
+ bundle exec rake test
24
+ ```
25
+
26
+ The tests are [cucumber](https://cucumber.io) features in `features/`. They
27
+ drive the real `busser` executable through
28
+ [aruba](https://github.com/cucumber/aruba) rather than calling the plugin's
29
+ classes, so they cover it end to end: install the plugin into a throwaway
30
+ Busser root, write a suite, run it, and check what came out. The step
31
+ definitions they use are published by busser itself, in `lib/busser/cucumber.rb`.
32
+
33
+ ## Linting
34
+
35
+ CI runs three linters, all of which you can run locally:
36
+
37
+ ```bash
38
+ bundle exec cookstyle --chefstyle # Ruby
39
+ yamllint --strict . # YAML
40
+ markdownlint-cli2 "**/*.md" "!**/CHANGELOG*.md"
41
+ ```
42
+
43
+ ## Commit messages
44
+
45
+ This project uses [Conventional Commits](https://www.conventionalcommits.org).
46
+ Releases are automated, and the commit subject on `main` is what decides the
47
+ next version number and what appears in the changelog.
48
+
49
+ Pull requests are **squash merged, so the pull request title becomes that
50
+ subject**. A CI check enforces the format on the title; the individual commits
51
+ on your branch are not checked.
52
+
53
+ | Prefix | Effect on the next release |
54
+ | --- | --- |
55
+ | `fix:` | Patch version bump |
56
+ | `feat:` | Minor version bump |
57
+ | `feat!:`, or a `BREAKING CHANGE:` footer | Minor bump, until this gem reaches 1.0 |
58
+ | `chore:`, `docs:`, `ci:`, `test:`, `refactor:` | No release |
59
+
60
+ For example:
61
+
62
+ ```text
63
+ fix: install the plugin into GEM_HOME rather than the bundle
64
+ feat: support a Gemfile alongside the suite
65
+ ci: pin the shared workflow to a release
66
+ ```
67
+
68
+ ## Opening a pull request
69
+
70
+ 1. Fork the repository and create a branch for your change.
71
+ 2. Add or update tests. A bug fix should come with a test that fails without it.
72
+ 3. Run `bundle exec rake test` and the linters above.
73
+ 4. Open a pull request with a Conventional Commits title.
74
+
75
+ ## Releases
76
+
77
+ Releases are handled by
78
+ [release-please](https://github.com/googleapis/release-please). It watches
79
+ commits landing on `main` and keeps a release pull request open with the next
80
+ version number and the accumulated changelog. Merging that pull request tags the
81
+ release and publishes the gem to RubyGems and GitHub Packages.
82
+
83
+ Maintainers do not bump `lib/busser/bats/version.rb` or edit
84
+ `CHANGELOG.md` by hand; release-please owns both files. This gem is still pre-1.0, so
85
+ `bump-minor-pre-major` is set and a breaking change takes the minor rather than
86
+ graduating it to 1.0.
data/Gemfile CHANGED
@@ -3,16 +3,18 @@ source "https://rubygems.org"
3
3
  gemspec
4
4
 
5
5
  group :cookstyle do
6
- gem "cookstyle", ">= 9.0.0"
6
+ gem "cookstyle", ">= 9.0"
7
7
  end
8
8
 
9
9
  group :test do
10
- gem "aruba", ">= 2.0"
11
- gem "base64" # cucumber needs it; not a default gem on Ruby 4.0
10
+ gem "aruba", ">= 2.4"
11
+ gem "base64", ">= 0.3" # cucumber needs it; not a default gem on Ruby 4.0
12
12
  gem "cucumber", ">= 11.1"
13
- gem "rake", ">= 11.0"
13
+ gem "minitest", ">= 6.0"
14
+ gem "mocha", ">= 2.7"
15
+ gem "rake", ">= 13.4"
14
16
  end
15
17
 
16
18
  group :development do
17
- gem "simplecov"
19
+ gem "yard", ">= 0.9.37"
18
20
  end
data/README.md CHANGED
@@ -1,50 +1,122 @@
1
- # Busser::RunnerPlugin::Bats
1
+ # busser-bats
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/busser-bats.svg)](http://badge.fury.io/rb/busser-bats)
3
+ [![Gem Version](https://badge.fury.io/rb/busser-bats.svg)](https://badge.fury.io/rb/busser-bats)
4
4
 
5
- A Busser runner plugin for [Bats][bats_site]
5
+ A [Busser](https://github.com/test-kitchen/busser) runner plugin that runs
6
+ [Bats](https://github.com/bats-core/bats-core) test files.
7
+
8
+ Bats is a TAP-producing test harness for bash. This plugin vendors a copy of it,
9
+ installs that copy onto the machine under test during postinstall, and then runs
10
+ it against the suite's `bats` directory — so the machine under test needs
11
+ nothing beyond bash.
12
+
13
+ The vendored copy is [bats-core](https://github.com/bats-core/bats-core), which
14
+ is the maintained fork; `vendor/bats/VERSION.txt` records the exact release.
15
+ `rake bats:vendor` refreshes it, and `BATS_VERSION` selects a different tag.
6
16
 
7
17
  ## Status
8
18
 
9
- This software project is no longer under active development as it has no active maintainers. The software may continue to work for some or all use cases, but issues filed in GitHub will most likely not be triaged. If a new maintainer is interested in working on this project please come chat with us in #test-kitchen on Chef Community Slack.
19
+ This software project is no longer under active development as it has no active
20
+ maintainers. The software may continue to work for some or all use cases, but
21
+ issues filed in GitHub will most likely not be triaged. If a new maintainer is
22
+ interested in working on this project please come chat with us in #test-kitchen
23
+ on Chef Community Slack.
24
+
25
+ ## Requirements
26
+
27
+ Ruby 3.2 or newer, and busser 0.9.0 or newer.
28
+
29
+ ## Installation
10
30
 
11
- ## Installation and Setup
31
+ Busser installs the plugin for you when Test Kitchen runs the suite, so there is
32
+ usually nothing to do. To install it by hand:
12
33
 
13
- Until proper reference documentation is complete, the [Writing a Test](https://kitchen.ci/docs/writing-test) section of the Test Kitchen's [Getting Started Guide](https://kitchen.ci/docs/) gives a working example of creating a bats test.
34
+ ```bash
35
+ busser plugin install busser-bats
36
+ ```
14
37
 
15
38
  ## Usage
16
39
 
17
- **TODO:** Write documentation explaining the structure/format of testing files.
40
+ Put your `.bats` files in the `bats` directory of a suite:
18
41
 
19
- ## Development
42
+ ```text
43
+ test
44
+ `-- integration
45
+ `-- default # suite name
46
+ `-- bats
47
+ `-- default.bats
48
+ ```
20
49
 
21
- * Source hosted at [GitHub][repo]
22
- * Report issues/questions/feature requests on [GitHub Issues][issues]
50
+ The whole directory is handed to `bats`, which picks up every `*.bats` file in
51
+ it. A test is a `@test` block, and it passes when every command in it succeeds:
23
52
 
24
- Pull requests are very welcome! Make sure your patches are well tested.
25
- Ideally create a topic branch for every separate change you make. For
26
- example:
53
+ ```bash
54
+ @test "foobar.txt was created" {
55
+ run cat /usr/local/foobar.txt
56
+ [ "$status" -eq 0 ]
57
+ [ "$output" = "hello" ]
58
+ }
59
+ ```
27
60
 
28
- 1. Fork the repo
29
- 2. Create your feature branch (`git checkout -b my-new-feature`)
30
- 3. Commit your changes (`git commit -am 'Added some feature'`)
31
- 4. Push to the branch (`git push origin my-new-feature`)
32
- 5. Create new Pull Request
61
+ See the [Bats documentation](https://bats-core.readthedocs.io) for the full
62
+ assertion and helper vocabulary.
33
63
 
34
- ## Authors
64
+ Test Kitchen picks the plugin up from the suite directory name — no verifier
65
+ configuration is needed beyond the default busser verifier.
35
66
 
36
- Created and maintained by [Fletcher Nichol][author] (<fnichol@nichol.ca>)
67
+ ## Using it with Test Kitchen
37
68
 
38
- ## License
69
+ This is how most people run it, and it needs no Busser commands of your own.
70
+ Select the verifier in `kitchen.yml`:
71
+
72
+ ```yaml
73
+ verifier:
74
+ name: busser
75
+
76
+ suites:
77
+ - name: default
78
+ ```
79
+
80
+ Then put your tests in a `bats` directory inside the suite:
39
81
 
40
- Apache 2.0 (see [LICENSE][license])
82
+ ```text
83
+ test/integration/default/bats/default.bats
84
+ ```
41
85
 
42
- [Bats][bats_site] is released under an MIT-style license, copyright Sam Stephenson.
86
+ `kitchen verify` installs Busser and this plugin on the instance and runs them.
87
+ The directory name is what selects this plugin -- there is nothing else to
88
+ configure.
89
+
90
+ ## When nothing runs
91
+
92
+ If the suite files do not match what this plugin looks for, the run prints one
93
+ line and **exits `0`**:
94
+
95
+ ```text
96
+ -----> Running bats test suite
97
+ ```
98
+
99
+ No tests ran, and nothing said so. Work through these in order:
100
+
101
+ 1. **Is the directory named `bats`?** That name alone selects this plugin.
102
+ `batss/`, `tests/` or anything else is not picked up.
103
+ 2. **Do the filenames match?** Every `*.bats` file in the directory is run
104
+ -- `smoke.sh` is *not* picked up.
105
+ 3. **Is the plugin installed?** `busser plugin list` shows what is available.
106
+ 4. **Is `BUSSER_ROOT` what you think?** `busser suite path` prints where suites
107
+ are actually being looked for.
108
+
109
+ ## Contributing
110
+
111
+ Bug reports and pull requests are welcome. See
112
+ [CONTRIBUTING.md](CONTRIBUTING.md) for how to set up the project, run the test
113
+ suite, and format your commits.
114
+
115
+ ## License
43
116
 
117
+ Apache License 2.0. See [LICENSE](LICENSE).
44
118
 
45
- [author]: https://github.com/fnichol
46
- [issues]: https://github.com/fnichol/busser-bats/issues
47
- [license]: https://github.com/fnichol/busser-bats/blob/master/LICENSE
48
- [repo]: https://github.com/fnichol/busser-bats
119
+ The vendored copy of Bats is released under an MIT-style license, copyright Sam
120
+ Stephenson and the bats-core contributors.
49
121
 
50
- [bats_site]: https://github.com/sstephenson/bats
122
+ Originally created by [Fletcher Nichol](https://github.com/fnichol).
data/Rakefile CHANGED
@@ -1,12 +1,17 @@
1
1
  require "bundler/gem_tasks"
2
- require "open-uri"
3
-
4
2
  namespace :bats do
5
- version = ENV.fetch("BATS_VERSION", "v0.4.0")
6
- url = "https://github.com/sstephenson/bats/archive/#{version}.tar.gz"
3
+ # bats moved. sstephenson/bats was archived in 2016 at v0.4.0; bats-core is
4
+ # the maintained fork and where every release since has come from.
5
+ version = ENV.fetch("BATS_VERSION", "v1.14.0")
6
+ url = "https://github.com/bats-core/bats-core/archive/refs/tags/#{version}.tar.gz"
7
7
  tarball = "tmp/bats-#{version}.tar.gz"
8
8
  vendor = "vendor/bats"
9
9
 
10
+ # install.sh needs bin, libexec, lib and the two man pages. Everything else in
11
+ # the tarball -- the test suite, the docs site, Docker and CI scaffolding --
12
+ # is weight in a gem that gets copied onto every machine under test.
13
+ keep = %w{bin libexec lib man install.sh uninstall.sh LICENSE.md README.md}
14
+
10
15
  desc "Vendors bats #{version} source code into gem codebase"
11
16
  task vendor: "#{vendor}/VERSION.txt"
12
17
 
@@ -14,19 +19,16 @@ namespace :bats do
14
19
  directory vendor
15
20
 
16
21
  file tarball => File.dirname(tarball) do |t|
17
- src = open(url).binmode
18
- dst = open(t.name, "wb")
19
- IO.copy_stream(src, dst)
20
- ensure
21
- src.close
22
- dst.close
22
+ sh "curl", "--fail", "--silent", "--location", url, "--output", t.name
23
23
  end
24
24
 
25
25
  file "#{vendor}/VERSION.txt" => [vendor, tarball] do |t|
26
26
  abs_tarball = File.expand_path(tarball)
27
- Dir.chdir(vendor) { sh "tar xzf #{abs_tarball} --strip-components=1" }
28
- rm_rf "#{vendor}/test"
29
- IO.write(t.name, url + "\n")
27
+ Dir.chdir(vendor) do
28
+ sh "tar", "xzf", abs_tarball, "--strip-components=1"
29
+ (Dir.glob("*", File::FNM_DOTMATCH) - [".", "..", *keep]).each { |f| rm_rf(f) }
30
+ end
31
+ File.write(t.name, "#{url}\n")
30
32
  end
31
33
 
32
34
  desc "Clean up a vendored bats in preparation for a new vendored version"
@@ -35,12 +37,37 @@ namespace :bats do
35
37
  end
36
38
  end
37
39
 
40
+ require "rake/testtask"
41
+ Rake::TestTask.new(:unit) do |t|
42
+ t.libs.push "lib"
43
+ t.test_files = FileList["spec/**/*_spec.rb"]
44
+ t.verbose = true
45
+ end
46
+
38
47
  require "cucumber/rake/task"
39
48
  Cucumber::Rake::Task.new(:features) do |t|
40
- t.cucumber_opts = ["features", "-x", "--format progress"]
49
+ t.cucumber_opts = ["features", "--format progress", "--fail-fast"]
50
+ end
51
+
52
+ # yard lives in the :development group, which CI omits when it runs the tests.
53
+ # Requiring it unconditionally would make `rake test` fail there, so the real
54
+ # task is only defined when yard is installed and a stub explains its absence
55
+ # otherwise. Nothing in CI gates on documentation.
56
+ begin
57
+ require "yard"
58
+
59
+ YARD::Rake::YardocTask.new(:doc) do |t|
60
+ t.files = ["lib/**/*.rb"]
61
+ t.options = ["--output-dir", "doc", "--markup", "markdown"]
62
+ end
63
+ rescue LoadError
64
+ desc "Generate YARD documentation (install the development group first)"
65
+ task :doc do
66
+ abort "yard is not available. Run `bundle install --with development` first."
67
+ end
41
68
  end
42
69
 
43
70
  desc "Run all test suites"
44
- task test: [:features]
71
+ task test: %i{unit features}
45
72
 
46
73
  task default: %i{test}
@@ -1,11 +1,6 @@
1
1
  require "aruba/cucumber"
2
2
  require "busser/cucumber"
3
3
 
4
- if ENV["COVERAGE"]
5
- require "simplecov"
6
- SimpleCov.command_name "features"
7
- end
8
-
9
4
  Before do
10
5
  @aruba_timeout_seconds = 20
11
6
  end
@@ -1,21 +1,9 @@
1
1
  require "aruba/cucumber"
2
2
  require "busser/cucumber"
3
3
 
4
- if ENV["COVERAGE"]
5
- require "simplecov"
6
- SimpleCov.command_name "features"
7
- end
8
-
9
4
  # aruba 2 dropped @aruba_timeout_seconds; setting it in a Before hook is a
10
5
  # no-op, which quietly left these commands on aruba's 15 second default.
11
6
  # Installing a plugin and its gems into a cold sandbox does not always fit.
12
7
  Aruba.configure do |config|
13
8
  config.exit_timeout = 60
14
9
  end
15
-
16
- After do |s|
17
- # Tell Cucumber to quit after this scenario is done - if it failed.
18
- # This is useful to inspect the 'tmp/aruba' directory before any other
19
- # steps are executed and clear it out.
20
- Cucumber.wants_to_quit = true if s.failed?
21
- end
@@ -8,37 +8,37 @@ Feature: Test command
8
8
  When I successfully run `busser plugin install busser-bats --force-postinstall`
9
9
  Given a suite directory named "bats"
10
10
 
11
- # Scenario: A passing test suite
12
- # Given a file in suite "bats" named "default.bats" with:
13
- # """
14
- # @test "runs something" {
15
- # run echo "hello"
16
- # [ "$status" -eq 0 ]
17
- # [ "$output" == "hello" ]
18
- # }
11
+ Scenario: A passing test suite
12
+ Given a file in suite "bats" named "default.bats" with:
13
+ """
14
+ @test "runs something" {
15
+ run echo "hello"
16
+ [ "$status" -eq 0 ]
17
+ [ "$output" == "hello" ]
18
+ }
19
19
 
20
- # """
21
- # When I run `busser test bats`
22
- # Then the output should contain:
23
- # """
24
- # 1..1
25
- # ok 1 runs something
26
- # """
27
- # And the exit status should be 0
20
+ """
21
+ When I run `busser test bats`
22
+ Then the output should contain:
23
+ """
24
+ 1..1
25
+ ok 1 runs something
26
+ """
27
+ And the exit status should be 0
28
28
 
29
- # Scenario: A failing test suite
30
- # Given a file in suite "bats" named "default.bats" with:
31
- # """
32
- # @test "fails something" {
33
- # run which uhoh-whatzit-called
34
- # [ "$status" -eq 0 ]
35
- # }
29
+ Scenario: A failing test suite
30
+ Given a file in suite "bats" named "default.bats" with:
31
+ """
32
+ @test "fails something" {
33
+ run which uhoh-whatzit-called
34
+ [ "$status" -eq 0 ]
35
+ }
36
36
 
37
- # """
38
- # When I run `busser test bats`
39
- # Then the output should contain:
40
- # """
41
- # 1..1
42
- # not ok 1 fails something
43
- # """
44
- # And the exit status should not be 0
37
+ """
38
+ When I run `busser test bats`
39
+ Then the output should contain:
40
+ """
41
+ 1..1
42
+ not ok 1 fails something
43
+ """
44
+ And the exit status should not be 0
@@ -16,7 +16,9 @@
16
16
  # limitations under the License.
17
17
 
18
18
  module Busser
19
+ # Namespace for the Bats Busser runner plugin.
19
20
  module Bats
20
- VERSION = "0.6.0".freeze
21
+ # Version string for the Bats Busser runner plugin
22
+ VERSION = "0.7.0".freeze
21
23
  end
22
24
  end
@@ -16,6 +16,7 @@
16
16
  # limitations under the License.
17
17
 
18
18
  require "pathname" unless defined?(Pathname)
19
+ require "shellwords" unless defined?(Shellwords)
19
20
 
20
21
  require "busser/runner_plugin"
21
22
 
@@ -25,14 +26,37 @@ require "busser/runner_plugin"
25
26
  #
26
27
  class Busser::RunnerPlugin::Bats < Busser::RunnerPlugin::Base
27
28
 
29
+ # Installs the vendored bats onto the machine under test. Runs once, when
30
+ # Busser installs this plugin.
31
+ #
32
+ # bats 0.4 shipped bin/bats as a symlink that the tarball did not preserve,
33
+ # so this used to recreate it by hand before running install.sh. bats-core
34
+ # ships bin/bats as a real file, and recreating the link would replace it
35
+ # with one pointing at libexec/bats, which does not exist in bats-core --
36
+ # its executables live in libexec/bats-core.
28
37
  postinstall do
29
38
  inside(Pathname.new(__FILE__).dirname.join("../../../vendor/bats")) do
30
- FileUtils.ln_sf("../libexec/bats", "bin/bats")
31
- run!(%{./install.sh #{vendor_path("bats")}})
39
+ run!(%{./install.sh #{Shellwords.escape(vendor_path("bats").to_s)}})
32
40
  end
33
41
  end
34
42
 
43
+ # Builds the bats invocation.
44
+ #
45
+ # Both paths are quoted: the Busser root is user supplied through
46
+ # BUSSER_ROOT, and an unquoted path containing a space would be split into
47
+ # two arguments by the shell and silently run the wrong thing.
48
+ #
49
+ # @param bats_bin [String, Pathname] the vendored bats executable
50
+ # @param suite [String, Pathname] the suite directory holding the .bats files
51
+ # @return [String] the command to run
52
+ def self.command_for(bats_bin, suite)
53
+ %{#{Shellwords.escape(bats_bin.to_s)} #{Shellwords.escape(suite.to_s)}}
54
+ end
55
+
56
+ # Runs the suite's .bats files through the vendored bats.
57
+ #
58
+ # @return [void]
35
59
  def test
36
- run!("#{vendor_path("bats").join("bin/bats")} #{suite_path("bats")}")
60
+ run!(self.class.command_for(vendor_path("bats").join("bin/bats"), suite_path("bats")))
37
61
  end
38
62
  end
@@ -0,0 +1,41 @@
1
+ require_relative "../../spec_helper"
2
+
3
+ require "shellwords"
4
+ require "busser/runner_plugin/bats"
5
+
6
+ describe Busser::RunnerPlugin::Bats do
7
+ describe ".command_for" do
8
+ it "puts the bats binary first and the suite second" do
9
+ cmd = Busser::RunnerPlugin::Bats.command_for("/opt/busser/vendor/bats/bin/bats",
10
+ "/opt/busser/suites/bats")
11
+
12
+ _(cmd).must_equal "/opt/busser/vendor/bats/bin/bats /opt/busser/suites/bats"
13
+ end
14
+
15
+ # BUSSER_ROOT is user supplied, and Windows-style or otherwise spaced paths
16
+ # do turn up. Unquoted, the shell would split the path and bats would be
17
+ # handed arguments nobody intended.
18
+ it "quotes a path containing spaces" do
19
+ cmd = Busser::RunnerPlugin::Bats.command_for("/opt/busser/bin/bats",
20
+ "/tmp/my tests/suites/bats")
21
+
22
+ # Shellwords.split is what a shell would do with this string, so this
23
+ # asserts the shell sees exactly two arguments rather than three.
24
+ _(Shellwords.split(cmd)).must_equal ["/opt/busser/bin/bats", "/tmp/my tests/suites/bats"]
25
+ end
26
+
27
+ it "neutralises shell metacharacters in a path" do
28
+ cmd = Busser::RunnerPlugin::Bats.command_for("/opt/busser/bin/bats",
29
+ "/tmp/a;rm -rf x/bats")
30
+
31
+ _(Shellwords.split(cmd)).must_equal ["/opt/busser/bin/bats", "/tmp/a;rm -rf x/bats"]
32
+ end
33
+
34
+ it "accepts Pathname arguments" do
35
+ cmd = Busser::RunnerPlugin::Bats.command_for(Pathname.new("/a/bats"),
36
+ Pathname.new("/b/suites/bats"))
37
+
38
+ _(cmd).must_equal "/a/bats /b/suites/bats"
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,2 @@
1
+ require "minitest/autorun"
2
+ require "mocha/minitest"