Module 9

Unit Testing, Github, Github Portfolio, More App Building

๐Ÿš€ Deploying Your Portfolio to GitHub Pages

What is GitHub Pages?

GitHub Pages is a free static site hosting service provided by GitHub. It allows you to host websites directly from your GitHub repositories. Perfect for portfolios, documentation, and personal projects!

Key Benefits:

How to Deploy Your Portfolio

Step 1: Create a GitHub Repository

# Create a new repository on GitHub # Repository name: yourusername.github.io # This special name creates a user/organization site

Step 2: Upload Your Portfolio Files

# Clone the repository git clone https://github.com/yourusername/yourusername.github.io.git # Add your portfolio files # - index.html (main page) # - CSS files # - JavaScript files # - Images and other assets # Commit and push git add . git commit -m "Add portfolio files" git push origin main

Step 3: Enable GitHub Pages

  1. Go to your repository on GitHub
  2. Click Settings tab
  3. Scroll down to Pages section
  4. Under Source, select Deploy from a branch
  5. Choose main branch
  6. Click Save

Step 4: Access Your Site

Your portfolio will be available at: https://yourusername.github.io

Note: It may take a few minutes for your site to be published.

Here is mine if you need to see how it looks on GitHub
Here is the code

The most common errors is not using index.html and also not creating a git repository from the file location.

Repository Structure for GitHub Pages

yourusername.github.io/ โ”œโ”€โ”€ index.html # Main portfolio page โ”œโ”€โ”€ css/ โ”‚ โ””โ”€โ”€ styles.css # Your styles โ”œโ”€โ”€ js/ โ”‚ โ””โ”€โ”€ script.js # Your JavaScript โ”œโ”€โ”€ images/ โ”‚ โ””โ”€โ”€ profile.jpg # Portfolio images โ”œโ”€โ”€ projects/ โ”‚ โ””โ”€โ”€ project1.html # Project pages โ””โ”€โ”€ README.md # Repository description

Important Files:

Custom Domain (Optional)

Using Your Own Domain

Want to use your own domain like www.yourname.com?

  1. Purchase a domain from a domain registrar (GoDaddy, Namecheap, etc.)
  2. Add a CNAME file to your repository:
    # Create a file named 'CNAME' (no extension) # Add your domain name inside: www.yourname.com
  3. Configure DNS with your domain registrar:
    # Add these DNS records: Type: CNAME Name: www Value: yourusername.github.io Type: A Name: @ Value: 185.199.108.153

Best Practices for Portfolio Deployment

โœ… Do's

โŒ Don'ts

UI Test

Enter a number to test the UI:

๐Ÿงช Understanding Software Testing

Unit Tests vs Integration Tests

Unit Tests

Unit tests focus on testing individual functions or components in isolation.

// Example: Testing a single function function add(a, b) { return a + b; } // Unit test assertEquals(add(2, 3), 5); assertEquals(add(-1, 1), 0);

Integration Tests

Integration tests verify that multiple components work together correctly.

// Example: Testing user registration flow function testUserRegistration() { // Test form validation const formData = { email: "test@example.com", password: "123456" }; const validation = validateForm(formData); // Test database connection const user = saveUserToDatabase(formData); // Test email sending const emailSent = sendWelcomeEmail(user.email); // Integration test - all parts work together assertTrue(validation && user && emailSent); }

Frontend vs Backend Testing

Aspect Frontend Testing Backend Testing
What to Test User interface, user interactions, visual elements, client-side logic API endpoints, database operations, business logic, server performance
Tools Jest, Cypress, Playwright, Selenium, React Testing Library Jest, Mocha, Supertest, Postman, database testing tools
Test Types Component tests, UI tests, E2E tests, visual regression tests API tests, database tests, unit tests, load tests
Example Test if button click shows correct modal Test if API returns correct user data

Frontend Testing Examples

Component Testing (React)

import { render, screen, fireEvent } from '@testing-library/react'; import Button from './Button'; test('button shows correct text and handles click', () => { const handleClick = jest.fn(); render(<Button onClick={handleClick}>Click me</Button>); expect(screen.getByText('Click me')).toBeInTheDocument(); fireEvent.click(screen.getByText('Click me')); expect(handleClick).toHaveBeenCalled(); });

UI Testing (Cypress)

describe('Login Form', () => { it('should show error for invalid email', () => { cy.visit('/login'); cy.get('[data-testid=email]').type('invalid-email'); cy.get('[data-testid=submit]').click(); cy.get('[data-testid=error]').should('contain', 'Invalid email'); }); });

Backend Testing Examples

API Testing (Node.js/Express)

const request = require('supertest'); const app = require('./app'); describe('User API', () => { test('GET /api/users returns user list', async () => { const response = await request(app) .get('/api/users') .expect(200); expect(response.body).toHaveProperty('users'); expect(Array.isArray(response.body.users)).toBe(true); }); });

Database Testing

describe('User Model', () => { test('should create user with valid data', async () => { const userData = { email: 'test@example.com', name: 'Test User' }; const user = await User.create(userData); expect(user.email).toBe(userData.email); expect(user.name).toBe(userData.name); }); });

Testing Best Practices

๐Ÿงฉ Arrange-Act-Assert Pattern (AAA)

The Arrange-Act-Assert pattern is a fundamental testing structure that makes tests clear, readable, and maintainable. It divides every test into three distinct sections:

1. Arrange - Set Up Your Test Data

This is where you prepare everything needed for your test. Think of it as "getting ready."

// ARRANGE - Set up test data and conditions const user = { name: "John Doe", email: "john@example.com", age: 25 }; const expectedResult = "Hello, John Doe!";

2. Act - Execute the Code Being Tested

This is where you actually call the function or perform the action you want to test.

// ACT - Call the function we're testing const result = greetUser(user.name);

3. Assert - Verify the Results

This is where you check if the result matches what you expected.

// ASSERT - Check if the result is correct expect(result).toBe(expectedResult);

Complete Example

describe('User Greeting', () => { test('should greet user with their name', () => { // ARRANGE const user = { name: "Alice", email: "alice@example.com" }; const expectedGreeting = "Hello, Alice!"; // ACT const actualGreeting = createGreeting(user.name); // ASSERT expect(actualGreeting).toBe(expectedGreeting); }); });

Why Use Arrange-Act-Assert?

๐ŸŽฏ Benefits

๐Ÿšซ Common Anti-Patterns to Avoid

// BAD: Mixed concerns, hard to read test('user test', () => { const user = { name: "Bob" }; const result = greetUser(user.name); expect(result).toBe("Hello, Bob!"); const user2 = { name: "Alice" }; const result2 = greetUser(user2.name); expect(result2).toBe("Hello, Alice!"); }); // GOOD: Clear AAA structure test('should greet Bob correctly', () => { // ARRANGE const user = { name: "Bob" }; const expected = "Hello, Bob!"; // ACT const result = greetUser(user.name); // ASSERT expect(result).toBe(expected); }); test('should greet Alice correctly', () => { // ARRANGE const user = { name: "Alice" }; const expected = "Hello, Alice!"; // ACT const result = greetUser(user.name); // ASSERT expect(result).toBe(expected); });

Real-World AAA Examples

Frontend Component Test

test('button should show loading state when clicked', () => { // ARRANGE const mockOnClick = jest.fn(); render(<Button onClick={mockOnClick}>Submit</Button>); const button = screen.getByText('Submit'); // ACT fireEvent.click(button); // ASSERT expect(button).toHaveTextContent('Loading...'); expect(mockOnClick).toHaveBeenCalledTimes(1); });

Backend API Test

test('POST /api/users should create new user', async () => { // ARRANGE const userData = { name: 'Jane Smith', email: 'jane@example.com' }; const expectedResponse = { id: expect.any(Number), name: userData.name, email: userData.email }; // ACT const response = await request(app) .post('/api/users') .send(userData); // ASSERT expect(response.status).toBe(201); expect(response.body).toMatchObject(expectedResponse); });

Database Test

test('should save user to database', async () => { // ARRANGE const userData = { name: 'Test User', email: 'test@example.com' }; // ACT const savedUser = await User.create(userData); // ASSERT expect(savedUser.id).toBeDefined(); expect(savedUser.name).toBe(userData.name); expect(savedUser.email).toBe(userData.email); });

AAA in Different Testing Scenarios

Test Type Arrange Act Assert
Unit Test Create test data, mock dependencies Call the function Check return value
Integration Test Set up database, create test records Call API endpoint Verify database state and response
UI Test Navigate to page, set up test data Click buttons, fill forms Check DOM changes, verify state
E2E Test Start application, prepare test environment Perform user actions Verify complete user journey