diff --git a/BE/package-lock.json b/BE/package-lock.json index d5cc169..89e3bcd 100644 --- a/BE/package-lock.json +++ b/BE/package-lock.json @@ -39,6 +39,7 @@ "winston": "^3.11.0" }, "devDependencies": { + "@faker-js/faker": "^8.3.1", "@nestjs/cli": "^10.0.0", "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", @@ -1736,6 +1737,22 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@faker-js/faker": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.3.1.tgz", + "integrity": "sha512-FdgpFxY6V6rLZE9mmIBb9hM0xpfvQOSNOLnzolzKwsE1DH+gC7lEKV1p1IbR0lAYyvYd5a4u3qWJzowUkw1bIw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0", + "npm": ">=6.14.13" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", diff --git a/BE/package.json b/BE/package.json index 9e90b57..918f071 100644 --- a/BE/package.json +++ b/BE/package.json @@ -50,6 +50,7 @@ "winston": "^3.11.0" }, "devDependencies": { + "@faker-js/faker": "^8.3.1", "@nestjs/cli": "^10.0.0", "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", diff --git a/BE/test/load-performance/loadtest-social.js b/BE/test/load-performance/loadtest-social.js new file mode 100644 index 0000000..c169298 --- /dev/null +++ b/BE/test/load-performance/loadtest-social.js @@ -0,0 +1,39 @@ +import { SharedArray } from 'k6/data'; +import http from 'k6/http'; +import { check, sleep, group } from 'k6'; +import { setInterval, setTimeout, clearInterval } from 'k6/experimental/timers'; +import moment from 'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js'; +import faker from 'https://cdnjs.cloudflare.com/ajax/libs/Faker/3.1.0/faker.min.js'; + +const tokens = new SharedArray('possible tokens', function () { + const mock_users = JSON.parse(open('./loadtest-mock.json')); + return mock_users.map(({ access_token }) => access_token); +}); + +export let options = { + stages: [ + { duration: '30s', target: 50 }, + { duration: '20s', target: 0 }, + ], + thresholds: { + http_req_duration: ['avg<200', 'p(95)<500', 'max<1000'], + http_reqs: ['rate>100'], + }, +}; + +export default function () { + const token = tokens[__VU % tokens.length]; + const url = 'http://localhost:3000/mates'; + const params = { + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + }; + + const date = moment(faker.date.between('2023-11-23', '2023-11-30')); + check(http.get(`${url}?date=${date}`, params), { + '친구 조회 응답 시간이 1초 이내': (r) => r.timings.duration < 1000, + }); + sleep(3); +} diff --git a/BE/test/load-performance/loadtest-study.js b/BE/test/load-performance/loadtest-study.js index aba731a..18633f2 100644 --- a/BE/test/load-performance/loadtest-study.js +++ b/BE/test/load-performance/loadtest-study.js @@ -1,6 +1,8 @@ import { SharedArray } from 'k6/data'; import http from 'k6/http'; import { check, sleep, group } from 'k6'; +import moment from 'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js'; +import faker from 'https://cdnjs.cloudflare.com/ajax/libs/Faker/3.1.0/faker.min.js'; const tokens = new SharedArray('possible tokens', function () { const mock_users = JSON.parse(open('./loadtest-mock.json')); @@ -9,9 +11,8 @@ const tokens = new SharedArray('possible tokens', function () { export let options = { stages: [ - { duration: '30s', target: 10 }, // 사용자 수를 1분 동안 500까지 증가 - - { duration: '16s', target: 0 }, // 사용자 수를 10초 동안 0으로 감소 + { duration: '30s', target: 50 }, + { duration: '10s', target: 0 }, ], thresholds: { http_req_duration: ['avg<200', 'p(95)<500', 'max<1000'], @@ -25,13 +26,24 @@ export default function () { const params = { headers: { Authorization: `Bearer ${token}`, - 'Content-Type': 'application/json', // JSON Content-Type 헤더 추가 + 'Content-Type': 'application/json', }, }; group('start 응답 시간이 1초 이내', function () { + const start_date = moment(faker.date.between('2023-11-23', '2023-11-30')); + + const start_created_at = faker.date.between( + start_date.format('YYYY-MM-DD'), + start_date.add(1, 'd').subtract(1, 's').format('YYYY-MM-DD'), + ); + const learning_time = faker.random.number({ + min: 60 * 30, + max: 60 * 60 * 5, + }); + const start_body = JSON.stringify({ - date: '2023-11-23', - created_at: '2023-11-23T23:01:02+09:00', + date: start_date, + created_at: start_created_at, type: 'start', learning_time: 0, }); @@ -40,10 +52,10 @@ export default function () { }); sleep(4); const finish_body = JSON.stringify({ - date: '2023-11-23', - created_at: '2023-11-23T23:01:02+09:00', + date: start_date, + created_at: moment(start_created_at).clone().add(learning_time, 's'), type: 'finish', - learning_time: 2222, + learning_time: learning_time, }); check(http.post(url, finish_body, params), { 'finish 응답 시간이 1초 이내': (r) => r.timings.duration < 1000,