Skip to content

Commit a587d07

Browse files
committed
feat: lab3
1 parent 98c2e9d commit a587d07

5 files changed

Lines changed: 111 additions & 123 deletions

File tree

lab2/main_test.js

Lines changed: 5 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,124 +1,6 @@
1-
const { test } = require('node:test');
2-
const assert = require('node:assert');
3-
const { Application, MailSystem } = require('./main.js');
4-
const fs = require('fs');
5-
6-
/*
7-
function coverage testing:
8-
- MailSystem
9-
- write
10-
- send
11-
- Application
12-
- getNames
13-
- getRandomPerson
14-
- selectNextPerson
15-
- notifySelected
16-
*/
17-
18-
test('MailSystem write test', (t) => {
19-
const mail = new MailSystem();
20-
const result = mail.write('Test');
21-
assert.equal(result, 'Congrats, Test!');
22-
});
23-
24-
// Test Stub
25-
test('MailSystem send test', (t) => {
26-
const mail = new MailSystem();
27-
const originalRandom = Math.random;
28-
29-
// Test success case
30-
Math.random = () => 1;
31-
assert.equal(mail.send('Test', 'content'), true);
32-
33-
// Test failure case
34-
Math.random = () => 0;
35-
assert.equal(mail.send('Test', 'content'), false);
36-
37-
Math.random = originalRandom;
38-
});
39-
40-
// Application tests
41-
test('Application initialization test', async (t) => {
42-
// 準備測試檔案
43-
fs.writeFileSync('name_list.txt', 'Test1\nTest2\nTest3');
44-
45-
try {
46-
const app = new Application();
47-
await new Promise(resolve => setTimeout(resolve, 100)); // 等待初始化完成
48-
49-
assert(Array.isArray(app.people));
50-
assert(Array.isArray(app.selected));
51-
assert.equal(app.people.length, 3);
52-
assert.equal(app.selected.length, 0);
53-
} finally {
54-
// 清理測試檔案
55-
fs.unlinkSync('name_list.txt');
56-
}
57-
});
58-
59-
60-
test('Application selectNextPerson test', async (t) => {
61-
// 準備測試檔案
62-
fs.writeFileSync('name_list.txt', 'Test1\nTest2\nTest3');
63-
64-
try {
65-
const app = new Application();
66-
await new Promise(resolve => setTimeout(resolve, 100)); // 等待初始化完成
67-
68-
const person1 = app.selectNextPerson();
69-
assert(app.people.includes(person1));
70-
assert.equal(app.selected.length, 1);
71-
72-
const person2 = app.selectNextPerson();
73-
assert(app.people.includes(person2));
74-
assert.equal(app.selected.length, 2);
75-
assert.notEqual(person1, person2);
76-
77-
const person3 = app.selectNextPerson();
78-
assert(app.people.includes(person3));
79-
assert.equal(app.selected.length, 3);
80-
81-
// 當所有人都被選中後,應該返回 null
82-
const person4 = app.selectNextPerson();
83-
assert.equal(person4, null);
84-
} finally {
85-
// 清理測試檔案
86-
fs.unlinkSync('name_list.txt');
87-
}
88-
});
89-
90-
91-
// Mock Object
92-
test('Application notifySelected test', async (t) => {
93-
// 準備測試檔案
94-
fs.writeFileSync('name_list.txt', 'Test1\nTest2');
95-
96-
try {
97-
const app = new Application();
98-
await new Promise(resolve => setTimeout(resolve, 100)); // 等待初始化完成
99-
100-
app.selectNextPerson(); // 選擇第一個人
101-
app.selectNextPerson(); // 選擇第二個人
102-
103-
// Mock MailSystem methods
104-
let writeCount = 0;
105-
let sendCount = 0;
106-
app.mailSystem.write = (name) => {
107-
writeCount++;
108-
return `Congrats, ${name}!`;
109-
};
110-
app.mailSystem.send = (name, context) => {
111-
sendCount++;
112-
return true;
113-
};
114-
115-
app.notifySelected();
116-
assert.equal(writeCount, 2);
117-
assert.equal(sendCount, 2);
118-
} finally {
119-
// 清理測試檔案
120-
fs.unlinkSync('name_list.txt');
121-
}
122-
});
123-
1+
const test = require('node:test');
2+
const assert = require('assert');
3+
const { Application, MailSystem } = require('./main');
1244

5+
// TODO: write your tests here
6+
// Remember to use Stub, Mock, and Spy when necessary

lab3/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Lab3
2+
3+
## Introduction
4+
5+
In this lab, you will write unit tests for functions implemented in `main.js`. You can learn how to use classes and functions in it by uncommenting the code in it. (But remember don't commit them on GitHub)
6+
7+
## Preparation (Important!!!)
8+
9+
1. Sync fork on GitHub
10+
2. `git checkout -b lab3` (**NOT** your student ID !!!)
11+
12+
## Requirement
13+
14+
1. (40%) Write test cases in `main_test.js` and achieve 100% code coverage.
15+
2. (30%) For each function, parameterize their testcases to test the error-results.
16+
3. (30%) For each function, use at least 3 parameterized testcases to test the non-error-results.
17+
18+
You can run `validate.sh` in your local to test if you satisfy the requirements.
19+
20+
Please note that you must not alter files other than `main_test.js`. You will get 0 points if
21+
22+
1. you modify other files to achieve requirements.
23+
2. you can't pass all CI on your PR.
24+
25+
## Submission
26+
27+
You need to open a pull request to your branch (e.g. 312XXXXXX, your student number) and contain the code that satisfies the abovementioned requirements.
28+
29+
Moreover, please submit the URL of your PR to E3. Your submission will only be accepted when you present at both places.

lab3/main.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
class Calculator {
2+
exp(x) {
3+
if (!Number.isFinite(x)) {
4+
throw Error('unsupported operand type');
5+
}
6+
const result = Math.exp(x);
7+
if (result === Infinity) {
8+
throw Error('overflow');
9+
}
10+
return result;
11+
}
12+
13+
log(x) {
14+
if (!Number.isFinite(x)) {
15+
throw Error('unsupported operand type');
16+
}
17+
const result = Math.log(x);
18+
if (result === -Infinity) {
19+
throw Error('math domain error (1)');
20+
}
21+
if (Number.isNaN(result)) {
22+
throw Error('math domain error (2)');
23+
}
24+
return result;
25+
}
26+
}
27+
28+
// const calculator = new Calculator();
29+
// console.log(calculator.exp(87));
30+
// console.log(calculator.log(48763));
31+
32+
module.exports = {
33+
Calculator
34+
};

lab3/main_test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const {describe, it} = require('node:test');
2+
const assert = require('assert');
3+
const { Calculator } = require('./main');
4+
5+
// TODO: write your tests here

lab3/validate.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/bash
2+
3+
# Check for unwanted files
4+
for file in *; do
5+
if [[ $file != "main.js" && $file != "main_test.js" && $file != "README.md" && $file != "validate.sh" ]]; then
6+
echo "[!] Unwanted file detected: $file."
7+
exit 1
8+
fi
9+
done
10+
11+
node=$(which node)
12+
test_path="${BASH_SOURCE[0]}"
13+
solution_path="$(realpath .)"
14+
tmp_dir=$(mktemp -d -t lab3-XXXXXXXXXX)
15+
16+
cd $tmp_dir
17+
18+
rm -rf *
19+
cp $solution_path/*.js .
20+
result=$($"node" --test --experimental-test-coverage) ; ret=$?
21+
if [ $ret -ne 0 ] ; then
22+
echo "[!] testing fails"
23+
exit 1
24+
else
25+
coverage=$(echo "$result" | grep 'all files' | awk -F '|' '{print $2}' | sed 's/ //g')
26+
if (( $(echo "$coverage < 100" | bc -l) )); then
27+
echo "[!] Coverage is only $coverage%"
28+
exit 1
29+
else
30+
echo "[V] Coverage is 100%"
31+
fi
32+
fi
33+
34+
rm -rf $tmp_dir
35+
36+
exit 0
37+
38+
# vim: set fenc=utf8 ff=unix et sw=2 ts=2 sts=2:

0 commit comments

Comments
 (0)