promqle2e: Add Go module for fast PromQL e2e tests.
TL;DR: Proposing a lower level, Go based, faster PromQL test alternative to ./promql directory. Inspired by the battle tested framework I wrote for GMP https://github.com/GoogleCloudPlatform/prometheus-engine/blob/main/pkg/export/gcm/export_gcm_test.go (once merged, I will use this framework here).
(Pasting README.md):
promqle2e
This directory contains the promqle2e Go module offering a docker based Go framework for
running fast, tailored acceptance tests for Prometheus compatibility, integrated into go test.
Compared to ../promql, that takes ~hours to run, it's focused on
a quick feedback loop setup that runs within a ~minute to tell you if your "backend"
are serving, on PromQL endpoint, certain metric types or cases as expected. Suitable
for CI runs and quick debugging sessions.
Backend means any collection and storage pipeline e.g.:
- Prometheus
- Prometheus + Cortex
- Prometheus + Thanos
- Prometheus + vendor
- otel-col + vendor
- etc.
Collection can be either scrape bases on remote write based. More ingestion APIs might be added in the future.
Using
- Ensure prerequisites are installed: Go 1.23+ and Docker.
- Get
promqle2emodulego get github.com/prometheus/compliance/promqle2e@latest - Create a new Go test in
_test.gotest file, similar to normal unit test. - Write a scrape based tests e.g.:
func TestPrometheus_Counter_e2e(t *testing.T) {
const interval = 30 * time.Second
// Use prometheus backend, create your own backend OR use multiple ones for reference.
prom1 := promqle2e.PrometheusBackend{Name: "prom1", Image: "quay.io/prometheus/prometheus:v3.2.0"}
prom2 := promqle2e.PrometheusBackend{Name: "prom2", Image: "quay.io/prometheus/prometheus:v2.55.0"}
// Create a scrape style test
pt := promqle2e.NewScrapeStyleTest(t)
//nolint:promlinter // Create a test metric.
counter := promauto.With(pt.Registerer()).NewCounterVec(prometheus.CounterOpts{
Name: "promqle2e_test_counter_total",
Help: "Test counter used by promqle2e test framework for acceptance tests.",
}, []string{"foo"})
var c prometheus.Counter
// Now record fake scrapes and its expected samples for a given metric and backend.
// No metric expected, counterVec empty.
pt.RecordScrape(interval)
c = counter.WithLabelValues("bar")
c.Add(200)
pt.RecordScrape(interval).
Expect(c, 200, prom1).
Expect(c, 200, prom2)
c.Add(10)
pt.RecordScrape(interval).
Expect(c, 210, prom1).
Expect(c, 210, prom2)
// so on... as much as you need to validate.
// Setup resonable timeout e.g. default Prometheus backend performs real scrapes
// with 1s interval so each "RecordScrape" requires at least 1s.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
t.Cleanup(cancel)
// Actual test.
pt.Run(ctx)
}