Skip to content

Commit 050fe3c

Browse files
authored
Merge branch '312555020' into 312555020
2 parents f351ec2 + 2d41d26 commit 050fe3c

File tree

11 files changed

+267
-11
lines changed

11 files changed

+267
-11
lines changed

.github/pull_request_template.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
## Description
22

3-
<!-- You can check sample PR here: (remember delete this link when you create your PR) -->
3+
<!-- You can check sample PR here: (remember to delete this link when you create your PR) -->
44
<https://github.com/SQLab/112-spring-software-testing/pull/2>
55

66
<!-- Please briefly describe your change here -->
77

88
---
99

10-
<!-- Please make sure you're satisfy and fill the following checkboxes -->
10+
<!-- Please make sure you're satisfied and fill in the following checkboxes -->
1111
<!-- A good PR should include the following parts: -->
1212

13-
- [ ] A clear title (name your pr "[LAB{lab_number}] {your_student_id}")
13+
- [ ] A clear title (name your PR "[LAB{lab_number}] {your_student_id}")
1414
- [ ] A meaningful message for PR, as well as its commits
1515
- [ ] From your specific branch (***not main or other's branch***) merging to your branch
1616
- [ ] Excluding any irrelevant files, such as binaries, text files, or dot files
17-
- [ ] Passing tests/CI
18-
- [ ] Add proper label for this PR
17+
- [ ] Passing all CI (You should check it first to pass one of the validations in CI. However, you need to make sure your PR passes all CI after you submit it.)

.github/workflows/PR.yml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: PR automation
2+
on:
3+
pull_request_target:
4+
types: [opened, reopened, edited, ready_for_review]
5+
6+
jobs:
7+
labeler:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- name: Label PR
11+
uses: actions/github-script@v5
12+
with:
13+
github-token: ${{ secrets.PAT }}
14+
script: |
15+
const { owner, repo, number: issue_number } = context.issue;
16+
const pr = await github.rest.pulls.get({ owner, repo, pull_number: issue_number });
17+
const title = pr.data.title;
18+
const labRegex = /\[LAB(\d+)\]/;
19+
const titleRegex = /^\[LAB\d+\] [\da-zA-Z]+$/;
20+
21+
if (!titleRegex.test(title)) {
22+
core.setFailed('PR title does not match the required format. Please use the format [LAB#] student#.');
23+
}
24+
25+
if (pr.data.head.ref !== pr.data.base.ref) {
26+
core.setFailed('The source branch and target branch must be the same.');
27+
}
28+
29+
if (pr.data.base.ref === 'main') {
30+
core.setFailed('The target branch cannot be main.');
31+
}
32+
33+
const match = title.match(labRegex);
34+
if (match) {
35+
const labelToAdd = 'lab' + match[1];
36+
await github.rest.issues.addLabels({ owner, repo, issue_number, labels: [labelToAdd] });
37+
} else {
38+
core.setFailed('No match found in PR title. Please add a label in the format [LAB#] to the PR title.');
39+
}
40+
checklist-check:
41+
runs-on: ubuntu-latest
42+
steps:
43+
- name: Check PR description
44+
uses: actions/github-script@v5
45+
with:
46+
github-token: ${{ secrets.GITHUB_TOKEN }}
47+
script: |
48+
const { owner, repo, number: issue_number } = context.issue;
49+
const pr = await github.rest.pulls.get({ owner, repo, pull_number: issue_number });
50+
const body = pr.data.body;
51+
52+
const checkboxes = body.match(/\- \[[x ]\]/g);
53+
if (!checkboxes || checkboxes.length !== 5) {
54+
core.setFailed('The PR description must contain exactly 5 checkboxes.');
55+
}
56+
57+
const unchecked = body.match(/\- \[ \]/g);
58+
if (unchecked && unchecked.length > 0) {
59+
core.setFailed(`There are ${unchecked.length} unchecked items in the PR description.`);
60+
}

.github/workflows/lab1.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
name: lab1
1+
name: lab1 autograding
22

33
on:
44
pull_request:
5-
types: [labeled]
5+
types: [labeled, synchronize, opened, reopened, ready_for_review]
66

77
jobs:
88
build:
9-
if: ${{ github.event.label.name == 'lab1' }}
9+
if: contains(github.event.pull_request.labels.*.name, 'lab1')
1010
runs-on: ${{ matrix.os }}
1111
strategy:
1212
matrix:
@@ -22,6 +22,5 @@ jobs:
2222
sudo apt-get install -y nodejs
2323
- name: grading
2424
run: |
25-
echo "cd lab1"
2625
cd lab1
2726
./validate.sh

.github/workflows/lab2.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: lab2 autograding
2+
3+
on:
4+
pull_request:
5+
types: [labeled, synchronize, opened, reopened, ready_for_review]
6+
7+
jobs:
8+
build:
9+
if: contains(github.event.pull_request.labels.*.name, 'lab2')
10+
runs-on: ${{ matrix.os }}
11+
strategy:
12+
matrix:
13+
os: [ubuntu-22.04]
14+
fail-fast: false
15+
steps:
16+
- uses: actions/checkout@v1
17+
with:
18+
fetch-depth: 1
19+
- name: dependency (ubuntu)
20+
run: |
21+
curl -fsSL https://deb.nodesource.com/setup_21.x | sudo -E bash - &&\
22+
sudo apt-get install -y nodejs
23+
- name: grading
24+
run: |
25+
cd lab2
26+
./validate.sh

lab1/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Introduction
44

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 `main.js.`
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.
66

77
## Requirement
88

lab1/validate.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ cd $tmp_dir
99

1010
rm -rf *
1111
cp $solution_path/*.js .
12-
result=$($node --test --experimental-test-coverage) ; ret=$?
12+
result=$($"node" --test --experimental-test-coverage) ; ret=$?
1313
if [ $ret -ne 0 ] ; then
1414
echo "[!] testing fails"
1515
exit 1

lab2/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Lab2
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+
## Requirement
8+
9+
1. Write test cases in `main_test.js` and achieve 100% code coverage. Remember to use Mock, Spy, or Stub when necessary, you need to at least use one of them in your test cases. (100%)
10+
11+
You can run `validate.sh` in your local to test if you satisfy the requirements.
12+
13+
Please note that you must not alter files other than `main_test.js`. You will get 0 points if
14+
15+
1. you modify other files to achieve requirements.
16+
2. you can't pass all CI on your PR.
17+
18+
## Submission
19+
20+
You need to open a pull request to your branch (e.g. 311XXXXXX, your student number) and contain the code that satisfies the abovementioned requirements.
21+
22+
Moreover, please submit the URL of your PR to E3. Your submission will only be accepted when you present at both places.

lab2/main.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
const fs = require('fs');
2+
const util = require('util');
3+
const readFile = util.promisify(fs.readFile);
4+
5+
class MailSystem {
6+
write(name) {
7+
console.log('--write mail for ' + name + '--');
8+
const context = 'Congrats, ' + name + '!';
9+
return context;
10+
}
11+
12+
send(name, context) {
13+
console.log('--send mail to ' + name + '--');
14+
// Interact with mail system and send mail
15+
sleep(1000);
16+
// random success or failure
17+
const success = Math.random() > 0.5;
18+
if (success) {
19+
console.log('mail sent');
20+
} else {
21+
console.log('mail failed');
22+
}
23+
return success;
24+
}
25+
}
26+
27+
class Application {
28+
constructor() {
29+
this.people = [];
30+
this.selected = [];
31+
this.mailSystem = new MailSystem();
32+
this.getNames().then(([people, selected]) => {
33+
this.people = people;
34+
this.selected = selected;
35+
});
36+
}
37+
38+
async getNames() {
39+
const data = await readFile('name_list.txt', 'utf8');
40+
const people = data.split('\n');
41+
const selected = [];
42+
return [people, selected];
43+
}
44+
45+
getRandomPerson() {
46+
const i = Math.floor(Math.random() * this.people.length);
47+
return this.people[i];
48+
}
49+
50+
selectNextPerson() {
51+
console.log('--select next person--');
52+
if (this.people.length === this.selected.length) {
53+
console.log('all selected');
54+
return null;
55+
}
56+
let person = this.getRandomPerson();
57+
while (this.selected.includes(person)) {
58+
person = this.getRandomPerson();
59+
}
60+
this.selected.push(person);
61+
return person;
62+
}
63+
64+
notifySelected() {
65+
console.log('--notify selected--');
66+
for (const x of this.selected) {
67+
const context = this.mailSystem.write(x);
68+
this.mailSystem.send(x, context);
69+
}
70+
}
71+
}
72+
73+
// const app = new Application();
74+
// app.selectNextPerson();
75+
// app.selectNextPerson();
76+
// app.selectNextPerson();
77+
// app.notifySelected();

lab2/main_test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const test = require('node:test');
2+
const assert = require('assert');
3+
const { Application, MailSystem } = require('./main');
4+
5+
// TODO: write your tests here
6+
// Remember to use Stub, Mock, and Spy when necessary

lab2/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 lab2-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:

scripts/rebase-all.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/bin/bash
2+
3+
git fetch origin
4+
5+
for branch in $(git branch -r | grep -v HEAD); do
6+
# Remove the "origin/" prefix
7+
branch=${branch#origin/}
8+
9+
if [[ "$branch" != "main" ]]; then
10+
git checkout "$branch"
11+
if [[ $? -ne 0 ]]; then
12+
echo "Checkout failed for branch $branch"
13+
exit 1
14+
fi
15+
git pull origin "$branch"
16+
if [[ $? -ne 0 ]]; then
17+
echo "Pull failed for branch $branch"
18+
exit 1
19+
fi
20+
git rebase main
21+
if [[ $? -ne 0 ]]; then
22+
echo "Rebase failed for branch $branch"
23+
exit 1
24+
fi
25+
git push origin "$branch"
26+
fi
27+
done
28+
29+
git checkout main

0 commit comments

Comments
 (0)