Skip to content

Commit e95bd63

Browse files
committed
added more content for docs-abs...
1 parent 2a758ae commit e95bd63

File tree

7 files changed

+530
-0
lines changed

7 files changed

+530
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"label": "Testing",
3+
"position": 10,
4+
"link": {
5+
"type": "generated-index",
6+
"description": "Don't just write code, write reliable code. Learn the different levels of testing to ensure your backend is bug-free and production-ready."
7+
}
8+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---
2+
sidebar_position: 4
3+
title: "Functional & E2E Testing"
4+
sidebar_label: "4. Functional Testing"
5+
description: "Learn how to test your API endpoints from the outside-in to ensure the business logic works for the user."
6+
---
7+
8+
Functional testing (often called **End-to-End** or **Black Box** testing) doesn't care about your clean code, your design patterns, or your variable names. It only cares about one thing: **"Does the feature actually work for the user?"**
9+
10+
In the **CodeHarborHub** backend, this usually means sending a real HTTP request to your API and checking if you get the correct HTTP response.
11+
12+
## The "Black Box" Concept
13+
14+
Imagine your API is a black box. You can't see inside it.
15+
1. You push a button (Send a `POST` request to `/api/register`).
16+
2. Something happens inside.
17+
3. You check the result (Did I get a `201 Created` status and a Welcome email?).
18+
19+
## Functional vs. Unit Testing
20+
21+
| Feature | Unit Testing | Functional Testing |
22+
| :--- | :--- | :--- |
23+
| **Viewpoint** | Developer (White Box) | User (Black Box) |
24+
| **Goal** | Correctness of logic | Correctness of feature |
25+
| **Example** | Testing the `sum()` function | Testing the `Checkout` process |
26+
| **Dependencies** | Mocked (Fake) | Real (Server + DB) |
27+
28+
## Tools for Functional Testing
29+
30+
To test your API endpoints without opening a browser or using Postman manually, we use **Supertest**. It allows us to "simulate" HTTP requests inside our Jest tests.
31+
32+
### Example: Testing the Signup Endpoint
33+
34+
```javascript
35+
import request from 'supertest';
36+
import app from '../app'; // Your Express app
37+
import { prisma } from '../lib/prisma';
38+
39+
describe('POST /api/auth/signup', () => {
40+
41+
test('should create a new user and return 201', async () => {
42+
// 1. Send the request
43+
const response = await request(app)
44+
.post('/api/auth/signup')
45+
.send({
46+
name: 'Ajay Dhangar',
47+
email: 'test@codeharborhub.com',
48+
password: 'securePassword123'
49+
});
50+
51+
// 2. Assert the HTTP Status
52+
expect(response.status).toBe(201);
53+
54+
// 3. Assert the Response Body
55+
expect(response.body).toHaveProperty('id');
56+
expect(response.body.name).toBe('Ajay Dhangar');
57+
58+
// 4. Verification: Is it actually in the DB?
59+
const userInDb = await prisma.user.findUnique({
60+
where: { email: 'test@codeharborhub.com' }
61+
});
62+
expect(userInDb).not.toBeNull();
63+
});
64+
65+
test('should return 400 if email is missing', async () => {
66+
const response = await request(app)
67+
.post('/api/auth/signup')
68+
.send({ name: 'Ajay' });
69+
70+
expect(response.status).toBe(400);
71+
expect(response.body.message).toMatch(/required/);
72+
});
73+
});
74+
```
75+
76+
## The "Happy Path" vs. "Edge Cases"
77+
78+
In functional testing at **CodeHarborHub**, you must test both:
79+
80+
1. **The Happy Path:** Everything goes perfectly (User enters correct data, server is up).
81+
2. **The Sad Path:** The user makes a mistake (Invalid email, password too short).
82+
3. **The Edge Case:** What happens if a user tries to register with an email that already exists?
83+
84+
## Summary Checklist
85+
86+
* [x] I understand that Functional Testing is "Black Box" testing.
87+
* [x] I know that Functional Tests check the API from the user's perspective.
88+
* [x] I can use **Supertest** to simulate HTTP requests.
89+
* [x] I understand the importance of testing "Sad Paths" and "Edge Cases."
90+
91+
:::info Best Practice
92+
Functional tests are slower than unit tests because they start the entire server and talk to the database. Run them **after** your unit tests have passed to catch "big picture" bugs before you deploy to production!
93+
:::
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
sidebar_position: 3
3+
title: Integration Testing
4+
sidebar_label: "3. Integration Testing"
5+
description: "Learn how to test the interaction between different modules, such as your code and the database."
6+
---
7+
8+
While Unit Tests prove that a single brick is strong, **Integration Tests** prove that the mortar (the glue) holds the bricks together to form a wall.
9+
10+
In a typical **CodeHarborHub** backend, this means testing if your **Service Layer** can successfully talk to your **Database** or an **External API**.
11+
12+
13+
## 🧐 The "Why" Behind Integration Tests
14+
15+
You might have a perfectly working `User` object and a perfectly working `Database`. But if the User object expects a `firstName` and the Database table is named `first_name`, your app will crash.
16+
17+
**Unit tests won't catch this. Integration tests will.**
18+
19+
## What Are We Testing?
20+
21+
In integration testing, we move beyond simple logic and start testing the "edges" of our application:
22+
23+
1. **Database Integration:** Does my query actually return data from PostgreSQL?
24+
2. **API Integration:** Does my app correctly parse the JSON response from a payment gateway?
25+
3. **File System:** Can my app successfully write a PDF report to the `/uploads` folder?
26+
27+
## Setting Up the Environment
28+
29+
Because integration tests touch real systems, they are slower and more complex than unit tests. Here is the professional workflow we use:
30+
31+
<Tabs>
32+
<TabItem value="db-test" label="🗄️ The Test Database" default>
33+
**Never** run integration tests against your "Production" or "Development" database.
34+
1. Create a separate `test_db`.
35+
2. Run **Migrations** to set up the schema.
36+
3. Seed the database with "dummy" data.
37+
4. Wipe the data after the tests finish.
38+
</TabItem>
39+
<TabItem value="env" label="🔑 Environment Variables">
40+
Use a `.env.test` file to point your app to the test database instead of the real one.
41+
</TabItem>
42+
</Tabs>
43+
44+
## Example: Testing a User Service
45+
46+
Let's test if our `UserService` can actually save a user into the database using **Prisma**.
47+
48+
```javascript
49+
import { UserService } from '../services/userService';
50+
import { prisma } from '../lib/prisma';
51+
52+
describe('UserService Integration', () => {
53+
54+
// Clean up the database before each test
55+
beforeEach(async () => {
56+
await prisma.user.deleteMany();
57+
});
58+
59+
test('should successfully create a user in the database', async () => {
60+
const userService = new UserService();
61+
const userData = { name: 'Ajay', email: 'ajay@codeharborhub.com' };
62+
63+
// Act: Call the service that talks to the DB
64+
const newUser = await userService.createUser(userData);
65+
66+
// Assert: Check if it's in the real DB
67+
const dbUser = await prisma.user.findUnique({
68+
where: { email: 'ajay@codeharborhub.com' }
69+
});
70+
71+
expect(dbUser).toBeDefined();
72+
expect(dbUser.name).toBe('Ajay');
73+
});
74+
});
75+
```
76+
77+
## Unit vs. Integration
78+
79+
| Feature | Unit Testing | Integration Testing |
80+
| :--- | :--- | :--- |
81+
| **Scope** | One function | Multiple modules |
82+
| **Dependencies** | Mocked (Fake) | Real (DB, APIs) |
83+
| **Speed** | Milliseconds | Seconds |
84+
| **Debugging** | Easy (Know exactly where) | Harder (Could be the DB, Config, or Code) |
85+
86+
## Summary Checklist
87+
88+
* [x] I understand that integration tests check the "interaction" between modules.
89+
* [x] I know that I should use a dedicated **Test Database**.
90+
* [x] I understand that integration tests catch bugs that unit tests miss (like schema mismatches).
91+
* [x] I know how to use `beforeEach` to keep my test database clean.
92+
93+
:::warning Don't Overdo It!
94+
Because integration tests are slower, don't try to test every single "if/else" condition here. Use **Unit Tests** for the logic and **Integration Tests** just to ensure the connection works!
95+
:::
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
sidebar_position: 1
3+
title: Introduction to Testing
4+
sidebar_label: "1. Why We Test"
5+
description: "Understand the mindset of software testing and why it is the most important habit of a professional developer."
6+
---
7+
8+
Imagine you are building a bridge. You wouldn't wait until the bridge is finished to see if it can hold a car, right? You would test every bolt, every beam, and every cable **during** the build.
9+
10+
In Software Engineering, **Testing** is the process of verifying that your code behaves exactly as you intended. At **CodeHarborHub**, we follow one simple rule: **"If it's not tested, it's already broken."**
11+
12+
## 🧐 The "Confidence" Factor
13+
14+
Why do we spend 30% of our time writing tests?
15+
16+
1. **Fearless Refactoring:** Want to change your code to make it cleaner? If you have tests, you'll know instantly if you broke something.
17+
2. **Documentation:** A test tells other developers (and your future self) exactly how a function is supposed to work.
18+
3. **Cost Savings:** Finding a bug while coding costs **`$1`**. Finding that same bug after it's live costs **`$1,000`** in lost users and emergency fixes.
19+
20+
## The Testing Pyramid
21+
22+
Not all tests are created equal. A professional strategy looks like a pyramid:
23+
24+
### 1. Unit Tests (The Base)
25+
These test the smallest "units" of code (like a single function).
26+
* **Speed:** ⚡ Lightning fast (thousands per second).
27+
* **Cost:** 💰 Very cheap to write.
28+
* **Example:** Testing if a `validateEmail()` function returns `false` for `"invalid-email"`.
29+
30+
### 2. Integration Tests (The Middle)
31+
These test how different parts of your app work together.
32+
* **Speed:** 🐢 Slower (requires a database or an API).
33+
* **Focus:** Does the `User Service` correctly save a user to the `Database`?
34+
35+
### 3. E2E / Functional Tests (The Top)
36+
These test the entire "End-to-End" journey of a user.
37+
* **Speed:** 🐌 Very slow (simulates a real browser/user).
38+
* **Example:** "A user signs up, receives a welcome email, and can log in."
39+
40+
## Manual vs. Automated Testing
41+
42+
At **CodeHarborHub**, we move away from manual clicking and toward **Automated Scripts**.
43+
44+
| Feature | Manual Testing | Automated Testing |
45+
| :--- | :--- | :--- |
46+
| **Execution** | Human-driven (Slow) | Machine-driven (Fast) |
47+
| **Reliability** | Prone to human error | Consistent every time |
48+
| **Cost** | High (Time = Money) | Low (Initial setup only) |
49+
| **Regression** | Hard to repeat | Runs on every "Git Push" |
50+
51+
## The Developer's Toolbox
52+
53+
To start testing in the Node.js ecosystem, you will encounter these terms:
54+
55+
* **Test Runner:** The engine that finds and runs your tests (e.g., **Jest**, **Vitest**, **Mocha**).
56+
* **Assertion Library:** The language used to define success (e.g., `expect(result).toBe(true)`).
57+
* **Mocks/Stubs:** "Fake" versions of real services (like a fake Payment Gateway) so you don't spend real money during tests.
58+
59+
## Summary Checklist
60+
* [x] I understand that testing provides a "Safety Net" for my code.
61+
* [x] I can explain why Unit Tests are the foundation of the pyramid.
62+
* [x] I know the difference between Manual and Automated testing.
63+
* [x] I understand that catching bugs early saves time and money.
64+
65+
:::tip Mindset Shift
66+
Don't think of testing as "finding bugs." Think of it as **defining requirements**. If the test passes, your requirement is met. If it fails, your code hasn't finished its job yet.
67+
:::
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
sidebar_position: 6
3+
title: "Mocking & Stubs"
4+
sidebar_label: "6. Mocking & Stubs"
5+
description: "Learn how to fake external dependencies like APIs and Databases to keep your tests fast and reliable."
6+
---
7+
8+
In a real-world application like **CodeHarborHub**, your code doesn't live in a bubble. It talks to:
9+
* 📧 Email Services (SendGrid/Nodemailer)
10+
* 💳 Payment Gateways (Stripe/Razorpay)
11+
* ☁️ Cloud Storage (AWS S3)
12+
* 🌐 External APIs (GitHub/Google)
13+
14+
If you use the **real** services during testing, your tests will be slow, they might cost you money, and they will fail if the internet goes down. We solve this by using **Mocks** and **Stubs**.
15+
16+
## 🧐 What’s the Difference?
17+
18+
While people often use these terms interchangeably, there is a technical difference:
19+
20+
| Concept | Simple Definition | Analogy |
21+
| :--- | :--- | :--- |
22+
| **Stub** | A "dumb" object that returns a hardcoded value. | A pre-recorded voicemail message. |
23+
| **Mock** | A "smart" object that records *how* it was called. | A spy who reports back: "The target called me twice at 5:00 PM." |
24+
25+
## When to use Mocking?
26+
27+
You should mock any dependency that is **non-deterministic** (unpredictable) or **external**:
28+
29+
1. **Network Requests:** Don't hit a real URL; mock the response.
30+
2. **Time:** If a feature only works on weekends, "mock" the system clock to be a Saturday.
31+
3. **Randomness:** If a function generates a random ID, mock it to always return `123`.
32+
4. **Costly Actions:** Mocking the "Send Email" function so you don't spam real users during testing.
33+
34+
## Mocking with Jest
35+
36+
Let's say we have a function that sends a "Course Completion" email to a student.
37+
38+
### The Service
39+
40+
```javascript title="emailService.js"
41+
export const sendWelcomeEmail = async (email) => {
42+
// Imagine this calls a real API like SendGrid
43+
const response = await fetch('[https://api.sendgrid.com/v3/send](https://api.sendgrid.com/v3/send)', { ... });
44+
return response.ok;
45+
};
46+
```
47+
48+
### The Test
49+
We want to test our `signup` logic without actually sending an email.
50+
51+
```javascript title="auth.test.js"
52+
import * as emailService from './emailService';
53+
import { signupUser } from './auth';
54+
55+
// 1. Tell Jest to "hijack" the email service
56+
jest.mock('./emailService');
57+
58+
test('signup should call the email service', async () => {
59+
// 2. Setup the "Mock" to return a successful value
60+
emailService.sendWelcomeEmail.mockResolvedValue(true);
61+
62+
const result = await signupUser('ajay@example.com');
63+
64+
// 3. Assert: Check if the function was CALLED
65+
expect(emailService.sendWelcomeEmail).toHaveBeenCalledTimes(1);
66+
expect(emailService.sendWelcomeEmail).toHaveBeenCalledWith('ajay@example.com');
67+
expect(result.success).toBe(true);
68+
});
69+
```
70+
71+
## The Dangers of Over-Mocking
72+
73+
Mocking is powerful, but if you mock **everything**, your tests become useless.
74+
75+
* **Bad:** Mocking your own internal database logic in an *Integration Test*. (You want to test the real DB!)
76+
* **Good:** Mocking the Stripe API in a *Unit Test*. (You don't want to charge a real card!)
77+
78+
> **Rule of Thumb:** Mock the things you don't control (3rd party APIs). Don't mock the things you do control (your own logic).
79+
80+
## Summary Checklist
81+
* [x] I understand that Mocks replace "Real-world" unpredictable services.
82+
* [x] I know that **Stubs** provide data, while **Mocks** verify behavior.
83+
* [x] I can use `jest.mock()` to fake a module.
84+
* [x] I understand that over-mocking can lead to tests that pass even when the app is broken.
85+
86+
:::success 🎉 Testing Module Complete!
87+
Congratulations! You've learned how to build a professional testing suite. From **Unit Tests** to **Mocks**, you now have the tools to build a robust, industrial-level backend for **CodeHarborHub**.
88+
:::

0 commit comments

Comments
 (0)