For context, the following technical post is rather bespoke to my recent work but I believe it helps to manage potentially heavy fixtures in tests.
A fixture is used to consistently test software. I used them in nearly every project I write and test. Lately, with my work on Snyk requires that the code is tested against a number of npm packages. This means entire swaths of node_modules
end up in our fixtures directory, which would then lead to pull requests that look like this (a recent real PR in our code):
UK EVENTAttend ffconf.org 2024
The conference for people who are passionate about the web. 8 amazing speakers with real human interaction and content you can't just read in a blog post or watch on a tiktok!
£249+VAT - reserve your place today
Using npm for fixtures
My new method now puts these npm packages inside of totally separate npm package. I've only used this once, but the name of the fixture package will the same as my main project, and suffixed with -fixtures
.
This can be tracked in something like GitHub, but it doesn't require pull requests or code reviews upon update.
The fixtures package can really include anything I like, but specifically I'm using it to include dependencies that will become the individual npm packages I'm using as fixtures. This method also allows me to create mock packages and include them in the node_modules
directory of my fixture page, something like this:
node_modules
├── @remy
│ └── vuln-test
│ └── node_modules
│ └── semver
│ ├── bin
│ └── test
├── debug
│ └── node_modules
│ └── ms
├── semver-rs-demo
│ └── node_modules
│ └── semver
│ ├── bin
│ └── test
├── uglify-package ⬅⬅⬅ this is the mocked package
│ └── node_modules
│ ├── ug-deep
│ │ └── node_modules
│ ├── ug-deep-alt
│ │ └── node_modules
│ │ └── ug-no-deps
│ └── uglify-js
│ └── <snip>
└── undefsafe
├── lib
└── test
You can see my live example of the fixture package and how it's being used in my Snyk work.
Important implementation details
- The big win here is that so long as you pin the fixture package version in your project, your fixtures are now immutable.
- If you're including mocked packages you need to list the top level package name (
uglify-package
in my case) in thebundleDependencies
array in thepackage.json
. - If you want the package directory structure to remain intact (maybe because you need an npm@3 flat directory structure for instance), include the name of the package in the
bundleDependencies
. - You can't include a directory called
node_modules
in your package anywhere (outside of the project root directory) as it's automatically stripped fromnpm publish
. - Do not expect
devDependencies
to be installed, as this isn't the normal install process when including a project dependency.
Simple
So that's it. Put the dependencies in a separate package. Make sure you pin the version of the fixture in your code (so it's immutable) and if you use a CI system that benefits from caching (like Travis does), then the build benefits from the cached fixture.
Most importantly though: no more unnecessarily large pull requests. Now they can focus on the code changes and tests alone.