Skip to content

Commit 50932ba

Browse files
authored
[tests] Introduce cozytest - a new testing framework (#982)
Signed-off-by: Andrei Kvapil <[email protected]> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced separate end-to-end test scripts for cluster and application provisioning, improving test clarity and modularity. - Added a new test runner script with enhanced output formatting and live tracing for easier debugging of test runs. - **Bug Fixes** - None. - **Chores** - Removed the legacy end-to-end test automation script. - Updated testing workflow to use new modular test scripts and runner for improved maintainability. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
2 parents f9f8bb2 + 74e7e5c commit 50932ba

5 files changed

Lines changed: 611 additions & 373 deletions

File tree

‎hack/cozytest.sh‎

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/bin/sh
2+
###############################################################################
3+
# cozytest.sh - Bats-compatible test runner with live trace and enhanced #
4+
# output, written in pure shell #
5+
###############################################################################
6+
set -eu
7+
8+
TEST_FILE=${1:?Usage: ./cozytest.sh <file.bats> [pattern]}
9+
PATTERN=${2:-*}
10+
LINE='----------------------------------------------------------------'
11+
12+
cols() { stty size 2>/dev/null | awk '{print $2}' || echo 80; }
13+
MAXW=$(( $(cols) - 12 )); [ "$MAXW" -lt 40 ] && MAXW=70
14+
BEGIN=$(date +%s)
15+
timestamp() { s=$(( $(date +%s) - BEGIN )); printf '[%02d:%02d]' $((s/60)) $((s%60)); }
16+
17+
###############################################################################
18+
# run_one <fn> <title> #
19+
###############################################################################
20+
run_one() {
21+
fn=$1 title=$2
22+
tmp=$(mktemp -d) || { echo "Failed to create temp directory" >&2; exit 1; }
23+
log="$tmp/log"
24+
25+
echo "╭ » Run test: $title"
26+
START=$(date +%s)
27+
skip_next="+ $fn" # первую строку трассировки с именем функции пропустим
28+
29+
{
30+
(
31+
PS4='+ ' # prefix for set -x
32+
set -eu -x # strict + trace
33+
"$fn"
34+
)
35+
printf '__RC__%s\n' "$?"
36+
} 2>&1 | tee "$log" | while IFS= read -r line; do
37+
case "$line" in
38+
'__RC__'*) : ;;
39+
'+ '*) cmd=${line#'+ '}
40+
[ "$cmd" = "${skip_next#+ }" ] && continue
41+
case "$cmd" in
42+
'set -e'|'set -x'|'set -u'|'return 0') continue ;;
43+
esac
44+
out=$cmd ;;
45+
*) out=$line ;;
46+
esac
47+
now=$(( $(date +%s) - START ))
48+
[ ${#out} -gt "$MAXW" ] && out="$(printf '%.*s…' "$MAXW" "$out")"
49+
printf '┊[%02d:%02d] %s\n' $((now/60)) $((now%60)) "$out"
50+
done
51+
52+
rc=$(awk '/^__RC__/ {print substr($0,7)}' "$log" | tail -n1)
53+
[ -z "$rc" ] && rc=1
54+
now=$(( $(date +%s) - START ))
55+
56+
if [ "$rc" -eq 0 ]; then
57+
printf '╰[%02d:%02d] ✅ Test OK: %s\n' $((now/60)) $((now%60)) "$title"
58+
else
59+
printf '╰[%02d:%02d] ❌ Test failed: %s (exit %s)\n' \
60+
$((now/60)) $((now%60)) "$title" "$rc"
61+
echo "----- captured output -----------------------------------------"
62+
grep -v '^__RC__' "$log"
63+
echo "$LINE"
64+
exit "$rc"
65+
fi
66+
67+
rm -rf "$tmp"
68+
}
69+
70+
###############################################################################
71+
# convert .bats -> shell-functions #
72+
###############################################################################
73+
TMP_SH=$(mktemp) || { echo "Failed to create temp file" >&2; exit 1; }
74+
trap 'rm -f "$TMP_SH"' EXIT
75+
awk '
76+
/^@test[[:space:]]+"/ {
77+
line = substr($0, index($0, "\"") + 1)
78+
title = substr(line, 1, index(line, "\"") - 1)
79+
fname = "test_"
80+
for (i = 1; i <= length(title); i++) {
81+
c = substr(title, i, 1)
82+
fname = fname (c ~ /[A-Za-z0-9]/ ? c : "_")
83+
}
84+
printf("### %s\n", title)
85+
printf("%s() {\n", fname)
86+
print " set -e" # ошибка → падение теста
87+
next
88+
}
89+
/^}$/ {
90+
print " return 0" # если автор не сделал exit 1 — тест ОК
91+
print "}"
92+
next
93+
}
94+
{ print }
95+
' "$TEST_FILE" > "$TMP_SH"
96+
97+
[ -f "$TMP_SH" ] || { echo "Failed to generate test functions" >&2; exit 1; }
98+
# shellcheck disable=SC1090
99+
. "$TMP_SH"
100+
101+
###############################################################################
102+
# run selected tests #
103+
###############################################################################
104+
awk -v pat="$PATTERN" '
105+
/^### / {
106+
title = substr($0, 5)
107+
name = "test_"
108+
for (i = 1; i <= length(title); i++) {
109+
c = substr(title, i, 1)
110+
name = name (c ~ /[A-Za-z0-9]/ ? c : "_")
111+
}
112+
if (pat == "*" || index(title, pat) > 0)
113+
printf("%s %s\n", name, title)
114+
}
115+
' "$TMP_SH" | while IFS=' ' read -r fn title; do
116+
run_one "$fn" "$title"
117+
done

‎hack/e2e-apps.bats‎

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/usr/bin/env bats
2+
# -----------------------------------------------------------------------------
3+
# Cozystack end‑to‑end provisioning test (Bats)
4+
# -----------------------------------------------------------------------------
5+
6+
@test "Create tenant with isolated mode enabled" {
7+
kubectl create -f - <<EOF
8+
apiVersion: apps.cozystack.io/v1alpha1
9+
kind: Tenant
10+
metadata:
11+
name: test
12+
namespace: tenant-root
13+
spec:
14+
etcd: false
15+
host: ""
16+
ingress: false
17+
isolated: true
18+
monitoring: false
19+
resourceQuotas: {}
20+
seaweedfs: false
21+
EOF
22+
kubectl wait hr/tenant-test -n tenant-root --timeout=1m --for=condition=ready
23+
kubectl wait namespace tenant-test --timeout=20s --for=jsonpath='{.status.phase}'=Active
24+
}
25+
26+
@test "Create a tenant Kubernetes control plane" {
27+
kubectl create -f - <<EOF
28+
apiVersion: apps.cozystack.io/v1alpha1
29+
kind: Kubernetes
30+
metadata:
31+
name: test
32+
namespace: tenant-test
33+
spec:
34+
addons:
35+
certManager:
36+
enabled: false
37+
valuesOverride: {}
38+
cilium:
39+
valuesOverride: {}
40+
fluxcd:
41+
enabled: false
42+
valuesOverride: {}
43+
gatewayAPI:
44+
enabled: false
45+
gpuOperator:
46+
enabled: false
47+
valuesOverride: {}
48+
ingressNginx:
49+
enabled: true
50+
hosts: []
51+
valuesOverride: {}
52+
monitoringAgents:
53+
enabled: false
54+
valuesOverride: {}
55+
verticalPodAutoscaler:
56+
valuesOverride: {}
57+
controlPlane:
58+
apiServer:
59+
resources: {}
60+
resourcesPreset: small
61+
controllerManager:
62+
resources: {}
63+
resourcesPreset: micro
64+
konnectivity:
65+
server:
66+
resources: {}
67+
resourcesPreset: micro
68+
replicas: 2
69+
scheduler:
70+
resources: {}
71+
resourcesPreset: micro
72+
host: ""
73+
nodeGroups:
74+
md0:
75+
ephemeralStorage: 20Gi
76+
gpus: []
77+
instanceType: u1.medium
78+
maxReplicas: 10
79+
minReplicas: 0
80+
resources:
81+
cpu: ""
82+
memory: ""
83+
roles:
84+
- ingress-nginx
85+
storageClass: replicated
86+
EOF
87+
kubectl wait namespace tenant-test --timeout=20s --for=jsonpath='{.status.phase}'=Active
88+
timeout 10 sh -ec 'until kubectl get kamajicontrolplane -n tenant-test kubernetes-test; do sleep 1; done'
89+
kubectl wait --for=condition=TenantControlPlaneCreated kamajicontrolplane -n tenant-test kubernetes-test --timeout=4m
90+
kubectl wait tcp -n tenant-test kubernetes-test --timeout=2m --for=jsonpath='{.status.kubernetesResources.version.status}'=Ready
91+
kubectl wait deploy --timeout=4m --for=condition=available -n tenant-test kubernetes-test kubernetes-test-cluster-autoscaler kubernetes-test-kccm kubernetes-test-kcsi-controller
92+
kubectl wait machinedeployment kubernetes-test-md0 -n tenant-test --timeout=1m --for=jsonpath='{.status.replicas}'=2
93+
kubectl wait machinedeployment kubernetes-test-md0 -n tenant-test --timeout=5m --for=jsonpath='{.status.v1beta2.readyReplicas}'=2
94+
}

0 commit comments

Comments
 (0)