Target-agnostic Artillery load and conformance tests for S3 static-website semantics: index documents, streaming, range requests, custom error documents, and URL encoding. The suite is just HTTP GETs against a base URL, so you can point it at:
- native S3 static website hosting (
bucket.s3-website-<region>.amazonaws.com), - s3proxy in front of a private bucket
(npm package
gmoon/s3proxyor containerforkzero/s3proxy-docker), - or anything else serving the same objects.
Run the same suite against native S3 and against s3proxy, then diff the results to prove parity (and measure overhead). That is the point of the kit.
npm install --save-dev @forkzero/s3-website-test-kit artilleryartillery is a peer dependency, so you control its version.
scenarios/core/- portable. Every request is valid against native S3 website hosting and s3proxy (static files, streaming,206range,403on a private object,404-> error document, special-character keys, HEAD).scenarios/s3proxy/- target-specific.health.ymlhits/health, which s3proxy serves but native S3 website hosting does not.error-contract.ymlasserts s3proxy's XML error bodies (404/403->application/xml), which native S3 website hosting returns astext/html. Only run these against an s3proxy target.
Resolve asset paths with the package helpers:
import { config, scenario, paths } from '@forkzero/s3-website-test-kit';
config('load-test.yml'); // -> /abs/.../configs/load-test.yml
scenario('core/load-test.yml'); // -> /abs/.../scenarios/core/load-test.yml
scenario('s3proxy/health.yml'); // -> /abs/.../scenarios/s3proxy/health.ymlOr point the Artillery CLI at the installed files. Override --target to choose
what you are testing:
# Against native S3 website hosting
artillery run \
--target http://my-bucket.s3-website-us-east-1.amazonaws.com \
--config node_modules/@forkzero/s3-website-test-kit/configs/load-test.yml \
node_modules/@forkzero/s3-website-test-kit/scenarios/core/load-test.yml
# Against s3proxy
artillery run \
--target http://localhost:8080 \
--config node_modules/@forkzero/s3-website-test-kit/configs/load-test.yml \
node_modules/@forkzero/s3-website-test-kit/scenarios/core/load-test.ymlSet TEST_ENVIRONMENT (e.g. native-s3, s3proxy-docker, s3proxy-npm) to
label the run in the JSON summary the test-runner.js processor emits.
Conformance is the kit's headline feature, so running it is one line. Pair
configs/conformance.yml (enables the expect plugin — the load configs don't,
so expect: assertions are otherwise silently inert) with the core conformance
scenario, and override --target:
artillery run \
--config node_modules/@forkzero/s3-website-test-kit/configs/conformance.yml \
--target http://localhost:8080 \
node_modules/@forkzero/s3-website-test-kit/scenarios/core/conformance.ymlThe scenario is a single sequential flow (one vuser hits every endpoint in order), so each assertion runs exactly once regardless of arrival volume, and any failed expectation makes Artillery exit non-zero — usable directly as a CI gate.
The conformance config intentionally omits a
processor: pairing theexpectplugin with this package's ESM processor crashes Artillery. Use a load config (e.g.configs/docker-container.yml) when you want the JSON summary.
configs/ Artillery config files (phases, processor wiring)
scenarios/core/ Portable S3-website scenarios (native S3 and s3proxy)
scenarios/s3proxy/ s3proxy-only scenarios (health)
utils/ Shared processor (test-runner.js) and results comparator
test-data/ Script to create the required objects in your S3 test bucket
A run using a config with the test-runner.js processor writes a JSON summary
named load-test-results-<TEST_ENVIRONMENT>-<ts>.json. s3-website-perf-compare
diffs two of them — a baseline and a candidate — labelling each by its
TEST_ENVIRONMENT. For example, native S3 vs s3proxy:
# each argument is a results file or a bare TEST_ENVIRONMENT label
# (uses the latest matching file in the current directory)
npx s3-website-perf-compare compare --baseline native-s3 --candidate s3proxy-docker
# or let it pick the two most recent runs from different environments:
npx s3-website-perf-compare compareThe conformance suite asserts specific keys, sizes, and content-types, plus
a deterministic 403. The scripts in test-data/ stand this up for you.
bootstrap-s3-target.sh creates a working conformance target end-to-end in any
account — region-aware bucket creation, the dataset with the exact content-types
the suite asserts, and a bucket-policy Deny for the 403 case (which works
under BucketOwnerEnforced / Block Public Access, unlike a legacy object ACL):
BUCKET=my-test-bucket ./test-data/bootstrap-s3-target.sh # create + load
BUCKET=my-test-bucket PUBLIC_READ=true ./test-data/bootstrap-s3-target.sh # also serve native S3 website hosting
BUCKET=my-test-bucket ./test-data/bootstrap-s3-target.sh teardown # delete everythingLeave PUBLIC_READ unset for an s3proxy target (s3proxy reads with its own
credentials); set PUBLIC_READ=true to also grant anonymous read so the bucket
can serve native S3 static-website hosting (disables Block Public Access).
setup-s3-data.sh uploads just the dataset (with content-types and the 403
policy) into a bucket you already have. BUCKET is required — there is no
default bucket:
BUCKET=my-test-bucket ./test-data/setup-s3-data.shindex.html—text/html, 338 Blarge.bin—application/octet-stream, 10 MB (streaming / range)test1m.tmp—binary/octet-stream, 1 MBzerobytefile—binary/octet-stream, 0 Bunauthorized.html— returns403(bucket-policyDeny)- a special-character key — 46 B, for URL-encoding tests
- a missing key (e.g.
/filenotfound) exercises the404path — no object needed
What this package supports for consumers (changes here follow semver):
- JS helpers —
paths,config(),scenario()from the package root (import { config, scenario } from '@forkzero/s3-website-test-kit'). Typed via the shippedindex.d.ts. - Asset files by path — everything under
configs/andscenarios/, referenced asnode_modules/@forkzero/s3-website-test-kit/…(or via the helpers). Filenames are part of the contract. - CLI — the
s3-website-perf-comparebin and its arguments. - Results contract — a run using a
processor:-wired config writesload-test-results-<TEST_ENVIRONMENT>-<ts>.json; that name and itssummaryshape are whats3-website-perf-compareconsumes.
Internal (no stability guarantee — do not import directly): everything under
utils/ (e.g. test-runner.js, results-parser.js). The processor is loaded by
Artillery via the processor: path inside a config, and the parser is exposed
through the CLI — neither is a supported import target.
Apache-2.0