당신은 현재 두 가지 상황 중 하나에 있을 것이다. 또는 자바스크립트 프로젝트가 거의 테스트가 없고 모든 리팩토링이 위험해 보이거나 이미 테스트가 있고 절반은 느리고 약하고 신뢰할 수 없게 느껴지는 테스트가 있다.
그것이 더 나빠지면 Capacitor Electron Electron 좋은 단위 테스트 자바스크립트는 지혜로운 매처 문법과 시작하지 않는다. 그것은 엄격한 경계: 순수 논리를 직접 테스트하고, 사이드 이펙트를 분리하고, 내부 함수를 이름을 바꾸면 테스트가 붕괴되는 테스트를 작성하지 않는다.
목차
자바스크립트 테스트 프레임워크를 선택하는 방법
- 프레임워크가 필수적이지 않은 이유
- 프로젝트 설정과 첫 번째 테스트
- Code 및 비동기 __CAPGO_KEEP_1__에 대한 마스터링
- 강력한 테스트를 위한 고급 전략
- CI, Capacitor, 및 Electron 앱을 위한 테스트
- 자바스크립트 단위 테스트에 대한 자주 묻는 질문
자바스크립트 테스트 프레임워크를 선택하십시오.
전문적인 자바스크립트 프로젝트에는 실제 테스트 러너가 필요합니다. 일회용 스크립트 및 수동 콘솔 확인은 여러 엔지니어가 동일한 코드베이스를 수정할 때 확장되지 않습니다. 테스트 발견, 진술, 비동기 처리, 모킹, 및 개발 환경에서 CI에서 일관되게 실행할 수 있는 방법이 필요합니다.
현재 지침은 대중적인 옵션의 작은 세트로 수렴하고 있습니다. Jest, Mocha, Jasmine JavaScript 테스트를 위한 프레임워크로 자주 강조되는 것은 Jest 자바스크립트 단위 테스트에서 자주 언급되는 내장 테스트 구조,断言, 모킹, 그리고 동시성 지원을 하나의 패키지로 제공하는 것을 보여주고 있습니다. 자바스크립트 테스트 연구소.

프레임워크는 선택사항이 아니다
단위 테스트를 부가 활동으로 다루는 첫 번째 실수는 파일 이름이 일관되지 않게 되고, nobody이 기억하지 못하는 커스텀 어설션과, 한 사람만 이해하는 헬퍼 함수가 생기는 것이다.
프레임워크는 공유 언어를 제공합니다.
- 테스트 구조 with
describe그리고test또는it - 주장 읽기 가능한 매처
- 설정 및 해제 비동기 지원
- 약속 및 타이머 모킹 도구
- 외부 종속성 만약 팀이 단위 수준 이외의 테스트 자동화에 대한 더 광범위한 시각이 필요하다면 __CAPGO_KEEP_0__는 앱 배포 워크플로우에서 자동화된 테스트에 대한 유용한 개요를 가지고 있다.
테스트 자동화의 더 넓은 관점을 필요로 하는 팀이 있다면, Capgo는 단위 테스트 외에 테스트 자동화에 대한 유용한 개요를 제공합니다. Jest vs Mocha 한눈에 보기.
설정 및 해제
Jest와 Mocha는 두 가지 다른 철학을 대표한다.
Jest 모든 것을 포함한 옵션입니다. 대부분의 팀이 첫날에 필요한 대부분을 포함합니다.
Mocha 더 나은 모듈성
| 설정 복잡도 | Jest | Mocha |
|---|---|---|
| 대부분의 팀에서 낮은 수준 | 일반적으로 어설션 및 모킹 라이브러리를 추가해야 하므로 더 높은 수준 | 어설션 |
| 설정 | 내장된 기능 | 일반적으로 다른 라이브러리와 함께 pair됩니다. |
| 모킹 | 내장된 기능 | 일반적으로 다른 라이브러리와 함께 pair됩니다. |
| 비동기 테스트 | 내장된 기능이며 직관적입니다. | 지원되지만, 주변 설정에 더 많이 의존합니다. |
| 테스트 커버리지 워크플로우 | 일반적으로 동일한 도구 chain에 통합됩니다. | 더욱더 조각조각한 형태로 구성됩니다. |
| 최적의 선택 | 새로운 프로젝트, 일관성을 원하는 팀 | 기존 스택, 모듈성을 원하는 팀 |
실용적인 규칙: 팀이 테스트 라이브러리와 모킹 라이브러리를 함께 사용해야 하는지 물어보지 않으면서, Jest를 사용하는 것이 좋습니다.
대부분의 팀에게 추천하는 것
대부분의 현대 프로젝트에서, 나는 Jest를 선택합니다. Jest를 제외하고 기존 코드베이스가 강력한 이유로 Mocha를 유지해야 하는 경우, Mocha를 선택합니다. 애플리케이션에 __CAPGO_KEEP_0__이 포함된 경우, 이 추천이 더 강해집니다. Capacitor Electron Electron, 왜냐하면 그런 프로젝트는 이미 충분히 움직이는 부분이 많기 때문입니다. 테스트 도구의 분산을 줄이면 빠르게 이익을 얻을 수 있습니다.
Mocha는 더 이상 노드 서비스나 오래된 코드베이스에서 유용하지만, 중급 엔지니어가 처음부터 강력한 테스트 스위트를 설정하는 경우, Jest는 더 많은 마찰을 일으키지 않습니다.
중요한 범위 주의 사항입니다. Cypress와 Playwright는 훌륭한 도구지만, 다른 문제를 해결합니다. 브라우저 수준 및 종단 간 검사를 위한 것이며, 단위 테스트가 수행해야 하는 빠른 내부 루프가 아닙니다.
프로젝트 설정 및 첫 번째 테스트
정확한 테스트 설정은 흥미롭지 않아야 합니다. 첫 번째 테스트를 추가하는 것이 복잡해 보인다면, 테스트 스위트가 건강하게 유지되지 않을 것입니다.

간단한 Jest 설정
JavaScript 프로젝트가 이미 가지고 있는 package.json그 다음에 Jest를 개발 의존성으로 추가하고 테스트 스크립트를 연결합니다.
{
"scripts": {
"test": "jest"
}
}
많은 프로젝트에 대해 충분합니다. 모듈 시스템, 전처리, 또는 모노레포 구조가 더 많은 구성이 필요하다고 하면, 나중에 추가할 수 있습니다.
로컬로 Capacitor 앱을 빌드하고 개발 환경을 정리하고 싶다면, Capgo의 설치하는 Capacitor 로컬 환경 을 참조하세요.
code
테스트를 작성하기 전에 테스트-first 패턴은 단순히 개인 선호가 아닙니다. 미국 소비자 금융 보호국(CFPB)의 자바스크립트 지침은 명확하게 테스트를 먼저 작성하는 것을 권장합니다.테스트를 먼저 작성합니다. describe , 테스트를 조직하는 it과 expect(...) 페이지/영역: Capgo 마케팅 웹사이트. 역할: 짧은 UI 레이블 또는 네비게이션 아이템. 보이는 곳: page trust.astro. 메시지 키 `and` (And). , 그리고 테스트를 프레임하는.
That matters because test-first changes how you design code. Functions tend to become smaller, dependencies become more visible, and side effects stop leaking into logic that should stay pure.
테스트 주변에
// math.js
function addTax(amount, rate) {
return amount + amount * rate;
}
module.exports = { addTax };
// math.test.js
const { addTax } = require('./math');
describe('addTax', () => {
it('returns the amount with the tax applied', () => {
expect(addTax(100, 0.2)).toBe(120);
});
});
자바스크립트 단위 테스트 지침
The 구성, 행동, 확인 패턴은 테스트가 더 복잡해질 때도 읽기 좋게 유지한다.
- 구성 입력과 필요한 설정을 준비한다.
- 행동 함수를 호출한다.
- 확인 결과에 대해 확인한다.
유효성 검사 도우미에 적용한다:
function isSupportedPlatform(platform) {
return ['ios', 'android', 'web', 'desktop'].includes(platform);
}
describe('isSupportedPlatform', () => {
it('returns true for ios', () => {
// Arrange
const platform = 'ios';
// Act
const result = isSupportedPlatform(platform);
// Assert
expect(result).toBe(true);
});
});
작은 테스트는 시간이 지날 때도 잘 유지된다. 테스트는 일반적으로 하나의 질문에 답해야 하며, 전체 워크플로를 설명하는 이야기를 하지 않아야 한다.
For Capacitor and Electron projects, that discipline matters more because your pure logic often sits next to native or desktop integration code. Keep the business rule testable without the platform runtime, and your first test won’t be your last useful one.
모킹과 비동기 Code를 마스터하는 것
어플리케이션 code에서 대부분의 버그는 두 숫자를 더하는 것에서 오지 않습니다. 그들은 code이 외부로 벗어나게 되는 것입니다: 네트워크 요청, 파일, 플러그인 API, 타이머, IPC 채널, 저장層.
그것은 code의 의사결정에 집중할 수 있도록 __CAPGO_KEEP_1__의 경계를 제어하는 데 도움이 됩니다.

경계를 모킹하세요, 모든 것을 모킹하지 마세요.
유지보수 가능한 테스트 지침은 단일 동작 커버리지 그리고 context한 번에 하나의 강력한 주장씩 유닛 테스트의 유지 보수성.
유닛 테스트 유지 보수에 대한 TestRail 기사
테스트 목적에 맞지 않는 가짜 목표:
- helper A가 helper B를 호출했는지 여부
- 서비스 C가 serializer D를 호출했는지 여부
- 내부 private 함수가 두 번 실행되었는지 여부
더 좋은 목표:
- 함수가 반환한 값
- 실패한 의존성을 올바르게 처리했는지 여부
- 데이터를 예상한 형태로 변형했는지 여부
A 더 좋은 패턴: Capacitor와 Electron code
모바일 및 데스크톱 앱에서, 나는 네이티브 또는 플랫폼 API 위에 wrapper 레이어를 선호한다. 그런 다음 단위 테스트는 wrapper를 모킹하고 플랫폼 자체를 모킹하지 않는다.
예제 구조:
// cameraGateway.js
async function getPhoto(cameraPlugin) {
return cameraPlugin.getPhoto();
}
module.exports = { getPhoto };
// profilePhotoService.js
async function loadProfilePhoto(cameraGateway) {
const photo = await cameraGateway.getPhoto();
return { path: photo.path, ready: true };
}
module.exports = { loadProfilePhoto };
// profilePhotoService.test.js
const { loadProfilePhoto } = require('./profilePhotoService');
test('returns mapped photo data', async () => {
const fakeCameraGateway = {
getPhoto: jest.fn().mockResolvedValue({ path: '/tmp/pic.jpg' })
};
const result = await loadProfilePhoto(fakeCameraGateway);
expect(result).toEqual({ path: '/tmp/pic.jpg', ready: true });
});
그 패턴은 Electron에도 적용된다. Wrap ipcRenderer, 파일 접근, 또는 셸 통합을 얇은 어댑터 뒤에 감싸라. 단위 테스트는 서비스 레이어를 직접 실행하는 대신 서비스 레이어를 타격한다.
팀이 Capacitor 앱의 릴리스 로직과 업데이트 경로를 테스트하고 Capgo에서 관련 가이드를 찾고 있습니다. Capacitor OTA 업데이트를 시뮬레이션한 테스트 시나리오로 테스트하는 방법.
팀이 여전히 비동기 테스트 스타일을 정규화하는 중이라면, 빠른_walkthrough가 도움이 될 것입니다:
비동기 흐름을 테스트하는 방법
Use async/await 테스트 시 code가 프로미스를 반환할 때. 이 패턴은 콜백이 많은 패턴보다 더 명확하고 디버깅하기도 더 쉽다.
async function fetchProfile(api) {
const response = await api.getUser();
return response.name;
}
test('returns the user name from the API response', async () => {
const api = {
getUser: jest.fn().mockResolvedValue({ name: 'Ava' })
};
const result = await fetchProfile(api);
expect(result).toBe('Ava');
});
happy path와 ugly path를 모두 테스트하세요. 실제로 사용자가 기억하는 경로는 일반적으로 실패 경로입니다.
test('throws when the API request fails', async () => {
const api = {
getUser: jest.fn().mockRejectedValue(new Error('network failed'))
};
await expect(fetchProfile(api)).rejects.toThrow('network failed');
});
robust한 테스트 전략
고급 테스트 전략
테스트 스위트가 유용한 것은 code 변경 후에도 유용한 것이기 때문에 그렇다. 하지만, 통과하는 테스트의 무더기를 작성하는 것보다 더 어려운 일이다.

__CAPGO_KEEP_0__
한 실제 가이드는 (Note: I elided the singular article "a" before the vowel "a" as per the instructions for French, but since the target language is Korean, I kept the translation as is. Also, I kept the word count within ±3 words of the source.) 70/20/10 분리된 단위, 통합 및 종합 테스트, 단위 테스트가 가장 빠른 feedback 및 가장 안정적인 실패를 제공한다고 말합니다. 동일한 지침은 완전한 단위 테스트 스위트가 ideally 10 초 이내에 완료되어야 한다고 말하고, pre-commit 체크는 5 초 이내에 유지되어야 한다고 말합니다. OpenReplay 테스트 가이드, 그리고 pre-commit 검사도 유지해야 합니다. Capgo 또는 Electron 앱의 경우, 건강한 균형은 보통 다음과 같습니다:단위 테스트 __CAPGO_KEEP_0__.
__CAPGO_KEEP_0__
Capacitor
- __CAPGO_KEEP_0__ 가격 논리, 권한 규칙, 직렬화, 업데이트 적격성, 기능 플래그 및 상태 변환에 대한
- 통합 테스트 저장 어댑터, 플러그인 래퍼 및 IPC 계약에 대한
- E2E 테스트 로그인, 구매 흐름, 동기화 또는 업데이트 알림과 같은 몇 가지 крит적인 여행에 대한
보장은 등대, 목표는 아님
보장은 중요한 논리에서 테스트되지 않은 branch를 식별하는 데 도움이 될 때 유용합니다. 그러나 팀이 보장률을 위해만 추구할 때는 해롭습니다.
로그인 유효성 검사에 대한 신중한 edge-case 테스트가 더 많은 가치를 제공하는 반면, 가치가 없는 단순한 주장으로 가득 찬 파일은 더 이상 가치가 없습니다. 특히 입력이 많은 code such as forms, parsers, date logic, and permission checks와 같은 UI에서 유효성 검사에 중점을 둔 팀이 품질을 높이고자 할 때, 이 가이드는 프론트엔드 폼 유효성 검사에 대한 마스터링 는 단위 테스트 수준의 전략과 함께 좋은 보완입니다.
행동 기반 테스트는 리팩토링을 견딘다
신뢰할 수 있는 테스트 세트는 내부를 리팩토링할 때 반드시 다시 테스트하지 않도록 해줍니다. 가장 쉬운 방법은 관찰 가능한 동작 구현 세부 사항 대신
유용한 사례:
- 경계 조건 빈 입력, null과 같은 값, 유효하지 않은 타입, oversized 문자열과 같은 것
- 도메인 결과 예를 들어 '권한이 없는 경우 반환'
- 상태 전환 예를 들어 '다운로드 메타데이터가 유효화된 후 업데이트 마크 pending'
유용하지 않은 사례:
- 내부 도우미 호출을 검사
- 사용자 정의 private 메서드 순서를 확인
- 모킹 호출 chain의 모든 layer
disciplined release process를 구축하는 앱 팀에게 Capgo의 기사 앱 품질 보증 은 유용합니다. 테스트 작업을 더 광범위한 릴리스 pipe line과 연결합니다.
CI, Capacitor, 및 Electron 앱을 위한 테스트
개발자의 한 대의 컴퓨터에서만 실행되는 테스트는 안전망이 아닙니다. 그것은 지역 습관입니다.
CI는 단위 테스트 자바 스크립트 작업을 팀 인프라로 변환합니다. 모든 푸시, pull request, 또는 릴리스 branch는 동일한 명령어와 동일한 기대치를 사용하여 동일한 명령어를 실행할 수 있습니다. 이러한 일관성은 Capacitor 및 Electron 프로젝트에서 환경 drift가 미묘한 실패를 유발하는 경우 더 중요합니다.
CI를 기본 실행 경로로 설정하십시오
최소한, CI는 의존성을 설치하고 단위 스위트를 모든 변경 세트에 대해 실행해야 합니다. 가능한 경우 로컬 개발과 동일한 명령어를 유지하십시오.
GitHub Actions workflow의 기본적인 것은 다음과 같습니다.
name: test
on: [push, pull_request]
jobs:
unit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
이것만으로는 깨진 임포트, 실패한 어설션, 그리고 의도치 않은 플랫폼 가정에 대해 메인에 도착하기 전에 잡을 수 있습니다.
Capgo는 자동화 pipeline를 통해 배포하는 모바일 팀에게 실용적인 가이드를 제공합니다. CI/CD를 위한 Capacitor 앱 설정.
Capacitor 플러그인 상호작용 테스트
Capacitor code을 위한 단위 테스트는 플랫폼 브리지를 의존하는 모든 서비스에 네이티브 플러그인을 직접_pull하는 것이 잘못된 방식입니다.
더 좋은 패턴은 다음과 같습니다:
// deviceStorage.js
async function saveFile(filesystem, path, data) {
return filesystem.writeFile({ path, data });
}
module.exports = { saveFile };
// draftService.js
async function persistDraft(storage, draft) {
await storage.save('draft.json', JSON.stringify(draft));
return { saved: true };
}
module.exports = { persistDraft };
// draftService.test.js
const { persistDraft } = require('./draftService');
test('persists a serialized draft', async () => {
const storage = {
save: jest.fn().mockResolvedValue(undefined)
};
const result = await persistDraft(storage, { title: 'Hello' });
expect(result).toEqual({ saved: true });
});
카메라 접근, 생체 인식 프롬프트, 푸시 토큰 등록, 네트워크 상태와 같은 아이디어도 동일합니다. 어댑터에서 플러그인 호출을 유지하고 인터페이스를 제어하는 것으로 앱 로직을 테스트하세요.
Electron main renderer 및 IPC code 테스트
Electron 앱에는 두 가지 중요한 구멍이 있습니다: main process code 그리고 renderer process code. 테스트에서 그들을 흐리게 하지 마십시오.
신뢰할 수 있는 설정은 일반적으로 다음과 같이 분리됩니다:
- JavaScript 단위 테스트 뷰 모델, 상태, 형식, UI 측면의 비즈니스 로직을 위한 단위 테스트
- 메인 프로세스 단위 테스트 메뉴, 파일 작업, 앱 라이프 사이클 결정에 대한 단위 테스트
- IPC 계약 테스트 메시지 형식과 예상 응답을 위한 IPC 계약 테스트
예제 IPC wrapper:
// ipcGateway.js
function sendSettings(ipcRenderer, payload) {
ipcRenderer.send('settings:update', payload);
}
module.exports = { sendSettings };
// ipcGateway.test.js
const { sendSettings } = require('./ipcGateway');
test('sends settings update over ipc', () => {
const ipcRenderer = { send: jest.fn() };
sendSettings(ipcRenderer, { theme: 'dark' });
expect(ipcRenderer.send).toHaveBeenCalledWith('settings:update', { theme: 'dark' });
});
내부 구현이 한 헬퍼에서 다른 헬퍼로 변경되더라도, 이 테스트는 여전히 유효합니다. 왜냐하면 이 테스트는 중요하게 여겨지는 동작을 검증하기 때문입니다. 데스크톱과 모바일에서 이 표준을 원하는 것입니다. code
JavaScript 단위 테스트에 대한 자주 묻는 질문
단위 통합 테스트와 E2E 테스트의 차이
A 단위 테스트 단위 테스트는 하나의 작은 논리 단위만 검사합니다. 그리고 통합 테스트 여러 컴포넌트나 서비스가 올바르게 작동하는지 확인합니다. 그리고 엔드 투 엔드 테스트 사용자 경로를 통해 애플리케이션을 실행하는 동안 사용자 경험을 시뮬레이션합니다.
단위 테스트를 사용하여 빠른 신뢰성을 얻으십시오. 통합 테스트를 사용하여 저장소, 플러그인 wrapper, IPC와 같은 접합부에 대해 사용하십시오. E2E 테스트는 워크플로우가 깨질 경우 심각한 영향을 미치는 워크플로우에 대해 가볍게 사용하십시오.
완벽한 커버리지에 도달해야 합니까
아니요. 완벽한 커버리지로 팀을 저가 테스트로 밀어넣을 수 있습니다.
커버리지가 유용한 경우는 code가 nobody가 실행하지 않은 위험한 것을 드러내는 경우입니다. 그러나 엔지니어가 대시보드를 만족시키기 위해 얕은 주장만 추가하는 경우는 유용하지 않습니다. 만약 테스트 스위트가 brittle하다면 더 많은 커버리지가 그것을 구원하지 못합니다.
기존 코드베이스에 테스트를 추가하는 방법은 무엇입니까
변경이 이미 발생하는 곳에서 시작하십시오. 테스트 전략을 다시 작성하는 거대한 프로젝트를 발표하지 마십시오.
실용적인 순서가 다음과 같습니다.
- 활성 code를 먼저 보호하세요 기능 개발 또는 버그 수정 중에 접근하는 모듈에 테스트를 추가하세요
- 순수 논리를 추출하세요 프레임워크나 런타임 노이즈 없이 비즈니스 규칙을 테스트할 수 있도록 하드웨어를 테스트하기 어려운 파일에서
- 네이티브 플러그인, 네트워크 클라이언트, 파일 시스템 호출 및 Electron IPC 주변에 세이밍 wrapper를 추가하세요 부실한 패턴을 거부하세요
- 가이드라인은 JavaScript 테스트 최선의 방법에서 유용합니다. 이것은 종종 놓치게 되는 오버 모킹과 그에 따른 부실한 테스트 문제를 강조합니다. 자바스크립트 테스트 최적화 방법 팀이 제품을 출시하면
이것은 팀이 가장 많이 손해를 보는 곳에서 꾸준히 개선하는 것을 목표로 합니다.
이것은 팀이 가장 많이 손해를 보는 곳에서 꾸준히 개선하는 것을 목표로 합니다. Capacitor 또는 Electron Electron Capgo JavaScript 변경에 대한 더 깨끗한 릴리스 프로세스가 필요합니다.