Showing 7 posts
If you use Bazel, your project is of moderate size. And because your project is of moderate size, it almost-certainly builds one or more binaries, at least one of which is a CLI tool. But let’s face it: you don’t have end-to-end testing for those tools, do you? I’m sure you have split the binary’s main function into its own file so that the rest of the tool can be put in a library, and I’m extra-sure that you have unit tests for such library. But… those tests do little to verify the functionality and quality of the tool as experienced by the end user. Consider: What exactly does the tool print to the console on success? Does it show errors nicely when they happen, or does it dump internal stack traces? How does it handle unknown flags or bad arguments? Is the built-in help message nicely rendered when your terminal is really wide? What if the terminal is narrow? You must write end-to-end tests for your tools but, usually, that isn’t easy to do. Until today. Combining shtk with Bazel via the new rules_shtk ruleset makes it trivial to write tests that verify the behavior of your CLI tools—no matter what language they are written in—and in this article I’m going to show you how.
While working on this static blog a few days ago, I made a change to its templates that warranted an automated test. I could have written a trivial shell script to do it, but instead I reached out for shtk’s unit-testing module. I tweeted about it right away to just say that you can, in fact, write tests in shell because lots of developers are skeptical about any script longer than 10 lines of code. Interestingly, this reply came through: a pointer to a contemporary, under-development library for writing tests in Bash. Which made me think: “Hey, I had already done that years ago… but nobody knows about it. Gotta fix that with a blog post!” But first, I had to bring shtk back from its ashes because I had not touched it for more than 6 years and it wasn’t read for show and tell. So I did something that I wanted to do back in the day but never did: I put together a website for shtk to host its reference manual and I fixed a few obvious rough edges. With those tweaks out of the way, we come to this article. In here, I want to show you how writing decent tests in shell is entirely possible and how shtk’s testing platform provides unique features to do integration testing of CLI apps written in any language.
The shell supports defining functions, which, as we learned in the previous post, you should embrace and use. Unfortunately, they are fairly primitive and their use can, paradoxically, introduce other readability problems. One specific problem is that function parameters are numbered, not named, so the risk of cryptic code is high. Let’s see why this is a problem.
Our team develops Bazel, a Java-based tool. We do have, however, a significant amount of shell scripting. The percentage is small at only 3.6% of our codebase… but given the size of our project, that’s about 130,000 lines—a lot, really. Pretty much nobody likes writing these integration tests in shell. Leaving aside that our infrastructure is clunky, the real problem is that the team at large is not familiar with writing shell per se.
The Shell Toolkit, or shtk for short, is a little project I introduced back in August of 2008 to support other tools such as sysbuild and sysupgrade. Since that time, the project has seen little activity because it did not have much to offer and because shtk's public interface was not documented (hence making it impossible for developers to get started with shtk). Well, both are changing today with the brand-new release of shtk 1.
Over a year ago, I developed two command line utilities for NetBSD (sysbuild and sysupgrade) and a supporting library for the two tools (shtk). These were all introduced in their corresponding blog posts —Introducing sysbuild for NetBSD, Introducing sysupgrade for NetBSD and Introducing shtk— and since then I have heard good comments about them. About a couple of weeks ago, I started working on the much-needed rewrite of pkg_comp and a supporting standalone tool.
Have you ever wanted to have a collection of ready-to-use modules for shell scripts? I have, particularly because I keep reimplementing the same functions over and over and over and over again whenever I write non-trivial shell scripts, and I'm tired of doing so. That's why I have just abstracted all the common code in the aforementioned tools and put it into a new package called the "Shell Toolkit", or shtk for short.