Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spike project: unit testing for bash scripts #1714

Closed
jotaen4tinypilot opened this issue Jan 9, 2024 · 1 comment · Fixed by #1721
Closed

Spike project: unit testing for bash scripts #1714

jotaen4tinypilot opened this issue Jan 9, 2024 · 1 comment · Fixed by #1721
Assignees
Labels
enhancement New feature or request

Comments

@jotaen4tinypilot
Copy link
Contributor

jotaen4tinypilot commented Jan 9, 2024

In the spirit of potential innovation (a topic we discussed in a recent dev meeting, related to us introducing hurl in the same spirit), I wanted to bring up the idea of writing automated tests for bash scripts.

I’ve used a bash testing utility called bats in one of my side-projects (more on that below), and found that it works somewhat nicely. (Well, as nice as it gets on bash.)

Tests with bats are basically shell script files that follow a specific notation/structure. Say, your tool under test is called my-cmd, and you wanted to test what invoking my-cmd --some-flag yields, you’d do:

#!/usr/bin/env bats

check_my_cmd() { #@test
	run my-cmd --some-flag
	[[ "${status}" -eq 0 ]]
	[[ "${output}" == 'Hello World' ]]
}

For executing the tests, you’d store that snippet in a file (e.g., test.bats) and run bats tests.bats on the terminal.

bats in a nutshell:

  • Tests are stored in regular bash script files (despite the .bats extension)
  • Test cases are regular bash functions that carry a #@test annotation comment
    • You can also use a more fancy @bats prefix, though then you break out of the regular bash realm, so e.g. you cannot shellcheck anymore.
  • Inside the test function you invoke your command-under-test via run. E.g., for a command/script my-cmd, you’d do run my-cmd.
  • The output and status are captured in $output and $status variables, which you can assert on via regular shell conditionals.

The side-project, in which I used bats, is a task runner CLI tool implemented in bash script. The full test-suite is in this folder; for isolation, I run the entire suite inside a disposable docker container, so I can safely mess with the file system. Note that the tool under test is also called run (like the bats built-in for invoking the command under test), which might cause confusion; therefore, my tool is aliased as main in my tests.

Discussion

If we are interested in exploring this, I thought that #1710 could be one possible opportunity that might lend itself for exploration, as it’s relatively simple and self-contained. We have other such scripts, though, and we could also add these tests in hindsight.

One downside that I’d see is that we’d increase the complexity of our tool chain.

There might be other bash testing utilities – which I haven’t looked into, though.

@jotaen4tinypilot jotaen4tinypilot added the enhancement New feature or request label Jan 9, 2024
@mtlynch
Copy link
Contributor

mtlynch commented Jan 9, 2024

Sure, this sounds good.

It's hard for me to say no to more tests! And as we write more bash scripts, it would be nice to have more automated testing of them.

It looks pretty lightweight and straightforward, and doing it in conjunction with #1710 sounds like a great test of it.

jotaen4tinypilot added a commit that referenced this issue Jan 17, 2024
Resolves #1714.
Related #1710.
Stacked onto #1720.

This PR sets up bash tests with
[bats](https://bats-core.readthedocs.io/en/stable/), and adds a first
test suite for [the `strip-marker-sections`
script](#1720).

## Notes
- Similar to how we do it with other test files, I put the `.bats` test
file next to the script under test. The directive in `.dockerignore`
[removes it from the bundle / `.deb`
file](https://github.com/tiny-pilot/tinypilot/assets/83721279/7f52ca3e-17d9-486a-83a5-ea1c6132eb36).
- The `build_bash` dev script is called “build” for consistency with
`build_python` and `build_javascript`, even though we technically don’t
build something. I’ve created
#1716 for us to
potentially reconsider this overall.
- In `build_bash`, it somehow felt reasonable to me to search all places
that are likely to contain `.bats` files, even though we currently only
have them in `/opt/tinypilot-privileged/scripts/`. I don’t feel strongly
about this, though.
- For running the tests, there theoretically would be [an official bats
Docker
image](https://bats-core.readthedocs.io/en/stable/installation.html#running-bats-in-docker),
however that doesn’t play nicely with our bash files: the docker image
doesn’t have a symlink at `/bin/bash`, so it fails to execute any of our
bash scripts that have a `#!/bin/bash` shebang (which is effectively all
of them). We instead would either have to change all our shebangs to the
(most portable) `#!/usr/bin/env bash` shebang, or we just install bats
manually like done here (in the Circle conf).
<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1721"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>

---------

Co-authored-by: Jan Heuermann <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants