2019년을 위한 강력한 테스팅 팁: 자바 자동화 테스팅 튜토리얼
게시 됨: 2022-03-11매년 전 세계의 테스트 자동화 엔지니어는 테스트 자동화 프레임워크를 보다 안정적이고 빠르며 사용 및 유지 관리하기 쉽게 만들기 위해 최신 도구와 기술을 연구합니다. 이는 회사 내에서 프레임워크를 지속적으로 광범위하게 채택하는 데 중요합니다. 일반적으로 부풀려진 구식 프레임워크는 빠르게 유행에서 벗어납니다.
이 기사에서는 2019년 프레임워크를 업데이트할 수 있는 몇 가지 방법과 2020년을 준비하는 방법을 살펴보겠습니다. 프레임워크를 개선하기 위해 저는 항상 "고통점"에 집중합니다. 설정이 복잡하거나 가장 많은 실패를 일으키는 영역입니다. 단순화하거나 개선하고 싶은 세 가지 주요 영역을 확인했습니다.
- 셀레늄 그리드
- 대기
- Chrome 개발자 도구
Selenium Grid는 설정이 까다롭기로 악명이 높으며 경고 없이 실패할 수 있습니다. 여기서 개선된 점이 있다면 무엇인지 보고 싶었습니다. 또한 내가 만든 테스트의 안정성을 개선하기 위해 새로운 waits
가 Selenium API에 추가되었는지 조사하고 싶었습니다. 마지막으로, 모든 테스터의 툴킷의 필수 부분이 된 Selenium을 통해 Chrome DevTools와 상호 작용할 수 있는지 확인하고 싶었습니다.
팁 #1: Selenium 그리드를 Dockerize
Selenium Grid는 설정하기 어렵고 불안정하며 CI 파이프라인에서 배포 또는 버전 제어가 어렵기로 악명이 높습니다. 훨씬 쉽고 안정적이며 유지 관리 가능한 방법은 미리 빌드된 Selenium Docker 이미지를 사용하는 것입니다.
참고: 이 방법의 한 가지 단점은 아직 Windows 운영 체제를 컨테이너화할 수 없기 때문에 IE(Internet Explorer)가 지원되지 않는다는 것입니다.
설정하기
시작하고 실행하려면 먼저 Docker 및 Docker Compose가 컴퓨터에 설치되어 있어야 합니다. Windows 10 또는 Mac을 실행하는 경우 둘 다 Docker Desktop을 통해 설치됩니다.
그리드 시작하기
Docker Hub의 공식 Selenium 리포지토리에는 Selenium Hub, Firefox 및 Chrome 노드용으로 사전 빌드된 Docker 이미지가 포함되어 있습니다.
로컬 Selenium Grid에서 이를 사용하는 가장 쉬운 방법은 프로젝트의 루트 디렉터리 내에 Docker Compose 파일을 구성하는 것입니다. 작업을 단순하게 유지하려면 파일 이름을 docker-compose.yml
로 지정합니다.
다음 그리드를 생성하는 예를 아래에 포함했습니다.
- 단일 셀레늄 허브
- 하나의 Chrome 노드
- 하나의 Firefox 노드
#docker-compose.yml version: "3" services: selenium-hub: image: selenium/hub:3.141.59-neon container_name: selenium-hub ports: - "4444:4444" chrome: image: selenium/node-chrome:3.141.59-neon volumes: - /dev/shm:/dev/shm depends_on: - selenium-hub environment: - HUB_HOST=selenium-hub - HUB_PORT=4444 firefox: image: selenium/node-firefox:3.141.59-neon volumes: - /dev/shm:/dev/shm depends_on: - selenium-hub environment: - HUB_HOST=selenium-hub - HUB_PORT=4444
Docker Compose 파일은 그리드 설정을 설명합니다. Docker Compose 파일 생성에 대한 자세한 내용은 공식 문서를 참조하십시오.
그리드를 시작하려면 터미널 창(Windows의 경우 powershell
또는 cmd
창)을 사용하여 프로젝트의 루트 디렉터리에서 다음 명령을 실행하기만 하면 됩니다.
docker-compose up
그리드에 연결
허브가 로컬 시스템의 포트 4444에서 수신 대기하므로 평소와 똑같은 방식으로 Selenium Grid에 연결할 수 있습니다. 다음은 Chrome 노드를 사용하도록 드라이버를 설정한 예입니다.
// Driver.java protected static RemoteWebDriver browser; DesiredCapabilities cap = new DesiredCapabilities(); ChromeOptions chromeOptions = new ChromeOptions(); cap.setCapability(ChromeOptions.CAPABILITY, chromeOptions); cap.setBrowserName("chrome"); driver = new RemoteWebDriver(cap);
그런 다음 TestNG 라이브러리를 사용하여 평소와 같이 여러 노드에서 테스트를 병렬로 실행할 수 있습니다.
각 노드에서 여러 브라우저를 실행할 수 있다는 점은 주목할 가치가 있습니다. 그러나 이것은 권장되지 않으며 노드당 하나의 브라우저를 사용하는 것이 최적의 성능을 위한 모범 사례로 간주됩니다.
추가 팁 및 요령
테스트를 디버그할 수 있도록 브라우저에서 무슨 일이 일어나고 있는지 확인하고 싶다면 debug
브라우저 노드를 다운로드하는 docker-compose.yml
파일의 debug
버전을 갖는 것이 좋습니다. 여기에는 VNC 서버가 포함되어 있으므로 테스트가 실행되는 동안 브라우저를 볼 수 있습니다.
속도를 높이기 위해 헤드리스 브라우저를 실행할 수도 있으며(일반적인 방법) Selenium은 base
버전의 이미지도 제공하므로 추가 소프트웨어를 설치해야 하는 경우 고유한 이미지를 구축할 수 있습니다.
CI 파이프라인을 위한 안정적인 버전의 Grid를 생성하기 위해 Grid를 Kubernetes 또는 Swarm에 배포할 수도 있습니다. 이렇게 하면 모든 Docker가 실패할 경우 신속하게 복원되거나 교체됩니다.
팁 #2: 스마트 대기
모든 테스트 자동화 엔지니어가 알고 있듯이 waits
는 테스트 자동화 프레임워크의 안정성에 매우 중요합니다. 또한 sleeps
또는 pauses
를 중복으로 렌더링하여 테스트 속도를 높이고 느린 네트워크 및 브라우저 간 문제를 극복할 수 있습니다. 다음은 waits
을 더욱 탄력적으로 만들기 위한 몇 가지 팁입니다.
Java Automation Testing Tutorial #2: 기다림의 논리 연산자: 구체적으로 기다림
ExpectedConditions
클래스는 시간이 지남에 따라 성장하여 이제 상상할 수 있는 거의 모든 상황을 포함합니다. ExpectedConditions.presenceOfElementLocated(locator)
충분하지만, 모든 사용자 작업을 Actions.java
클래스에 포함시켜 모든 사용자 작업을 다루기 위해 ExpectedCondition
클래스 내의 메서드를 사용하는 것이 가장 좋습니다. 이렇게 하면 대부분의 브라우저 간 또는 느린 웹 사이트 문제에 대한 테스트를 완벽하게 방지할 수 있습니다.
예를 들어 , 링크를 클릭하면 새 탭이 열리면 ExpectedConditions.numberOfWindowsToBe(2)
를 사용하십시오. 이렇게 하면 탭으로 전환하기 전에 탭이 있는지 확인합니다.
findElements
를 사용할 때 페이지에 있는 모든 요소를 캡처하도록 wait
를 사용할 수도 있습니다. 이는 search
페이지에서 결과를 반환하는 데 시간이 걸리는 경우에 특히 유용할 수 있습니다. 예를 들어 다음 줄은 다음과 같습니다.
List<WebElement> results = driver.findElements(locators.RESULTS);
검색 결과가 아직 로드되지 않은 경우 빈 List
배열이 생성될 수 있습니다. 대신 numberOfElementsToBeMoreThan
예상 조건을 사용하여 결과가 0보다 클 때까지 기다리는 것이 좋습니다. 예를 들어:
WebElement searchButton = driver.findElement(locators.SEARCH_BUTTON); searchButton.click(); new WebDriverWait(driver, 30) .until(ExpectedConditions .numberOfElementsToBeMoreThan(locators.RESULTS, 0)); List<WebElement> results = driver.findElements(locators.RESULTS); results.get(0).click();
이제 findElements
명령은 검색 결과가 반환된 후에만 실행됩니다.
이 wait
는 Selenium과 잘 작동하지 않는 프런트 엔드(예: Angular 웹 사이트)를 처리할 때 단일 요소를 찾는 데에도 유용합니다. 이와 같은 방법을 작성하면 테스트를 보호하여 훨씬 더 안정적으로 만들 수 있습니다.
protected static WebElement waitForElement(By locator){ try { new WebDriverWait(browser, 30) .until(ExpectedConditions .numberOfElementsToBeMoreThan(locator, 0)); } catch (TimeoutException e){ e.printStackTrace(); Assert.fail("Timeout: The element couldn't be found in " + WAIT + " seconds!"); } catch (Exception e){ e.printStackTrace(); Assert.fail("Something went wrong!"); } return browser.findElement(locator); }
요소가 더 이상 표시되지 않을 때까지 기다릴 수도 있습니다. 이것은 테스트를 진행하기 전에 OK
또는 Save
버튼을 클릭한 후 팝업이 사라지기를 기다리는 경우에 특히 유용합니다.
WebElement okButton = driver.findElement(locators.OK_BUTTON); okButton.click(); new WebDriverWait(driver, 30) .until( ExpectedConditions .invisibilityOfElementLocated(locators.POPUP_TITLE) );
위에서 설명한 모든 방법과 그 이상은 공식 문서에 나열되어 있습니다. 모든 가능성을 읽고 프레임워크의 안정성을 개선하는 데 10분을 할애할 가치가 있습니다.
Java Automation Testing Tutorial #2: 대기 중인 논리 연산자
waits
에 탄력성을 구축하는 좋은 방법은 논리 연산자를 사용하는 것입니다. 예를 들어 요소를 찾았고 클릭할 수 있는지 확인하려면 다음 코드를 사용합니다(이 예제에서는 부울 값을 반환함).
wait.until(ExpectedConditions.and( ExpectedConditions.presenceOfElementLocated(locator), ExpectedConditions.elementToBeClickable(locator) ) );
페이지 제목이 변경될 수 있는지 여부가 확실하지 않은 경우 OR 연산자가 적합합니다. 그런 다음 첫 번째 조건이 실패할 경우 URL 확인을 포함하여 올바른 페이지에 있는지 확인할 수 있습니다.
wait.until(ExpectedConditions.or( ExpectedConditions.titleIs(expectedTitle), ExpectedConditions.urlToBe(expectedUrl) ) );
또는 페이지에서 작업이 수행된 후 확인란이 더 이상 활성화되지 않도록 하려면 NOT 연산자가 적합합니다.

wait.until(ExpectedConditions.not( ExpectedConditions.elementToBeClickable(locator) ) );
연산자를 사용하면 waits
을 더욱 탄력적으로 만들고 덜 취약한 테스트 결과를 얻을 수 있습니다.
팁 #3: Chrome DevTools: 네트워크 조건 시뮬레이션
localhost 또는 로컬 네트워크에서 웹 앱을 실행하면 야생에서 실행할 때 성능에 대해 잘못된 인상을 줄 수 있습니다. 다양한 업로드 및 다운로드 속도를 조절하는 기능은 시간 초과로 인해 작업이 실패할 수 있는 인터넷을 통해 응용 프로그램이 실행되는 방식을 더 잘 나타낼 수 있습니다. Chrome의 DevTools를 사용하여 시뮬레이션을 시작할 수 있습니다.
다음 코드는 다른 다운로드 및 업로드 속도를 사용하여 Toptal 홈 페이지를 엽니다. 먼저 다음 코드를 사용하여 TestNG 데이터 공급자에 속도를 저장합니다.
import org.testng.annotations.DataProvider; public class ExcelDataProvider { @DataProvider(name = "networkConditions") public static Object[][] networkConditions() throws Exception { return new Object[][] { // Upload Speed, Dowload Speed in kb/s and latency in ms. { 5000 , 5000, 5 }, { 10000, 7000, 5 }, { 15000, 9000, 5 }, { 20000, 10000, 5 }, { 0, 0 }, }; } }
참고: 업로드 및 다운로드 제한은 kb/s
이고 지연 시간은 ms
입니다.
그런 다음 이 데이터를 사용하여 다양한 네트워크 조건에서 테스트를 실행할 수 있습니다. 테스트 내에서 CommandExecutor
는 브라우저의 현재 세션에서 명령을 실행합니다. 그러면 느린 네트워크를 시뮬레이션하기 위해 Chrome의 개발자 도구 기능에서 필요한 설정이 활성화됩니다. if
문의 코드는 테스트 모음을 실행할 때 @BeforeClass
메서드에 포함될 수 있습니다.
import org.testng.annotations.Test; import com.google.common.collect.ImmutableMap; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.openqa.selenium.remote.Command; import org.openqa.selenium.remote.CommandExecutor; import org.openqa.selenium.remote.Response; public class TestClass { // load our data provider @Test(dataProvider = "networkConditions") public void test(int download, int upload, int latency) throws IOException { // only run if the network is throttled if (download > 0 && upload > 0) { CommandExecutor executor = driver.getCommandExecutor(); // create a hashmap of the required network conditions Map map = new HashMap(); // you can even test 'offline' behaviour map.put("offline", false); map.put("latency", latency); map.put("download_throughput", downloadThroughput); map.put("upload_throughput", uploadThroughput); // execute our code Response response = executor.execute( new Command(driver.getSessionId(), "setNetworkConditions", ImmutableMap.of("network_conditions", ImmutableMap.copyOf(map)))); } // Open the website driver.get("https://www.toptal.com/"); // You can then check that elements are loaded etc. // Don't forget to use waits! } }
보너스 팁: 쿠키 관리 방법
브라우저 쿠키는 이전 세션에서 저장되었는지 여부에 따라 애플리케이션에서 다른 동작을 일으킬 수 있습니다(예: 사용자가 이미 로그인한 상태에서 애플리케이션이 로드될 수 있음). 문제를 일으키지 않도록 각 테스트를 실행하기 전에 쿠키를 지우는 것이 좋습니다.
아래 코드를 사용하면 모든 쿠키를 삭제할 수 있습니다.
driver.manage().deleteAllCookies();
이름으로 쿠키를 삭제할 수도 있습니다.
driver.manage().deleteCookieNamed("CookieName");
또는 쿠키의 내용을 가져옵니다.
String myCookie = driver.manage().getCookieNamed("CookieName").getValue();
또는 모든 쿠키를 가져옵니다.
List<Cookie> cookies = driver.manage().getCookies();
2020년 테스트 자동화: 미래를 바라보다
Selenium 4는 앞으로 몇 달에 걸쳐 출시될 예정입니다. 아직 개발 중이지만 알파 버전이 이미 출시되었으므로 어떤 개선 사항을 제공할지 살펴볼 가치가 있습니다.
참고: 로드맵을 보면 진행 상황을 추적할 수 있습니다.
W3C WebDriver 표준화
더 이상 Selenium은 JSON 유선 프로토콜을 통해 브라우저와 통신할 필요가 없습니다. 대신 자동화된 테스트가 브라우저와 직접 통신합니다. 이것은 브라우저 업그레이드에 대한 보호를 포함하여 Selenium 테스트의 유명한 불안정한 특성을 해결해야 합니다. 테스트 속도도 향상되기를 바랍니다.
더 간단한 셀레늄 그리드
Selenium Grid는 Selenium 4에서 보다 안정적이고 설정 및 관리하기 쉽습니다. 그리드가 결합된 노드 및 허브 역할을 하므로 사용자는 더 이상 허브와 노드를 별도로 설정하고 시작할 필요가 없습니다. 또한 Docker에 대한 더 나은 지원이 있을 것이며 병렬 테스트가 기본적으로 포함되며 보다 유익한 UI를 제공할 것입니다. Hooks를 사용한 요청 추적은 그리드를 디버그하는 데도 도움이 됩니다.
선적 서류 비치
Selenium 설명서는 Selenium 2.0 릴리스 이후 업데이트되지 않은 매우 필요한 정밀 검사를 받게 됩니다.
API 변경 사항
Opera 및 PhantomJS 브라우저에 대한 지원이 제거됩니다. 헤드리스 실행은 Chrome 또는 Firefox에서 수행할 수 있으며 Opera는 Chromium을 기반으로 하므로 이 브라우저에서는 Chromium 테스트로 충분합니다.
WebElement.getSize()
및 WebElement.getLocation()
은 이제 단일 메서드 WebElement.getRect()
로 대체되었습니다. 그러나 이들은 단일 요소의 스크린샷을 만드는 데 자주 사용되므로 Selenium 4에서 요소의 스크린샷을 캡처하는 API 명령도 있다는 것을 아는 것이 좋습니다.
WebDriver Window
의 경우 getPosition
및 getSize
메소드는 getRect
메소드로 대체되고 setPosition
및 setSize
메소드는 setRect
메소드로 대체됩니다. fullscreen
및 minimize
방법을 사용할 수 있으므로 테스트 내에서 이러한 작업을 수행할 수 있습니다.
기타 주목할만한 변경 사항:
- 이제 모든 브라우저의
Options
클래스가Capabilities
클래스를 확장합니다. - 프레임 탐색을 쉽게 하기 위해
driver.switchTo().parentFrame()
메서드가 추가되었습니다. - 현재의 것보다 높은 수준에서 작동하는
nice
로케이터가 포함될 것입니다.By
의 하위 클래스가 됩니다. -
DevTools
API가 구현되어 사용자가 Chrome 디버깅 프로토콜(및 다른 브라우저에서 이에 상응하는 기능)을 사용하여 제공되는 기능을 활용할 수 있습니다. 여기에는 다음이 포함됩니다.- 전체 페이지 스크린샷(오프스크린 요소 포함).
- 스트리밍 로그.
- 페이지에서 돌연변이 이벤트를 기다리고 있습니다.
- 사용되지 않는 많은 메서드와 클래스도 삭제됩니다.
참고: Maven 저장소에서 Selenium 4의 알파 버전을 얻을 수 있습니다. 현재 프레임워크(이상적으로는 샌드박스 브랜치에서)에 대해 이 작업을 시도하는 것이 좋습니다. 그러면 변경 준비가 완료됩니다.
결론
이 기사에서는 테스트 자동화 프레임워크를 개선한 몇 가지 영역을 다루었습니다. 이제 이전보다 더 안정적이고 사용할 수 있게 되었으며, 이는 소프트웨어 제공 수명 주기에 관련된 모든 사람에게 긍정적인 영향을 미칠 것입니다.
위에서 설명한 변경을 하는 것은 좋은 시작이지만, 내가 다루지 않은 개선 사항이 있을 수 있으므로 전체 프레임워크에서 "고통점"을 검토하는 것이 좋습니다. 예를 들어, WebDriver Manager를 사용하여 드라이버를 관리하고 있습니까, 아니면 여전히 수동으로 업데이트하고 있습니까?
또한 6개월마다 하는 것이 이상적이지만 적어도 1년에 한 번 이 작업을 수행하도록 날짜를 설정하는 것이 좋습니다. 이 기사에는 Selenium 4.0에 포함될 변경 사항이 포함되어 있습니다. Selenium의 alpha
버전을 직접 검토하십시오. 변화는 극적이며 준비가 필요합니다. 이 정보가 유용하기를 바랍니다. 프레임워크에서 약간의 봄 청소를 수행하는 동안 새로운 방법이나 기술을 발견하면 아래의 설명 섹션에 추가하여 이 블로그의 다른 독자와 공유하십시오.
또한 Selenium의 자동화된 테스트를 살펴보고 페이지 개체 모델을 사용하여 유지 관리 및 재사용 가능한 테스트 루틴을 작성하는 방법을 보려면 Selenium의 자동화: 페이지 개체 모델 및 페이지 팩토리 를 확인하세요.