From ed91a197d3f4150740da09ddb757dcfd80fa8b58 Mon Sep 17 00:00:00 2001 From: ShangHungWan Date: Wed, 28 Feb 2024 21:06:39 +0800 Subject: [PATCH 1/2] feat: lab1 doc: add title's description and branch warning in pr template feat: remove badge requirement in lab1 doc: add sample's link in pr template feat: add automatic PR labeler in github workflow feat: update labeler's event and add github-token fix: validate.sh will failed if there are spaces in node's path doc: remove label instruction in pr template --- .github/pull_request_template.md | 17 ++++++++++ .github/workflows/lab1.yml | 27 ++++++++++++++++ .github/workflows/label.yml | 24 ++++++++++++++ README.md | 1 + lab1/README.md | 19 +++++++++++ lab1/main.js | 55 ++++++++++++++++++++++++++++++++ lab1/main_test.js | 23 +++++++++++++ lab1/validate.sh | 30 +++++++++++++++++ 8 files changed, 196 insertions(+) create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/lab1.yml create mode 100644 .github/workflows/label.yml create mode 100644 lab1/README.md create mode 100644 lab1/main.js create mode 100644 lab1/main_test.js create mode 100755 lab1/validate.sh diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..ab8eabd5 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,17 @@ +## Description + + + + + + +--- + + + + +- [ ] A clear title (name your pr "[LAB{lab_number}] {your_student_id}") +- [ ] A meaningful message for PR, as well as its commits +- [ ] From your specific branch (***not main or other's branch***) merging to your branch +- [ ] Excluding any irrelevant files, such as binaries, text files, or dot files +- [ ] Passing tests/CI diff --git a/.github/workflows/lab1.yml b/.github/workflows/lab1.yml new file mode 100644 index 00000000..62e939c5 --- /dev/null +++ b/.github/workflows/lab1.yml @@ -0,0 +1,27 @@ +name: lab1 + +on: + pull_request: + types: [labeled] + +jobs: + build: + if: ${{ github.event.label.name == 'lab1' }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-22.04] + fail-fast: false + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 1 + - name: dependency (ubuntu) + run: | + curl -fsSL https://deb.nodesource.com/setup_21.x | sudo -E bash - &&\ + sudo apt-get install -y nodejs + - name: grading + run: | + echo "cd lab1" + cd lab1 + ./validate.sh diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml new file mode 100644 index 00000000..4e7902a5 --- /dev/null +++ b/.github/workflows/label.yml @@ -0,0 +1,24 @@ +name: Automatic PR Labeler +on: + pull_request_target: + types: [opened, reopened, edited] + +jobs: + labeler: + runs-on: ubuntu-latest + steps: + - name: Label PR + uses: actions/github-script@v5 + with: + github-token: ${{ secrets.PAT }} + script: | + const { owner, repo, number: issue_number } = context.issue; + const pr = await github.rest.pulls.get({ owner, repo, pull_number: issue_number }); + const title = pr.data.title; + const labRegex = /\[LAB(\d+)\]/i; + + const match = title.match(labRegex); + if (match) { + const labelToAdd = 'lab' + match[1]; + await github.rest.issues.addLabels({ owner, repo, issue_number, labels: [labelToAdd] }); + } diff --git a/README.md b/README.md index 77f96354..067204ec 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # 112-spring-software-testing + Labs for NYCU software testing course in 112 spring diff --git a/lab1/README.md b/lab1/README.md new file mode 100644 index 00000000..779166ca --- /dev/null +++ b/lab1/README.md @@ -0,0 +1,19 @@ +# Lab1 + +## Introduction + +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.` + +## Requirement + +1. Write test cases in `main_test.js` and achieve 100% code coverage. (100%) + +You can run `validate.sh` in your local to test if you satisfy the requirements. + +Please note that you must not alter files other than `main_test.js`. You will get 0 points if you modify other files to achieve requirements. + +## Submission + +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. + +Moreover, please submit the URL of your PR to E3. Your submission will only be accepted when you present at both places. diff --git a/lab1/main.js b/lab1/main.js new file mode 100644 index 00000000..c9aed9f0 --- /dev/null +++ b/lab1/main.js @@ -0,0 +1,55 @@ +// NOTICE: DO NOT MODIFY THE CODE IN THIS FILE +// But you can uncomment code below and run this file to understand how to use the classes + +class MyClass { + constructor() { + this.students = []; + } + + addStudent(student) { + if (!(student instanceof Student)) { + return -1; + } + this.students.push(student); + return this.students.length - 1; + } + + getStudentById(id) { + if (id < 0 || id >= this.students.length) { + return null; + } + return this.students[id]; + } +} + +class Student { + constructor() { + this.name = undefined; + } + + setName(userName) { + if (typeof userName !== 'string') { + return; + } + this.name = userName; + } + + getName() { + if (this.name === undefined) { + return ''; + } + return this.name; + } +} + +// const myClass = new MyClass(); +// const names = ['John', 'Jane', 'Doe', 'Smith']; +// names.forEach(name => { +// const student = new Student(); +// student.setName(name); +// const newStudentId = myClass.addStudent(student); +// const newStudentName = myClass.getStudentById(newStudentId).getName(); +// console.log('[+] Added student with id: %d, name: %s', newStudentId, newStudentName); +// }); + +module.exports = { MyClass, Student }; \ No newline at end of file diff --git a/lab1/main_test.js b/lab1/main_test.js new file mode 100644 index 00000000..74a716b4 --- /dev/null +++ b/lab1/main_test.js @@ -0,0 +1,23 @@ +const test = require('node:test'); +const assert = require('assert'); +const { MyClass, Student } = require('./main'); + +test("Test MyClass's addStudent", () => { + // TODO + throw new Error("Test not implemented"); +}); + +test("Test MyClass's getStudentById", () => { + // TODO + throw new Error("Test not implemented"); +}); + +test("Test Student's setName", () => { + // TODO + throw new Error("Test not implemented"); +}); + +test("Test Student's getName", () => { + // TODO + throw new Error("Test not implemented"); +}); \ No newline at end of file diff --git a/lab1/validate.sh b/lab1/validate.sh new file mode 100755 index 00000000..d64ed954 --- /dev/null +++ b/lab1/validate.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +node=$(which node) +test_path="${BASH_SOURCE[0]}" +solution_path="$(realpath .)" +tmp_dir=$(mktemp -d -t lab1-XXXXXXXXXX) + +cd $tmp_dir + +rm -rf * +cp $solution_path/*.js . +result=$($"node" --test --experimental-test-coverage) ; ret=$? +if [ $ret -ne 0 ] ; then + echo "[!] testing fails" + exit 1 +else + coverage=$(echo "$result" | grep 'all files' | awk -F '|' '{print $2}' | sed 's/ //g') + if (( $(echo "$coverage < 100" | bc -l) )); then + echo "[!] Coverage is only $coverage%" + exit 1 + else + echo "[V] Coverage is 100%" + fi +fi + +rm -rf $tmp_dir + +exit 0 + +# vim: set fenc=utf8 ff=unix et sw=2 ts=2 sts=2: \ No newline at end of file From 224abb481b6202553758682ebe1905ece83a3bc2 Mon Sep 17 00:00:00 2001 From: tsaiet Date: Thu, 29 Feb 2024 21:07:23 +0800 Subject: [PATCH 2/2] first commit --- lab1/main_test.js | 69 +++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/lab1/main_test.js b/lab1/main_test.js index 74a716b4..2e8b75f5 100644 --- a/lab1/main_test.js +++ b/lab1/main_test.js @@ -1,23 +1,46 @@ -const test = require('node:test'); -const assert = require('assert'); -const { MyClass, Student } = require('./main'); - -test("Test MyClass's addStudent", () => { - // TODO - throw new Error("Test not implemented"); -}); - -test("Test MyClass's getStudentById", () => { - // TODO - throw new Error("Test not implemented"); -}); - -test("Test Student's setName", () => { - // TODO - throw new Error("Test not implemented"); -}); - -test("Test Student's getName", () => { - // TODO - throw new Error("Test not implemented"); -}); \ No newline at end of file +const test = require('node:test'); +const assert = require('assert'); +const { MyClass, Student } = require('./main'); + +test("Test MyClass's addStudent", () => { + const mc = new MyClass(); + const st = new Student(); + assert.strictEqual(mc.addStudent(mc), -1); // not Student class + assert.strictEqual(mc.addStudent(st), 0); // 1 students + assert.strictEqual(mc.addStudent(st), 1); // 2 students +}); + +test("Test MyClass's getStudentById", () => { + const mc = new MyClass(); + + const st1 = new Student(); + st1.setName("st1"); + const st2 = new Student(); + st2.setName("st2"); + mc.addStudent(st1); + mc.addStudent(st2); + + assert.strictEqual(mc.getStudentById(-1), null); // id < 0 + assert.strictEqual(mc.getStudentById(2), null); // id >= length + assert.strictEqual(mc.getStudentById(0), st1); // st1 + assert.strictEqual(mc.getStudentById(1), st2); // st2 +}); + +test("Test Student's setName", () => { + const st1 = new Student(); + st1.setName("st1"); + const st2 = new Student(); + st2.setName(1); + + assert.strictEqual(st1.name, "st1"); // st1 + assert.strictEqual(st2.name, undefined); // st2 not a string +}); + +test("Test Student's getName", () => { + const st1 = new Student(); + st1.setName("st1"); + const st2 = new Student(); + + assert.strictEqual(st1.getName(), "st1"); // st1 + assert.strictEqual(st2.getName(), ''); // st2 +});