-
Notifications
You must be signed in to change notification settings - Fork 4
Automated Tests
Automated tests validate that our applications still work as expected after code changes.
In the practicum, we rely on Jest-based test suites and GitHub Actions to automatically run tests for both backend and frontend projects.
This page uses the NSC Events project as a concrete example of how automated testing is wired into our workflows.
View Automated Testing Overview
In NSC Events, automated tests run in three main places:
- You run tests manually with npm scripts
- Husky pre-push hook runs tests before your code is pushed
- Backend CI (
backend-ci.yml) - Frontend CI (
frontend-ci.yml) - Both run tests on the main branch when relevant files change
-
on-pull-request.ymldetects changes for frontend/backend - Runs only the relevant CI steps for the changed part of the monorepo
Automated testing is therefore:
- Preventive: catches issues before merging
- Selective: runs only where changes happen
- Consistent: the same scripts run locally and in CI
View Backend Test Workflow
The backend lives in nsc-events-nestjs/ and uses a dedicated CI workflow:
File: .github/workflows/backend-ci.yml
name: Backend CI
run-name: NestJS CI
on:
push:
branches: [ main ]
paths:
- 'nsc-events-nestjs/**'
- '!nsc-events-nestjs/**/*.md'
- '!nsc-events-nestjs/LICENSE*'
- '!nsc-events-nestjs/.gitignore'
- '!nsc-events-nestjs/.prettierrc'
- '!nsc-events-nestjs/.eslintrc.js'
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js 22
uses: actions/setup-node@v3
with:
node-version: '22.x'
cache: 'npm'
cache-dependency-path: 'package-lock.json'
- name: Clean install dependencies
run: HUSKY=0 npm ci
- name: Run linter
run: npm run lint
working-directory: ./nsc-events-nestjs
- name: Compile typescript
run: npm run compile
working-directory: ./nsc-events-nestjs
- name: Test coverage
run: npm run test:cov
working-directory: ./nsc-events-nestjs
- name: Build App
run: npm run build --if-present
working-directory: ./nsc-events-nestjsFor backend changes pushed to main:
-
Installs dependencies with
npm ci - Runs lint to catch style and basic issues
- Compiles TypeScript to catch type errors
- Runs Jest tests with coverage via
npm run test:cov - Builds the app via
npm run build
If tests or compilation fail, the workflow fails and flags the problem in GitHub.
The workflow also archives build artifacts and coverage reports, which can be downloaded from the GitHub Actions run.
View Frontend Test Workflow
The frontend lives in nsc-events-nextjs/ and has its own CI workflow:
File: .github/workflows/frontend-ci.yml
name: Frontend CI
run-name: NextJS CI
on:
push:
branches: [ main ]
paths:
- 'nsc-events-nextjs/**'
- '!nsc-events-nextjs/**/*.md'
- '!nsc-events-nextjs/LICENSE*'
- '!nsc-events-nextjs/.gitignore'
- '!nsc-events-nextjs/.prettierrc'
- '!nsc-events-nextjs/.eslintrc.js'
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js 22
uses: actions/setup-node@v3
with:
node-version: "22.x"
cache: "npm"
cache-dependency-path: 'package-lock.json'
- name: Clean install dependencies
run: HUSKY=0 npm ci
- name: Run linter
run: npm run lint
working-directory: ./nsc-events-nextjs
- name: Compile typescript
run: npm run compile
working-directory: ./nsc-events-nextjs
- name: Jest unit tests
run: npm run test
working-directory: ./nsc-events-nextjs
- name: Test coverage
run: npm run test:coverage
working-directory: ./nsc-events-nextjs
- name: Build App
run: npm run build
working-directory: ./nsc-events-nextjsFor frontend changes on main:
- Installs dependencies with
npm ci - Runs ESLint via
npm run lint - Compiles TypeScript via
npm run compile - Runs Jest unit tests via
npm run test - Optionally generates coverage via
npm run test:coverage - Builds the Next.js app via
npm run build
Like the backend, any failure (lint, tests, compile, build) causes the CI check to fail.
View PR-Based Test Behavior
NSC Events uses a monorepo-aware CI workflow for pull requests, so we only run tests for the parts of the repo that changed.
File: .github/workflows/on-pull-request.yml
The dorny/paths-filter action checks whether frontend and/or backend files were modified:
jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
frontend: ${{ steps.filter.outputs.frontend }}
backend: ${{ steps.filter.outputs.backend }}
steps:
- uses: actions/checkout@v3
- uses: dorny/paths-filter@v2
id: filter
with:
filters: |
frontend:
- 'nsc-events-nextjs/**'
- '!nsc-events-nextjs/**/*.md'
- '!nsc-events-nextjs/LICENSE*'
- '!nsc-events-nextjs/.gitignore'
- '!nsc-events-nextjs/.prettierrc'
- '!nsc-events-nextjs/.eslintrc.js'
backend:
- 'nsc-events-nestjs/**'
- '!nsc-events-nestjs/**/*.md'
- '!nsc-events-nestjs/LICENSE*'
- '!nsc-events-nestjs/.gitignore'
- '!nsc-events-nestjs/.prettierrc'
- '!nsc-events-nestjs/.eslintrc.js'If backend code changed, backend becomes true. Same for frontend.
Then we conditionally run the relevant CI job(s):
frontend-ci:
needs: detect-changes
if: needs.detect-changes.outputs.frontend == 'true'
# ... (lint, compile, test, build)
backend-ci:
needs: detect-changes
if: needs.detect-changes.outputs.backend == 'true'
# ... (lint, compile, test:cov, build)- Faster PR checks
- No unnecessary test runs for unaffected code
- Still guarantees coverage for changed areas
View Manual Test Commands
From the repo root, or nsc-events-nestjs directory:
cd nsc-events-nestjs
npm run test # run backend unit tests
npm run test:cov # run tests with coverage reportFrom the repo root, or nsc-events-nextjs directory:
cd nsc-events-nextjs
npm run test # run frontend unit tests
npm run test:coverage # run tests with coverage report- Run tests locally before pushing large feature branches
- Always run
npm run testafter major refactors - Use coverage reports to identify untested critical paths
Home β’ New Student Onboarding β’ Guides β’ Projects β’ Code of Conduct β’ FAQ
Last updated: 12/7/2025