제대로 된 통합 테스트를 하려면 인프라를 완벽하게 설정해야 합니다. 특히 개발자 랩톱, CI 노드 또는 테스트를 실행해야 하는 다른 머신을 지원해야 하는 경우 이 작업을 수행하기가 다소 어려울 수 있습니다. 이 문제를 해결하는 좋은 해결책은 컨테이너를 공통 런타임으로 사용하는 것입니다. Docker는 모든 머신에서 동일하게 작동합니다. 따라서 개발자 노트북과 CI 노드에 설치되어 있기만 하면 됩니다.) 그래서 다시 한 번 다음을 사용하여 이 작업을 수행하는 방법을 보여드리겠습니다. 테스트 컨테이너.
테스트 대상
여행 샘플로 Couchbase를 테스트할 수 있는 훌륭한 샘플 앱이 있습니다. Java 백엔드는 여기에 있습니다. https://github.com/couchbaselabs/try-cb-java/ 그리고 여기 프론트엔드 https://github.com/couchbaselabs/try-cb-frontend/. 이를 통해 N1QL, FTS 또는 하위 문서와 같은 다양한 기능을 이해할 수 있습니다. 카우치베이스 학습을 시작하기에 좋은 곳입니다. 배우기에는 좋은 곳이지만 아직 통합 테스트가 없습니다. 그래서 저는 이 문제를 해결하기 위해 새로운 프로젝트를 시작했습니다. 이 프로젝트는 다음에서 사용할 수 있습니다. https://github.com/couchbaselabs/try-cb-integration-test. 이것이 오늘 제가 쓸 내용입니다.
테스트 설정
프론트엔드를 테스트하기 위해 셀레늄을 사용하겠습니다. 기본적으로 페이지를 클릭할 위치를 지정하고, 키 입력을 입력하고, 페이지의 콘텐츠를 확인할 수 있습니다. 따라서 셀레늄 드라이버에 특정 URL에서 페이지를 로드하고, 페이지가 올바르게 로드되었는지 확인하고, 링크를 클릭하고, 새 페이지가 원하는 페이지로 이동했는지 확인할 수 있습니다. 오늘은 여기까지가 테스트의 전부입니다. 여기서 중요한 것은 이를 설정하는 방법입니다. 먼저 제 테스트 코드를 살펴보세요:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
@테스트 public void testTab() 던지기 중단된 예외 { 원격 웹 드라이버 드라이버 = 크롬.getWebDriver(); 드라이버.get("http://trycbfront"); 웹 요소 사용자 이름 필드 = (new 웹 드라이버 대기(드라이버, 10)) .까지(예상 조건.presenceOfElementLocated(으로.이름("username"))); // 가입 사용자 이름 필드.sendKeys("ld@cb.com"); 드라이버.이름별 요소 찾기("비밀번호").sendKeys("비밀번호"); 드라이버.태그 이름으로 요소 찾기("버튼").클릭(); // 가입 확인 문자열 textElement = (new 웹 드라이버 대기(드라이버, 10)) .까지(예상 조건.presenceOfElementLocated(으로.xpath(("/html/body/app-root/div/div[2]/div[1]/div/div[2]/app-home/div[1]/div/div[1]/div/div[1]/div/div/div[2]/div/small/strong")))).getText(); Assert.assertEquals("항공편 찾기", textElement); // 장바구니 페이지 테스트 장바구니 탐색(드라이버); textElement = (new 웹 드라이버 대기(드라이버, 10)) .까지(예상 조건.presenceOfElementLocated(으로.xpath(("/html/body/app-root/div/div[2]/div[1]/div/div[2]/app-cart/div[1]/button")))).getText(); Assert.assertEquals("장바구니 지우기", textElement); } public void 장바구니 탐색(원격 웹 드라이버 드라이버) { 드라이버.찾기 엘리먼트 경로("/html/body/app-root/div/div[2]/div[1]/div/div[1]/div/app-navbar/div/div[3]/div/a[2]").클릭(); } |
셀레늄에 익숙하다면 크고 긴 XPath 값을 보고 눈이 아플 것입니다. 대부분의 애플리케이션에서 이 값은 찾고자 하는 DOM 요소의 ID로 대체됩니다. 이제 이 문제를 해결했으니 첫 번째 줄을 살펴보겠습니다: 리모트웹드라이버 드라이버 = 크롬.get웹드라이버();
셀레늄 드라이버는 크롬 객체로 제공되었습니다. 이 객체는 셀레늄을 실행하는 컨테이너를 나타냅니다. 테스트 컨테이너와 셀레늄 통합 덕분에 가능합니다. 하지만 컨테이너이기 때문에 다른 것에 액세스하려면 컨테이너에서 빌드하거나 다른 컨테이너에 연결해야 합니다. 물론 그렇게 했습니다. 트래블 샘플을 실행하려면 세 가지가 필요합니다. 카우치베이스 서버, 트래블 샘플 백엔드, 트래블 샘플 프론트엔드가 필요하며, 모두 자체 컨테이너에 있는 것이 바람직합니다. 다행히도 저희는 이들 각각에 대한 Docker 이미지를 보유하고 있습니다. 아래에서 프로젝트 Readme 를 만들 수 있습니다.
이 모든 것이 작동하려면 특정 순서대로 시작해야 합니다. 먼저 백엔드에 필요하므로 Couchabse를 시작하세요. 프론트엔드에 필요하기 때문에 백엔드를 시작하는 것보다 셀레늄과 브라우저를 포함하는 셀레늄 이미지에 필요하기 때문에 프론트엔드를 시작하는 것이 좋습니다. 따라서 다른 컨테이너를 시작하기 전에 각 컨테이너가 시작되고 준비되었는지 확인해야 합니다. 준비되었다고 말하는 이유는 경우에 따라 시작과 다를 수 있기 때문입니다. 카우치베이스 컨테이너를 시작하면 컨테이너를 구성해야 합니다. 백엔드용 Spring Boot 애플리케이션의 경우, 가동되고 연결을 수락할 준비가 되려면 시간이 좀 걸립니다. 다행히 테스트 컨테이너는 이 점을 고려하여 몇 가지 흥미로운 대기 메커니즘을 제공합니다.
카우치베이스 컨테이너부터 시작하겠습니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public 정적 final 문자열 클러스터 사용자 = "관리자"; public 정적 final 문자열 클러스터 비밀번호 = "비밀번호"; public 정적 카우치베이스 컨테이너 카우치베이스 컨테이너 = new 카우치베이스 컨테이너() .withFTS(true) .withIndex(true) .withQuery(true) .위드 트래블 샘플(true) .withClusterUsername(클러스터 사용자) .위드클러스터패스워드(클러스터 비밀번호) .위드뉴버킷(기본 버킷 설정.빌더().활성화Flush(true).이름("default").할당량(100).복제본(0).유형(버킷 유형.터치베이스).빌드()); 정적 { 카우치베이스 컨테이너.시작(); } |
이 유창한 API로 쉽게 구성할 수 있다는 것을 알 수 있습니다. 여기서는 FTS, 인덱스 및 쿼리 서비스가 활성화되고 여행 샘플이 미리 로드되며 사용자 이름과 비밀번호, 기본 버킷도 사용하도록 설정하고 있습니다.
일반적으로 테스트 컨테이너를 사용하면 테스트에 @ClassRule이 있습니다. 그러면 컨테이너가 자동으로 시작됩니다. 하지만 @ClassRule로 모든 것을 동시에 시작하게 됩니다. 안타깝게도 앞서 설명한 것처럼 컨테이너는 다음 컨테이너를 시작하기 전에 가동되고 준비되어야 하기 때문에 그렇게 할 수 없습니다. 따라서 정적 코드 블록을 추가하여 이 문제를 해결할 수 있습니다. 이 코드들은 모두 순서대로 실행됩니다. 따라서 시작 블록에서 컨테이너를 시작하면 다음 정적 블록이 시작되기 전에 컨테이너가 가동되고 준비되었는지 확인할 수 있습니다. CouchbaseContainer 대기 전략은 Couchbase의 REST API 상태를 폴링하고 노드 상태가 건강한지 확인하여 준비된 것으로 간주하고 대기를 중지합니다. CouchbaseContainer에 대한 자세한 내용을 보려면 다음 코드를 참조하세요. 여기 그리고 또한 이전 블로그 게시물 카우치베이스와 테스트 컨테이너에 대해 알아보세요.
다음 단계는 Couchbase가 가동되고 준비되었으므로 Java 백엔드를 시작하는 것입니다:
1 2 3 4 5 6 7 8 9 10 11 |
public 정적 제네릭 컨테이너 trycbBack = new LinkedContainer("trycb/java:최신") .위드링크투컨테이너(카우치베이스 컨테이너, "couchbase") .노출된 포트(8080) .위드 커맨드("-Dspring.couchbase.bootstrap-hosts="+카우치베이스 컨테이너.getContainerIpAddress()) .기다리는(new HttpWaitStrategy().forPath("/wut").forStatusCode(404)); 정적 { trycbBack.시작(); } |
여기서 주목해야 할 몇 가지 흥미로운 점이 있습니다. 앞서 설명한 것과 같은 이유로 컨테이너를 시작하는 정적 블록이 존재한다는 점입니다. 여기서 포트 8080을 노출하고 있는 것을 볼 수 있습니다. CouchbaseContainer에는 기본 Couchbase 이미지 전용의 특정 클래스가 있으므로 이 작업을 수행할 필요가 없습니다. 따라서 포트에 대한 기본 구성과 사전 정의된 대기 전략이 있습니다. 백엔드에서는 GenericContainer를 사용하므로 이를 지정해야 합니다. 대기 전략은 구성된 경로에 대해 404를 받을 때까지 기다립니다. 기본적으로 서버가 가동 중이고 프론트엔드에서 사용할 수 있다는 응답을 받으면 됩니다. 또한 Couchbase의 주소를 정의하는 Java 매개 변수가 제공되고 CouchbaseContainer 인스턴스에서 값을 가져오는 것을 볼 수 있습니다.
마지막으로 매우 유용한 정보는 withLinkToContainer 메서드에 대한 호출입니다. 이 메서드는 GenericContainer API의 일부가 아닌데, 그 이유는 잘 모르겠습니다. 확장해야 했습니다:
1 2 3 4 5 6 7 8 9 10 11 |
public 클래스 LinkedContainer> 확장 제네릭 컨테이너 { public LinkedContainer(문자열 이름) { super(이름); } public SELF 위드링크투컨테이너(LinkableContainer 다른 컨테이너, 문자열 alias) { addLink(다른 컨테이너, alias); 반환 self(); } |
CouchbaseContainer와 backemd 사이에 Docker 링크가 있는지 확인하기만 하면 됩니다. 이렇게 하면 컨테이너가 서로 통신할 수 있도록 할 수 있습니다.
이제 카우치베이스와 백엔드가 준비되었으므로 프론트엔드를 시작할 수 있습니다. 이것은 Angular2 애플리케이션 내부의 기본 nginx 컨테이너. 백엔드에 액세스해야 하므로 이전 컨테이너에 대한 링크를 추가해야 합니다. 한 가지 확인해야 할 사항은 Angular 앱에서 백엔드 서버의 URL을 동적으로 변경할 수 있어야 한다는 것입니다. 이 작업은 환경을 사용하여 쉽게 수행할 수 있습니다. 이 테스트 이미지는 테스트 환경으로 빌드되었으므로 withLinkToContainer 메서드에 지정된 이름인 trycbBack 호스트 이름을 찾습니다. 그리고 다시 정적 블록에서 컨테이너를 시작합니다.
1 2 3 4 5 6 |
public 정적 제네릭 컨테이너 trycbFront = new LinkedContainer("trycb/front:최신").위드링크투컨테이너(trycbBack, "trycbBack").노출된 포트(80); 정적 { trycbFront.시작(); } |
모든 컨테이너가 실행되고 나면 셀레늄 컨테이너를 시작할 수 있습니다. 이 컨테이너는 TestContainers 프로젝트의 일부이며 여러 기능에 액세스할 수 있습니다. Chrome 또는 Firefox를 사용할지, 테스트를 기록할지 여부를 결정할 수 있습니다. 저희의 경우 크롬 드라이버를 사용하며 테스트가 기록되어 대상 포들러에 저장됩니다. 또한 프론트엔드와 백엔드 모두에 링크를 추가한 것을 알 수 있습니다. 프론트엔드는 컨테이너 내부의 Chrome 브라우저에서 액세스되며, 앵귤러 앱은 이를 통해 백엔드에 액세스합니다. 따라서 셀레늄 컨테이너에서도 액세스할 수 있는지, 그리고 CORS 구성이 통신을 허용하는지 확인해야 합니다.
1 2 3 4 5 6 7 |
@ClassRule public 정적 브라우저웹드라이버컨테이너 크롬 = new 브라우저웹드라이버컨테이너() .위드링크투컨테이너(trycbFront, "trycbfront") .위드링크투컨테이너(trycbBack, "trycbback") .원하는 기능(DesiredCapabilities.크롬()) .위드 레코딩 모드(브라우저웹드라이버컨테이너.VncRecordingMode.RECORD_ALL, new 파일("target")); |
이제 모든 설정이 완료되었으며 이 글의 시작 부분에 제시된 테스트를 실행할 수 있습니다. 도움이 되셨기를 바라며, 이제 테스트 컨테이너를 사용하여 Couchbase 기반 애플리케이션을 쉽게 통합 테스트할 수 있기를 바랍니다.