Comprehensive Test Suite #32
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Comprehensive Test Suite | |
| on: | |
| pull_request: | |
| branches: [main, develop] | |
| push: | |
| branches: [main, develop] | |
| schedule: | |
| # Run E2E tests daily at 2 AM UTC | |
| - cron: '0 2 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| run_e2e: | |
| description: 'Run E2E tests' | |
| required: false | |
| type: boolean | |
| default: false | |
| env: | |
| DOTNET_VERSION: '8.0.x' | |
| NODE_VERSION: '20' | |
| jobs: | |
| # Backend Unit and Integration Tests | |
| backend-tests: | |
| name: Backend Tests | |
| runs-on: ubuntu-latest | |
| services: | |
| sqlserver: | |
| image: mcr.microsoft.com/mssql/server:2022-latest | |
| env: | |
| ACCEPT_EULA: Y | |
| SA_PASSWORD: Test123!Strong | |
| MSSQL_PID: Developer | |
| ports: | |
| - 1433:1433 | |
| options: >- | |
| --health-cmd "/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Test123!Strong -Q 'SELECT 1'" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Cache NuGet packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.nuget/packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nuget- | |
| - name: Restore dependencies | |
| working-directory: ./Backend/Podium | |
| run: dotnet restore | |
| - name: Build | |
| working-directory: ./Backend/Podium | |
| run: dotnet build --no-restore --configuration Release | |
| - name: Run tests with coverage | |
| working-directory: ./Backend/Podium | |
| env: | |
| ConnectionStrings__TestDatabase: "Server=localhost,1433;Database=PodiumTest;User Id=sa;Password=Test123!Strong;TrustServerCertificate=True" | |
| run: | | |
| dotnet test --no-build --configuration Release \ | |
| --logger "trx;LogFileName=test-results.trx" \ | |
| --logger "console;verbosity=detailed" \ | |
| /p:CollectCoverage=true \ | |
| /p:CoverletOutputFormat=cobertura \ | |
| /p:CoverletOutput=./TestResults/ | |
| - name: Generate coverage report | |
| if: always() | |
| run: | | |
| dotnet tool install -g dotnet-reportgenerator-globaltool | |
| reportgenerator \ | |
| -reports:"Backend/Podium/**/TestResults/*.cobertura.xml" \ | |
| -targetdir:"coverage-report" \ | |
| -reporttypes:"Html;JsonSummary" | |
| - name: Upload coverage report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: backend-coverage-report | |
| path: coverage-report/ | |
| retention-days: 30 | |
| - name: Publish test results | |
| uses: dorny/test-reporter@v1 | |
| if: always() | |
| with: | |
| name: Backend Test Results | |
| path: '**/TestResults/*.trx' | |
| reporter: dotnet-trx | |
| fail-on-error: true | |
| - name: Upload to Codecov | |
| uses: codecov/codecov-action@v4 | |
| if: always() | |
| with: | |
| files: Backend/Podium/**/TestResults/*.cobertura.xml | |
| flags: backend | |
| name: backend-coverage | |
| # Frontend Unit Tests | |
| frontend-tests: | |
| name: Frontend Unit Tests | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: ./Frontend/podium-frontend | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| cache-dependency-path: Frontend/podium-frontend/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run unit tests with coverage | |
| run: npm run test:ci | |
| - name: Upload coverage report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: frontend-coverage-report | |
| path: Frontend/podium-frontend/coverage/ | |
| retention-days: 30 | |
| - name: Upload to Codecov | |
| uses: codecov/codecov-action@v4 | |
| if: always() | |
| with: | |
| files: Frontend/podium-frontend/coverage/lcov.info | |
| flags: frontend | |
| name: frontend-coverage | |
| # E2E Tests with Playwright | |
| e2e-tests: | |
| name: E2E Tests | |
| runs-on: ubuntu-latest | |
| # Only run E2E tests on: | |
| # - Schedule (daily) | |
| # - Manual trigger with run_e2e input | |
| # - Commits with [e2e] in message | |
| if: | | |
| github.event_name == 'schedule' || | |
| (github.event_name == 'workflow_dispatch' && github.event.inputs.run_e2e == 'true') || | |
| contains(github.event.head_commit.message, '[e2e]') | |
| services: | |
| sqlserver: | |
| image: mcr.microsoft.com/mssql/server:2022-latest | |
| env: | |
| ACCEPT_EULA: Y | |
| SA_PASSWORD: Test123!Strong | |
| ports: | |
| - 1433:1433 | |
| options: >- | |
| --health-cmd "/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Test123!Strong -Q 'SELECT 1'" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| cache-dependency-path: Frontend/podium-frontend/package-lock.json | |
| - name: Start backend | |
| working-directory: ./Backend/Podium | |
| env: | |
| ASPNETCORE_ENVIRONMENT: Testing | |
| ASPNETCORE_URLS: http://localhost:5000 | |
| ConnectionStrings__DefaultConnection: "Server=localhost,1433;Database=PodiumTest;User Id=sa;Password=Test123!Strong;TrustServerCertificate=True" | |
| run: | | |
| dotnet restore | |
| dotnet build --no-restore | |
| nohup dotnet run --project Podium.API/Podium.API.csproj --no-build > backend.log 2>&1 & | |
| # Wait for backend with retry and health check | |
| echo "Waiting for backend to start..." | |
| for i in {1..30}; do | |
| if curl -f http://localhost:5000/health 2>/dev/null; then | |
| echo "Backend is ready!" | |
| break | |
| fi | |
| echo "Attempt $i/30: Backend not ready yet, waiting..." | |
| sleep 2 | |
| done | |
| # Final health check | |
| if ! curl -f http://localhost:5000/health; then | |
| echo "Backend failed to start. Logs:" | |
| cat backend.log | |
| exit 1 | |
| fi | |
| - name: Install frontend dependencies | |
| working-directory: ./Frontend/podium-frontend | |
| run: npm ci | |
| - name: Install Playwright browsers | |
| working-directory: ./Frontend/podium-frontend | |
| run: npx playwright install --with-deps | |
| - name: Run E2E tests | |
| working-directory: ./Frontend/podium-frontend | |
| env: | |
| API_URL: http://localhost:5000 | |
| run: npx playwright test | |
| - name: Upload Playwright report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: playwright-report | |
| path: Frontend/podium-frontend/playwright-report/ | |
| retention-days: 30 | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: playwright-results | |
| path: Frontend/podium-frontend/test-results/ | |
| retention-days: 30 | |
| # Test Summary | |
| test-summary: | |
| name: Test Summary | |
| runs-on: ubuntu-latest | |
| needs: [backend-tests, frontend-tests] | |
| if: always() | |
| steps: | |
| - name: Check test results | |
| run: | | |
| echo "## Test Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "- Backend Tests: ${{ needs.backend-tests.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Frontend Tests: ${{ needs.frontend-tests.result }}" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ needs.backend-tests.result }}" != "success" ] || [ "${{ needs.frontend-tests.result }}" != "success" ]; then | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "❌ Some tests failed. Please review the logs above." >> $GITHUB_STEP_SUMMARY | |
| exit 1 | |
| else | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ All tests passed successfully!" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| # Load Testing (Manual trigger only) | |
| load-tests: | |
| name: Load Tests | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'workflow_dispatch' | |
| services: | |
| sqlserver: | |
| image: mcr.microsoft.com/mssql/server:2022-latest | |
| env: | |
| ACCEPT_EULA: Y | |
| SA_PASSWORD: Test123!Strong | |
| ports: | |
| - 1433:1433 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Start backend | |
| working-directory: ./Backend/Podium | |
| env: | |
| ASPNETCORE_ENVIRONMENT: Testing | |
| ASPNETCORE_URLS: http://localhost:5000 | |
| ConnectionStrings__DefaultConnection: "Server=localhost,1433;Database=PodiumTest;User Id=sa;Password=Test123!Strong;TrustServerCertificate=True" | |
| run: | | |
| dotnet restore | |
| dotnet build --no-restore | |
| nohup dotnet run --project Podium.API/Podium.API.csproj --no-build > backend.log 2>&1 & | |
| # Wait for backend with retry | |
| echo "Waiting for backend to start..." | |
| for i in {1..30}; do | |
| if curl -f http://localhost:5000/health 2>/dev/null; then | |
| echo "Backend is ready!" | |
| break | |
| fi | |
| sleep 2 | |
| done | |
| - name: Install K6 | |
| run: | | |
| sudo gpg -k | |
| sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69 | |
| echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list | |
| sudo apt-get update | |
| sudo apt-get install k6 | |
| - name: Run load tests | |
| working-directory: ./load-tests | |
| env: | |
| API_URL: http://localhost:5000 | |
| run: | | |
| mkdir -p results | |
| k6 run --out json=results/auth-load.json scripts/auth-load.js | |
| k6 run --out json=results/student-search.json scripts/student-search-load.js | |
| - name: Upload load test results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: load-test-results | |
| path: load-tests/results/ | |
| retention-days: 30 |