편집 꺼짐
자주쓰는 라이브러리
2025.06.25 01:07:43
예제 : 링크 이동 테스트
cypress.config.ts
import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
baseUrl: "http://localhost:3000", // 기본 주소 추가
setupNodeEvents(on, config) {},
},
component: {
devServer: {
framework: "next",
bundler: "webpack",
},
},
});
localhost를 기본 url로 e2e config에 추가하고
npm run dev
를 실행해 서버를 켜준다.
테스트 코드 작성
cypress/e2e/pages.cy.ts
describe("Navigation", () => {
it("should navigate to the about page", () => {
cy.visit("/");
cy.get('a[href*="about"]').click();
cy.url().should("include", "/about");
});
});
/
에 접속한다about
으로 가는 링크 태그를 찾아 클릭한다/about
에 접속된다.
컴포넌트 작성
app/page.tsx
import Link from "next/link";
export default function Home() {
return (
<div>
<Link href="/about">
<h2>더 알아보기</h2>
</Link>
</div>
);
}
app/about/page.tsx
import Link from "next/link";
export default function About() {
return (
<div>
알아보는 페이지
</div>
);
}
테스팅
npm run cypress:open
으로 E2E 테스트를 클릭하고,
spec에서 pages.cy.ts를 실행하면 테스트가 통과된다.
Cypress 테스트 코드 작성
Cypress는 크게 '선택', '행동', '검증'의 세 단계를 거친다.
선택
cy.get(선택자)
의 구조를 띄며 선택자는 document.querySelector()
와 같은 css 선택자를 사용한다.
cy.get('input[name="email"]') // name="email"인 input 태그 선택
선택자 | 의미 | 예시 |
---|---|---|
태그 | 특정 태그 | cy.get('button') |
클래스 | .클래스명 | cy.get('.submit-btn') |
ID | #아이디명 | cy.get('#login-form') |
속성 | [속성=값] | cy.get('[name="email"]') |
복합 | div.class#id | cy.get('form.login-form') |
포함 텍스트 | cy.contains() 사용 | cy.contains('로그인') |
cy.contains(매처)
는 요소의 text가 특정 값인 첫번째 태그를 찾는다.
<div>
<button class="login-button">로그인</button>
<a href="/signup">회원가입</a>
</div>
cy.get('button') // 버튼이 하나뿐일 땐 가능
cy.get('.login-button') // 클래스 기준
cy.get('button.login-button') // 태그 + 클래스
cy.get('a[href="/signup"]') // 태그 + 속성
cy.contains('로그인') // <button>로그인</button> 찾음
cy.contains('회원가입') // <a>회원가입</a> 찾음
cy.contains('button', '로그인') // 태그가 button인 요소 중 '로그인' 찾음
cy.contains('.login-button', '로그인') // 클래스가 login-button인 요소 중 '로그인' 포함된 것 찾음
행동 명령어
명령어 | 설명 |
---|---|
.click() | 클릭 |
.type() | 텍스트 입력 |
.clear() | 입력값 제거 |
.check() / .uncheck() | 체크박스 조작 |
.select() | 드롭다운 선택 |
.focus() / .blur() | 포커스/포커스 해제 |
.scrollIntoView() | 스크롤 이동 |
.trigger() | 이벤트 직접 실행 |
1. .click()
클릭
cy.get('button').click()
- 일반적인 클릭
- 좌표 클릭도 가능:
.click(50, 20)
- force 클릭도 가능:
.click({ force: true })
(숨겨진 버튼 강제 클릭)
2. .type()
텍스트 입력
cy.get('input[name="email"]').type('hello@example.com')
- 기본적으로 실제 사람이 타이핑하듯 입력됨
- 빠르게 입력:
.type('hello', { delay: 0 })
- 특수 키 지원:
{enter}
,{esc}
,{backspace}
등
cy.get('input').type('비밀번호123{enter}')
3. .clear()
입력된 텍스트 지우기
cy.get('input[name="search"]').clear()
.type()
전에 호출하면 항상 초기화 가능
4. .check()
, .uncheck()
체크박스 선택/해제
cy.get('input[type="checkbox"]').check()
cy.get('input[type="checkbox"]').uncheck()
value
기반으로도 선택 가능
cy.get('[type="checkbox"]').check(['A', 'B']) // 여러 개 체크
5. .select()
드롭다운에서 옵션 선택
cy.get('select').select('남자')
cy.get('select').select('male') // value 속성 기반
6. .focus()
/ .blur()
포커스 주기 / 포커스 해제
cy.get('input').focus()
cy.get('input').blur()
.blur()
는 유효성 검사 등 포커스 해제 이벤트 트리거할 때 사용
7. .scrollIntoView()
요소로 스크롤 이동
cy.get('#target').scrollIntoView()
- 안 보이는 요소를 클릭하기 전에 스크롤해 올려야 할 때 유용
8. .trigger('event')
강제로 이벤트 발생시키기
cy.get('input').trigger('mouseover')
cy.get('form').trigger('submit')
- 마우스 hover, submit, keydown 등 직접 이벤트 트리거 가능
9. .dblclick()
/ .rightclick()
마우스 추가 동작
cy.get('button').dblclick()
cy.get('button').rightclick()
10. .check()
/ .select()
조건
동작 | 설명 |
---|---|
.check() | 체크박스 또는 라디오 버튼 |
.select() | <select><option> 구조 |
.click() | 거의 모든 요소 클릭 가능 |
.type() | <input> , <textarea> 등 입력 요소만 가능 |
예시 시나리오
cy.visit('/login')
cy.get('input[name="email"]').type('abc@example.com')
cy.get('input[name="password"]').type('123456{enter}') // enter로 로그인
cy.url().should('include', '/dashboard')
cy.get('button.logout').click()
cy.url().should('include', '/login')
검증
선택한 요소에 대해 should로 검증 조건을 추가하고,
해당 조건을 통해 테스트 Pass, Fail이 결정된다.
.should()
는 기본적으로 500ms 간격으로 4초 동안 재시도- 기본 문법
cy.get('선택자').should('검사조건', '기대값')
.and
로 체이닝 가능cy.get('input').should('have.value', 'hello').and('be.visible')
자주 쓰는 검사 조건
검사 조건 | 설명 | 예시 |
---|---|---|
exist | 요소가 존재함 | cy.get('input').should('exist') |
be.visible | 화면에 보임 (숨김 요소 아님) | cy.get('button').should('be.visible') |
have.text | 정확한 텍스트 | cy.get('h1').should('have.text', '로그인') |
contain.text | 포함된 텍스트 | cy.get('h1').should('contain.text', '로그') |
have.value | <input> 의 값 | cy.get('input').should('have.value', 'abc') |
have.attr | 특정 속성 존재 여부 | cy.get('a').should('have.attr', 'href', '/home') |
have.class | 특정 클래스 존재 | cy.get('div').should('have.class', 'active') |
have.length | 요소 개수 확인 | cy.get('.item').should('have.length', 3) |
be.checked | 체크박스/라디오가 체크됨 | cy.get('input[type="checkbox"]').should('be.checked') |
not.be.checked | 체크 안 되어 있음 | cy.get('input').should('not.be.checked') |
include | URL, 배열 등에 포함됨 | cy.url().should('include', '/dashboard') |
예시 시나리오
cy.url().should('include', '/dashboard')
cy.get('button').should('exist').and('be.visible') // 버튼이 보이는지 확인
cy.get('input[name="email"]').should('have.value', 'abc@example.com') // 입력값 확인
cy.get('h1').should('contain.text', '환영합니다') // 텍스트 포함 여부