Cypress 변수와 별칭 — 비동기 값 다루기
Cypress 변수와 별칭 — 비동기 값 다루기
Cypress는 비동기 API라서, 처음에는 커맨드가 산출하는 객체를 어떻게 참조하고 비교하고 활용할지 헷갈리기 쉬워요. 이 가이드는 Cypress로 복잡한 상황을 다루는 흔한 패턴을 여러 개 소개해요. 그중 핵심 원칙 하나는 "Cypress 커맨드의 반환값을 변수에 담아 쓰면 안 된다"는 거예요.
출처: Variables and aliases in Cypress | Cypress Documentation
중요: Cypress 커맨드의 반환값을 변수에 할당하거나 그걸로 작업할 수 없어요. 커맨드는 큐에 쌓여 비동기로 실행되기 때문이에요.
// this won't work the way you think it does
const button = cy.get('button')
const form = cy.get('form')
button.click()
클로저로 값에 접근하기
각 Cypress 커맨드가 산출하는 값에 접근하려면 .then()을 써요.
cy.get('button').then(($btn) => {
// $btn is the object that the previous command yielded us
})
네이티브 Promise에 익숙하다면 Cypress의 .then()도 비슷하게 동작한다고 보면 돼요. .then() 안에 더 많은 Cypress 커맨드를 중첩할 수 있어요.
cy.get('button').then(($btn) => {
// store the button's text
const txt = $btn.text()
// submit a form
cy.get('form').submit()
// compare the two buttons' text and make sure they are different
cy.get('button').should(($btn2) => {
expect($btn2.text()).not.to.eq(txt)
})
})
.then() 밖의 커맨드는 중첩된 커맨드가 모두 끝날 때까지 실행되지 않아요. 콜백 함수를 쓰면서 우리는 **클로저(closure)**를 만들었어요. 클로저 덕분에 이전 커맨드에서 한 작업을 참조하는 참조를 계속 유지할 수 있어요.
디버깅
.then() 함수는 debugger를 쓰기에 좋은 기회예요. 커맨드가 실행되는 순서를 이해하고, 각 커맨드가 산출하는 객체를 검사하는 데 도움이 돼요.
cy.get('button').then(($btn) => {
// inspect $btn <object>
debugger
cy.get('[data-testid="countries"]').select('USA').then(($select) => {
// inspect $select <object>
debugger
})
})
별칭으로 값 공유하기
후크(hook)와 테스트 사이에서 객체를 공유하려면 변수 대신 **별칭(alias)**을 쓰는 게 좋아요. cy.as()로 별칭을 만들고, cy.get('@alias')로 참조해요.
beforeEach(() => {
cy.wrap('some value').as('exampleValue')
})
it('works in the first test', () => {
cy.get('@exampleValue').should('equal', 'some value')
})
별칭은 각 테스트가 시작하기 전에 리셋돼요. 그래서 before가 아니라 beforeEach에서 만들어야 각 테스트에서 유효해요. 별칭은 DOM 요소, intercept(네트워크 요청), request 등 여러 대상을 지정할 수 있어요.
정리하면, Cypress 커맨드의 비동기 산출값은 변수에 담지 말고 .then()이나 별칭(cy.as·cy.get('@...'))으로 접근하는 것이 정석이에요. 특히 훅과 테스트 사이에서 값을 공유할 때는 별칭이 필수예요.