Test setup for JavaScript/web development with less stress and pain— My solution so far: batr
batr — A “bundle and test … and repeat” library.
I’ve been tired of Webpacks excessive updates since version 5 got released, and have also been looking for a solution to do real UI browser testing for some small JavaScript and web modules. So far I’ve used Webpack for bundling scripts, tape as a test runner, and tape-run to run the same test-scripts in a browser (electron) console. But that started to halt and have issues too. So I decided to have a look at all the issues and see if I could fix some, or hopefully all. The issues I figured out I had:
The problem
- Webpack had way too many releases, often several per week, totally unrelated to any of my needs.
- In addition, all those Webpack updates hit all of my libraries with tests set up. So update X libraries.
- …and if that wasn’t enough I had both Webpack and Webpack-cli that had almost the same release schedule. Meaning updates X libraries X 2.
- Some weird error messages that after some searching and reading seemed to tell me that Webpack wasn’t supposed to do part of what I wanted, and the learning curve to go the correct way seemed too steep.
- I’ve been happy with Travis CI, but got tired of asking for OSS credit since I had to explain it all over, every time. And they didn’t support that I could get OSS credit for projects where I were the maintainer but not the owner. All in one place would also be nice.
- The combination of tape & tape-run seemed to not get error fixes often enough, and electron version seemed to lag behind.
I’ve seen some discussions, and even a group of people doing research on the noise that GitHub’s dependabot creates. Maybe there are better ways for this, but not having dependabot means that suddenly you have too many dependencies to fix, and the changes are too big, so you won’t manage to catch up. The noise dependabot creates is a hassle, but without it or similar stuff, your code will die. I’m learning to have less dependencies, and also archiving pet projects that has de facto died.
In addition I wanted some other features as well. Most would be possible with Webpack I guess, but I wasn’t too happy making a fragile setup even more fragile.
Other things I ideally wanted
- Recording user interactions for the browser UI tests. Not a must have, but really convenient, and something that would make UI tests more likely to happen.
- Bundling CJS, ESM and UMD scripts.
- Minified versions of the same JavaScripts.
- Real user interface automated testing. So far I had used tape-run to run the tape test-scripts in a console in Electron. Okay for just scripts, but I wanted to have regression testing on my HTML demos too. Too many of my demos has gone belly up without me knowing when it happened.
Stuff that worked well and I wanted to continue doing
- Linting and formatting with Standard.js
My solution
A container for dependencies — batr
batr — “bundle and test … and repeat”. It’s just a collection of dependencies that I need for testing, wrapped in one dependency. That I update approximately once a month. It becomes a lightning rod for all my other libraries, limiting the exposure to dependenies version bumps. The library also holds the documentation on how you can use the different parts in combination.
So far the list contains:
- ava
Node.js test runner - playwright
End-to-end testing for modern web apps. I’m using the UI-part. - rollup
Module bundler for JavaScript - standard
Javascript style guide, linter and formatter - CI
In addition I use a GitHub custom continuous integration workflow to run the tests automatically on git push and PRs. All there is to it is a tests.yml-file in the ./.github/workflows/-folder.
And then some rollup plugins I need to make rollup do what I want:
- @rollup/plugin-commonjs
- @rollup/plugin-json
- @rollup/plugin-node-resolve
- rollup-plugin-license
- rollup-plugin-terser
An example on how to use it — batr-example
batr-example: Small example library on the usage of batr, that also doubles as automated tests for batr. I’ve kept it separate so that all code would be as close to real life use as possible.
What’s the solution for you?
I’m not saying batr and batr-example is the solution, it’s just mine, and it turned out just as good as I hoped and a lot better than I feared. And it makes maintenance of my other libraries simpler. But it’s opinionated and tuned to fix my needs for my libraries which may not be yours. Just make your own that fit your needs and reuse it for all your libraries or projects that needs it.
Or maybe you have a pretty good setup already. Post the link in a comment, so I can learn some more. I’m sure I’m not the only one with this problem and a solution. And there may be far better solutions than mine =)