Skip to content

Commit cb37e1b

Browse files
committed
adding backend unit tests in ginkgo framework
Signed-off-by: Nelesh Singla <117123879+nsingla@users.noreply.github.com>
1 parent 3fb014e commit cb37e1b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+12972
-492
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# This workflow runs tests to verify all the API Server REST Endpoints
2+
name: Backend Unit Tests
3+
env:
4+
TESTS_DIR: "./components/backend/handlers"
5+
TESTS_LABEL: "unit"
6+
JUNIT_FILENAME: "junit.xml"
7+
8+
on:
9+
push:
10+
branches: [main]
11+
12+
workflow_dispatch:
13+
inputs:
14+
test_label:
15+
description: "Test label that you want to filter on and run"
16+
default: 'unit'
17+
required: true
18+
type: string
19+
default_namespace:
20+
description: "Default namespace for testing"
21+
default: 'test-namespace'
22+
required: false
23+
type: string
24+
25+
pull_request:
26+
paths:
27+
- '.github/workflows/backend-unit-tests.yml'
28+
- './components/backend/**'
29+
- '!**/*.md'
30+
31+
concurrency:
32+
group: backend-unit-tests-${{ github.event.pull_request.number || github.ref }}
33+
cancel-in-progress: true
34+
35+
jobs:
36+
backend-unit-test:
37+
runs-on: ubuntu-latest
38+
name: Ambient Code Backend Unit Tests
39+
40+
steps:
41+
- name: Checkout code
42+
uses: actions/checkout@v4
43+
44+
- name: Create reports directory
45+
shell: bash
46+
working-directory: ${{ env.TESTS_DIR }}
47+
run: |
48+
mkdir -p reports
49+
50+
- name: Configure Input Variables
51+
shell: bash
52+
id: configure
53+
run: |
54+
TEST_LABEL=${{ env.TESTS_LABEL }}
55+
DEFAULT_NAMESPACE="test-namespace"
56+
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
57+
TEST_LABEL=${{ inputs.test_label }}
58+
DEFAULT_NAMESPACE=${{ inputs.default_namespace }}
59+
fi
60+
61+
{
62+
echo "TEST_LABEL=$TEST_LABEL"
63+
echo "DEFAULT_NAMESPACE=$DEFAULT_NAMESPACE"
64+
} >> "$GITHUB_OUTPUT"
65+
66+
- name: Run Tests
67+
id: run-tests
68+
shell: bash
69+
working-directory: ${{ env.TESTS_DIR }}
70+
run: |
71+
go run github.com/onsi/ginkgo/v2/ginkgo -r -v --cover --keep-going --github-output=true --tags=test --label-filter=${{ steps.configure.outputs.TEST_LABEL }} --junit-report=${{ env.JUNIT_FILENAME }} --output-dir=reports -- -testNamespace=${{ steps.configure.outputs.DEFAULT_NAMESPACE }}
72+
continue-on-error: true
73+
74+
- name: Install Junit2Html plugin and generate report
75+
if: (!cancelled())
76+
shell: bash
77+
run: |
78+
pip install junit2html
79+
junit2html ${{ env.TESTS_DIR }}/reports/${{ env.JUNIT_FILENAME }} ${{ env.TESTS_DIR }}/reports/test-report.html
80+
continue-on-error: true
81+
82+
- name: Configure report name
83+
id: name_gen
84+
shell: bash
85+
run: |
86+
uuid=$(uuidgen)
87+
REPORT_NAME="Backend Unit Tests HTML Report - ${{ github.run_id }}_${{ github.job }}_$uuid"
88+
echo "REPORT_NAME=$REPORT_NAME" >> "$GITHUB_OUTPUT"
89+
90+
- name: Upload HTML Report
91+
id: upload
92+
uses: actions/upload-artifact@v4
93+
if: (!cancelled())
94+
with:
95+
name: ${{ steps.name_gen.outputs.REPORT_NAME }}
96+
path: ${{ env.TESTS_DIR }}/reports/test-report.html
97+
retention-days: 7
98+
continue-on-error: true
99+
100+
- name: Publish Test Summary With HTML Report
101+
id: publish
102+
uses: kubeflow/pipelines/.github/actions/junit-summary@master
103+
if: (!cancelled()) && steps.upload.outcome != 'failure'
104+
with:
105+
xml_files: '${{ env.TESTS_DIR }}/reports'
106+
custom_data: '{\"HTML Report\": \"${{ steps.upload.outputs.artifact-url }}\"}'
107+
continue-on-error: true
108+
109+
- name: Publish Test Summary
110+
id: summary
111+
uses: kubeflow/pipelines/.github/actions/junit-summary@master
112+
if: (!cancelled()) && steps.upload.outcome == 'failure'
113+
with:
114+
xml_files: '${{ env.TESTS_DIR }}/reports'
115+
continue-on-error: true
116+
117+
- name: Mark Workflow failure if test step failed
118+
if: steps.run-tests.outcome != 'success' && !cancelled()
119+
shell: bash
120+
run: exit 1
121+
122+
- name: Mark Workflow failure if test reporting failed
123+
if: (steps.publish.outcome == 'failure' || steps.summary.outcome == 'failure' || steps.upload.outcome != 'success') && !cancelled()
124+
shell: bash
125+
run: exit 1

.github/workflows/go-lint.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,15 @@ jobs:
8989
working-directory: components/backend
9090
args: --timeout=5m
9191

92+
# The backend unit tests require -tags=test (to compile test-only hooks used by handlers tests).
93+
# We lint both production build (default) and test build (with tags) to avoid hiding issues.
94+
- name: Run golangci-lint (test build tags)
95+
uses: golangci/golangci-lint-action@v9
96+
with:
97+
version: latest
98+
working-directory: components/backend
99+
args: --timeout=5m --build-tags=test
100+
92101
lint-operator:
93102
runs-on: ubuntu-latest
94103
needs: detect-go-changes

.github/workflows/test-local-dev.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ jobs:
1111
steps:
1212
- name: Checkout code
1313
uses: actions/checkout@v5
14+
15+
- name: Set up Go
16+
uses: actions/setup-go@v6
17+
with:
18+
go-version-file: 'components/backend/go.mod'
19+
cache-dependency-path: 'components/backend/go.sum'
1420

1521
- name: Install minikube and kubectl
1622
run: |
@@ -58,6 +64,29 @@ jobs:
5864
kubectl describe deployment agentic-operator -n ambient-code | tail -50
5965
exit 1
6066
}
67+
68+
- name: Run backend integration tests (real k8s auth path)
69+
run: |
70+
set -euo pipefail
71+
72+
echo "Setting up ServiceAccount + RBAC for backend integration tests..."
73+
kubectl -n ambient-code create serviceaccount backend-integration-test 2>/dev/null || true
74+
kubectl -n ambient-code create role backend-integration-test \
75+
--verb=get,list \
76+
--resource=configmaps 2>/dev/null || true
77+
kubectl -n ambient-code create rolebinding backend-integration-test \
78+
--role=backend-integration-test \
79+
--serviceaccount=ambient-code:backend-integration-test 2>/dev/null || true
80+
81+
TEST_TOKEN="$(kubectl -n ambient-code create token backend-integration-test)"
82+
echo "::add-mask::$TEST_TOKEN"
83+
84+
echo "Running Go integration tests (skips any external-provider tests without env)..."
85+
cd components/backend
86+
INTEGRATION_TESTS=true \
87+
K8S_TEST_TOKEN="$TEST_TOKEN" \
88+
K8S_TEST_NAMESPACE="ambient-code" \
89+
go test ./tests/integration/... -count=1 -timeout=10m
6190
6291
- name: Run Makefile smoke tests
6392
run: |

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,7 @@ e2e/langfuse/.env.langfuse-keys
132132
# AI assistant configuration
133133
.cursor/
134134
.tessl/
135+
136+
# Test Reporting
137+
logs/
138+
reports/

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ local-test-quick: check-kubectl check-minikube ## Quick smoke test of local envi
356356
@echo "$(COLOR_BLUE)$(COLOR_RESET) Testing namespace..."
357357
@kubectl get namespace $(NAMESPACE) >/dev/null 2>&1 && echo "$(COLOR_GREEN)$(COLOR_RESET) Namespace exists" || (echo "$(COLOR_RED)$(COLOR_RESET) Namespace missing" && exit 1)
358358
@echo "$(COLOR_BLUE)$(COLOR_RESET) Waiting for pods to be ready..."
359-
@kubectl wait --for=condition=ready pod -l app=backend -n $(NAMESPACE) --timeout=60s >/dev/null 2>&1 && \
359+
@kubectl wait --for=condition=ready pod -l app=backend-api -n $(NAMESPACE) --timeout=60s >/dev/null 2>&1 && \
360360
kubectl wait --for=condition=ready pod -l app=frontend -n $(NAMESPACE) --timeout=60s >/dev/null 2>&1 && \
361361
echo "$(COLOR_GREEN)$(COLOR_RESET) Pods ready" || (echo "$(COLOR_RED)$(COLOR_RESET) Pods not ready" && exit 1)
362362
@echo "$(COLOR_BLUE)$(COLOR_RESET) Testing backend health..."

components/backend/.golangci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ linters:
3131
- staticcheck
3232
- govet
3333

34+
# Exclude style checks from test utilities (common patterns in test code)
35+
- path: tests/.*\.go
36+
linters:
37+
- staticcheck
38+
text: "(should not use|should not use dot imports|should not use ALL_CAPS|at least one file)"
39+
3440
# Allow type assertions in K8s unstructured object parsing (intentional pattern)
3541
- path: (handlers|jira)/.*\.go
3642
text: "type assertion"

components/backend/Makefile

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,62 @@ clean: ## Clean build artifacts
1818
# Test targets
1919
test: test-unit test-contract ## Run all tests (excluding integration tests)
2020

21-
test-unit: ## Run unit tests
22-
go test ./tests/unit/... -v
21+
test-unit: ## Run unit tests using Ginkgo
22+
@echo "Running unit tests with Ginkgo..."
23+
ginkgo run --label-filter="unit" --junit-report=reports/junit.xml --json-report=reports/results.json test/unit
24+
25+
test-unit-go: ## Run unit tests with go test (alternative)
26+
go test -v -tags=test ./handlers ./types ./git -timeout=5m
2327

2428
test-contract: ## Run contract tests
2529
go test ./tests/contract/... -v
2630

2731
test-integration: ## Run integration tests (requires Kubernetes cluster)
2832
@echo "Running integration tests (requires Kubernetes cluster access)..."
29-
go test ./tests/integration/... -v -timeout=5m
33+
USE_REAL_CLUSTER=true CLEANUP_RESOURCES=true ginkgo run --label-filter="integration" --timeout=10m
3034

3135
test-integration-short: ## Run integration tests with short timeout
3236
go test ./tests/integration/... -v -short
3337

3438
test-all: test test-integration ## Run all tests including integration tests
3539

40+
# Ginkgo-specific test targets
41+
test-ginkgo: ## Run all tests using Ginkgo framework
42+
@echo "Running all tests with Ginkgo..."
43+
ginkgo run --junit-report=reports/junit.xml --json-report=reports/results.json
44+
45+
test-ginkgo-parallel: ## Run tests in parallel
46+
@echo "Running tests in parallel..."
47+
ginkgo run -p --junit-report=reports/junit.xml --json-report=reports/results.json
48+
49+
test-ginkgo-verbose: ## Run tests with verbose output
50+
@echo "Running tests with verbose output..."
51+
ginkgo run -v --junit-report=reports/junit.xml --json-report=reports/results.json
52+
53+
test-handlers: ## Run handler tests only
54+
@echo "Running handler tests..."
55+
ginkgo run --tags=test --label-filter="handlers" -v
56+
57+
test-types: ## Run type tests only
58+
@echo "Running type tests..."
59+
ginkgo run --tags=test --label-filter="types" -v
60+
61+
test-git: ## Run git operation tests only
62+
@echo "Running git operation tests..."
63+
ginkgo run --tags=test --label-filter="git" -v
64+
65+
test-fast: ## Run tests excluding slow ones
66+
@echo "Running fast tests only..."
67+
SKIP_SLOW_TESTS=true ginkgo run --tags=test --label-filter="!slow"
68+
69+
test-auth: ## Run authentication and authorization tests
70+
@echo "Running auth tests..."
71+
ginkgo run --tags=test --label-filter="auth" -v
72+
73+
test-focus: ## Run specific test by pattern (usage: make test-focus FOCUS="test pattern")
74+
@echo "Running focused tests: $(FOCUS)"
75+
ginkgo run --focus="$(FOCUS)" -v
76+
3677
# Test with specific configuration
3778
test-integration-local: ## Run integration tests with local configuration
3879
@echo "Running integration tests with local configuration..."
@@ -88,7 +129,10 @@ vet: ## Run go vet
88129
go vet ./...
89130

90131
lint: ## Run golangci-lint (requires golangci-lint to be installed)
91-
golangci-lint run
132+
# Lint production build
133+
golangci-lint run --timeout=5m
134+
# Lint test build (handlers unit tests use -tags=test for test-only hooks)
135+
golangci-lint run --timeout=5m --build-tags=test
92136

93137
# Dependency management
94138
deps: ## Download dependencies
@@ -106,6 +150,7 @@ install-tools: ## Install development tools
106150
@echo "Installing development tools..."
107151
go install github.com/cosmtrek/air@latest
108152
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
153+
go install github.com/onsi/ginkgo/v2/ginkgo@latest
109154

110155
# Kubernetes-specific targets for integration testing
111156
k8s-setup: ## Setup local Kubernetes for testing (requires kubectl and kind)

components/backend/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,51 @@ make run
3434
make dev
3535
```
3636

37+
### Local development authentication (DISABLE_AUTH removed)
38+
39+
The backend **does not** support authentication bypass via `DISABLE_AUTH` (or any env-var based bypass).
40+
All authenticated endpoints require a valid Kubernetes/OpenShift token passed via:
41+
42+
- `Authorization: Bearer <token>` (preferred)
43+
- `X-Forwarded-Access-Token: <token>` (when running behind an auth proxy)
44+
45+
#### Option A: OpenShift / CRC (recommended for this repo)
46+
47+
```bash
48+
# Login and obtain a user token
49+
oc login ...
50+
export OC_TOKEN="$(oc whoami -t)"
51+
52+
# Example request
53+
curl -H "Authorization: Bearer ${OC_TOKEN}" \
54+
http://localhost:8080/health
55+
```
56+
57+
#### Option B: kind/minikube (ServiceAccount token for local dev)
58+
59+
```bash
60+
export DEV_NS=ambient-code
61+
kubectl create namespace "${DEV_NS}" 2>/dev/null || true
62+
63+
kubectl -n "${DEV_NS}" create serviceaccount backend-dev 2>/dev/null || true
64+
65+
# Minimal example permissions (adjust as needed)
66+
kubectl -n "${DEV_NS}" create role backend-dev \
67+
--verb=get,list,watch,create,update,patch,delete \
68+
--resource=secrets,configmaps,services,pods,rolebindings 2>/dev/null || true
69+
70+
kubectl -n "${DEV_NS}" create rolebinding backend-dev \
71+
--role=backend-dev \
72+
--serviceaccount="${DEV_NS}:backend-dev" 2>/dev/null || true
73+
74+
export DEV_TOKEN="$(kubectl -n "${DEV_NS}" create token backend-dev)"
75+
76+
curl -H "Authorization: Bearer ${DEV_TOKEN}" \
77+
http://localhost:8080/health
78+
```
79+
80+
> Tip: If you’re running the backend in-cluster (e.g. via `make dev-start`), your client must still send a token; the backend will never fall back to the in-cluster service account for user-initiated operations.
81+
3782
### Build
3883

3984
```bash

0 commit comments

Comments
 (0)