Cypress 테스트에서 이메일 흐름 다루기 #frontend@twiliosendgrid
게시 됨: 2020-11-24Twilio SendGrid는 많은 이메일을 보냅니다. 비밀번호 재설정부터 계정 이메일 확인, CSV 이메일 내보내기에 이르기까지 모든 거래 이메일을 보내기 위해 자체 백엔드 서비스를 사용합니다.
우리는 최근에 3조 개가 넘는 이메일이 전송되었다는 거대한 이정표를 통과했습니다.
테스트 환경에서 테스트 이메일을 Gmail과 같은 실제 이메일 받은 편지함 서비스 제공업체로 보내는 것을 피하기 위해 자체 호스팅 Squirrelmail 서버의 테스트 이메일 받은 편지함으로 이메일을 보냅니다. 많은 중요한 흐름은 사용자가 이메일을 확인하고 실행 가능한 링크를 클릭하고 웹 애플리케이션으로 다시 리디렉션한 다음 일부 다운로드 또는 확인 성공 페이지에서 계속 진행해야 합니다.
Squirrelmail 이메일 주소를 필요한 양식에 입력하고, 일부 버튼을 클릭하고, 이메일 링크를 따라가 예상대로 작동하는지 확인하여 이러한 기능을 수동으로 테스트합니다. 새로운 코드가 변경될 때마다 이 작업을 수행하여 어디에서든 회귀하지 않도록 할 수 있지만 원할 때마다 다시 실행할 수 있는 종단 간(E2E) 테스트에서 이러한 단계를 자동화하는 것이 좋습니다. 특히 Cypress를 사용하여 E2E 테스트를 작성하고 싶습니다. 따라서 이러한 잠재적으로 느리고 혼란스러운 이메일 흐름을 매번 자체 웹 브라우저에서 수동으로 테스트할 필요가 없습니다.
이 게시물에 들어가기 전에 먼저 읽어볼 만한 몇 가지 기사가 있습니다.
- 이전에 E2E 테스트를 작성한 적이 없거나 E2E 테스트를 작성할 때 생각하는 방법에 대해 복습하고 싶다면 시작하기 전에 이 블로그 게시물을 보는 것이 좋습니다.
- 일반적으로 E2E 테스트를 작성하기 위해 Cypress를 사용하는 것에 익숙하지 않은 경우 웹 애플리케이션에 대한 Cypress 테스트 구현에 대한 1,000피트 개요를 확인하는 것이 좋습니다. 그러면 Cypress API에 대한 더 나은 아이디어를 얻을 수 있습니다.
이 게시물은 cy.task()
와 같은 Cypress 함수 중 일부를 알고 있다고 가정하여 이메일 처리를 지원하기 위해 노드 서버에서 정의한 임의의 코드를 실행합니다. 또한 TypeScript가 포함된 이후 코드 조각이 약간 혼란스럽다면 Cypress 테스트를 입력한 방법에 대한 블로그 게시물을 보면 문제가 해결될 수 있습니다. 유형 정의를 제거하고 JavaScript 전용 구문을 고수하여 고유한 Cypress 테스트에서 코드를 계속 수정할 수 있습니다.
자체 테스트 이메일 받은 편지함 서버(예: Squirrelmail)를 설정하는 방법은 다루지 않지만 이메일 검색, 일치하는 이메일 콘텐츠 구문 분석 및 이메일 링크 추적과 관련된 이러한 단계를 자동화하는 데 중점을 둘 것입니다. 이렇게 하면 테스트 이메일 받은 편지함 서버와 연결할 고유 자격 증명이 있다고 가정할 때 이러한 이메일 흐름을 처리하기 위해 어떤 종류의 기능을 사용하고 구현해야 하는지 더 잘 알 수 있습니다.
Cypress 테스트에서 이메일 흐름을 어떻게 처리합니까?
전체 이메일 흐름을 테스트하기 위해 다음을 위해 cy.task()
플러그인을 구축했습니다.
- 특정 제목이 포함된 이메일의 경우 이메일 받은 편지함에 연결 및 필터링 처리
- 일치하는 이메일의 본문 내용 검색
- Squirrelmail UI를 통해 로그인할 필요 없이 사용자의 받은 편지함에서 이메일 삭제
우리는 또한 Squirrelmail UI를 소유하거나 제어하지 않기 때문에 이 경로를 택했습니다. Squirrelmail UI의 URL은 배포된 프론트엔드 앱과 별도의 상위 도메인에 있기 때문에 Cypress 테스트에서 둘 이상의 상위 도메인을 방문할 수 없습니다. .
일부 자격 증명 및 호스트 구성을 통해 Squirrelmail 받은 편지함에 연결하도록 IMAP 클라이언트를 설정하는 데 도움이 되도록 "emailjs-imap-client"라는 라이브러리를 먼저 설치했습니다 . 이 라이브러리를 사용하여 squirrelmail.ts
라는 모듈 안에 모든 Squirrelmail 관련 항목을 캡슐화했습니다. 이 모듈은 나중에 cy.task()
함수 정의를 위해 plugins/index.ts
에서 가져올 것입니다.
이메일과 관련된 테스트를 실행하기 전에 이전 테스트에서 트리거된 이전 이메일을 실수로 참조하는 오탐을 방지하기 위해 동일한 제목을 가진 모든 이메일을 분해해야 합니다. 이 사용 사례를 처리하기 위해 다음과 같이 사용자의 받은 편지함에서 제목이 일치하는 모든 이메일을 삭제하는 이 작업을 구현했습니다.
테스트 중에 이메일이 사용자의 Squirrelmail 이메일 주소로 전송되도록 하는 작업을 트리거하고 종종 일치하는 제목 줄이 포함된 이메일이 사용자의 이메일 받은 편지함에 도착할 때까지 기다려야 합니다. 이 프로세스는 백엔드 프로세스의 관련 정도에 따라 몇 초에서 몇 분 정도 걸립니다. 메일 보내기 부분에서 무언가가 작동하지 않거나 지연되는지 알려주기 위해 도착할 때까지 폴링하거나 테스트에서 시간 초과 오류를 제공해야 합니다. 제목이 일치하는 이메일을 사전에 이미 삭제했기 때문에 성공적으로 반환되면 테스트 실행에서 트리거되었다고 확신할 수 있습니다.
다음은 "귀하의 이메일 활동 내보내기" 또는 "발신자 확인"과 같은 특정 제목의 이메일이 사용자의 이메일 받은 편지함에 도착하기를 기다리는 기능을 개발한 방법입니다.
지금까지:
- 사용자의 이메일 받은편지함을 지웠습니다.
- 테스트가 실행되고 이메일이 사용자의 이메일 받은 편지함으로 전송되도록 트리거합니다.
- 이메일이 사용자의 이메일 받은편지함에 도착할 때까지 성공적으로 기다렸습니다.
이제 해당 이메일의 본문 내용을 가져와야 합니다.
고맙게도 일치하는 이메일의 본문 내용을 문자열로 반환할 수 있습니다. 이 문자열은 나중에 작업 링크가 우리가 제어하고 소유한 웹 앱으로 반환하기 위해 구문 분석해야 합니다. 아래의 작업 플러그인은 사용자의 받은 편지함에서 제목이 일치하는 이메일을 검색하고 나중에 사용할 수 있도록 본문 내용을 반환합니다.
간단히 말해서, 우리는 단순히 Squirrelmail 페이지에 대한 페이지 개체를 생성하고, UI를 통해 Squirrelmail을 방문하고, 일치하는 제목 줄을 필터링하고, 이메일을 열고, 실행 가능한 링크를 직접 클릭하고, 다시 즐거운 시간을 보낼 수 없습니다. 동일한 Cypress 테스트에서 여러 슈퍼도메인을 방문할 수 없기 때문입니다. 또한 제어하거나 소유하지 않는 페이지와 애플리케이션을 방문하는 것은 반패턴에 가깝습니다.
테스트에서 트리거한 일치하는 이메일 본문 콘텐츠를 찾은 후 HTML 콘텐츠를 구문 분석하고 작업 링크를 찾고 링크에 대한 HTTP 요청을 트리거한 다음 웹 애플리케이션으로 다시 리디렉션해야 합니다.
이메일 HTML 내용을 구문 분석하고 작업 링크 부분을 찾기 위해 "cheerio"라는 다른 라이브러리를 활용했습니다. 이 라이브러리는 HTML 문자열을 로드하고 jQuery와 유사한 함수를 호출하여 필요한 작업 버튼이나 링크를 추출할 수 있도록 합니다. 링크를 구문 분석한 후에는 cy.request()
를 사용하여 링크에 대한 HTTP 요청을 만들고, 리디렉션 링크를 따라 하나의 수퍼 도메인에서 제어하고 소유한 웹 앱으로 돌아가고, 페이지에서 성공 상태 확인을 진행합니다. 로 리디렉션되었습니다.
귀하의 경우 링크가 이미 적절한 위치를 가리키는 경우 링크에 대한 HTTP 요청을 트리거하고 응답의 리디렉션을 따를 필요가 없습니다. 링크 URL이 이미 웹 앱을 직접 가리키는 경우 링크 경로를 추출하고 cy.visit(linkPath)
를 수행하여 앱으로 다시 리디렉션하는 것을 막을 수 있는 것은 없습니다. Twilio SendGrid 링크의 경우 이메일에 대한 링크 추적이 켜져 있는 경우 링크가 "...sendgrid.net?…", 링크 브랜딩이 켜져 있는 경우 "brandedlink.com"처럼 보일 수 있습니다. 이것이 링크의 즉각적인 "href"가 웹 앱과 일치하지 않기 때문에 HTTP 요청을 만들고 cy.visit(redirectPath)
를 수행하기 위해 리디렉션 경로를 추출해야 하는 이유입니다.
다음은 치어리오로 링크를 찾고, 링크에 HTTP 요청을 하고, 리다이렉트를 따라가는 예이다.
결론
받은 편지함에서 일치하는 이메일로 더 많은 읽기 및 삭제 작업을 수행하기 위해 구현한 많은 cy.task()
플러그인 기능을 안내했습니다. 웹 페이지에서 이러한 이메일 흐름을 트리거하기 전에 사용자의 이메일 받은 편지함 상태를 적절하게 재설정하고 이메일이 받은 편지함에 도착할 때까지 기다렸다가 마지막으로 링크를 따라 성공 상태로 돌아가도록 이러한 기능을 만들었습니다. Cypress 테스트의 주요 단계를 다음과 같이 요약합니다.
-
cy.task(“teardownMatchingEmails”)
를 사용하여 오탐지(false positive)를 방지하기 위해 특정 제목이 있는 모든 이메일을 분해합니다. - API를 통해 사용자에게 로그인한 다음 UI를 통해 일련의 단계를 수행하여 사용자의 이메일 받은 편지함으로 보낼 해당 이메일을 생성합니다.
-
cy.task(“awaitEmailInSquirrelmailInbox”)
를 통해 제목이 일치하는 이메일을 수신하도록 사용자의 이메일 받은 편지함을 폴링합니다. -
cy.task(“squirrelmailSearchBySubject”)
를 사용하여 일치하는 제목 줄과 함께 이메일의 본문 내용을 읽으십시오. - 이메일 본문 HTML 문자열을 전달하고 jQuery와 유사한 구문을 사용하여 요소를 검색하여 치어리오 라이브러리로 적절한 작업 링크를 구문 분석합니다.
-
cy.request(“link”)
를 통해 구문 분석된 이메일 링크에 대한 HTTP 요청을 만들고 웹 앱으로 다시 리디렉션 응답을 따르거나 링크가 이미cy.visit(“emailLinkToWebApp”)
을 사용하여 상위 도메인과 일치하는 경우 해당 경로를 방문합니다.cy.visit(“emailLinkToWebApp”)
. - 성공 상태가 발생했는지 확인하거나 소유한 페이지에서 더 많은 UI 단계를 따르세요.
이 블로그 게시물을 통해 처음부터 끝까지 철저하게 테스트를 시작할 수 있기를 바랍니다. 우리는 이메일 흐름으로 E2E 테스트를 작성하는 것을 피했지만 고맙게도 이러한 Cypress 테스트를 통해 모든 것을 수동으로 회귀 테스트하는 데 소비했던 많은 시간을 절약할 수 있는 방법을 찾았습니다. 많은 단계가 귀하가 소유하거나 제어하지 않는 타사 서비스에 의존하거나 사용자를 다시 특정 상태를 안정적으로.
웹 애플리케이션을 위한 Cypress 테스트 작성에 대해 배운 내용과 관련된 더 많은 블로그 게시물에 관심이 있으시면 다음 기사를 확인하십시오.
- E2E 테스트를 작성할 때 고려해야 할 사항
- Cypress 테스트 작성에 대한 1,000피트 개요
- Cypress 테스트의 모든 것을 TypeScript
- Cypress 테스트 구성, 구성 및 통합을 위한 아이디어
- Docker, Buildkite 및 CICD와 Cypress 테스트 통합