앞서 UI 자동화에 대한 기본적인 개요 및 네이버 자동 로그인을 IE 11과 Chrome(66 Stable)로 테스트 해보았습니다.
이제 제대로 업무에 적용하기에 앞서 자동화가 이루어지기 위해서 빠지지 않는 webDriver에 대해 조사해보았습니다.
Selenium WebDriver
Selenium webDriver(셀레니엄 웹드라이버) 는 많은 브라우저(FireFox,Edge,InternetExplorer,Chrome...) , 운영체제 및 프로그래밍언어(ruby,js,C#,JAVA,Python .. ) 등을 지원하며 웹 응용 프로그램들의 테스트 를 단순화 함과 동시에 가속화를 도와주는 툴입니다.
해당 Selenium WebDriver 가나오기전 있었던 Selenium Remote Control(RC) 버전이 있었습니다.
해당 제품의 구동 방식은 이와 같습니다.
[Chrome]
Chrome 바이너리가 실행 되고 Remote Controller를 통해서 해당 Chrome에 메시지를 전달하고 다시 받고 다시 전달 하는 방식을 취득하였으며 지원되는 브라우저도 적었으며 RC구현으로 인해 OS의 제약도 많았습니다.
또한 해당 메시지 방식을 취득 하다 보니 실제 사용자의 동작으로 보이지 않는 경우도 있었습니다.
이러저러한 문제점으로 인해 Selenium WebDriver(2.0) 이 webDriver + Selenium1.0 으로 나오게 되었으며
Selenium WebDriver 의 장점이 있습니다.
1. 다채로운 프로그래밍 언어 지원
기존의 Selenium IDE와는 다르게 Java,PHP,Perl,Ruby,Python,C#,JS 등을 지원합니다.
2. 매우 단순한 사용 법
기존의 RC사용법은 RC실행 + 드라이버 세팅 + Selenium 세팅 및 스크립트가 따로 가야 하지만
WebDriver는 StandardAlone으로 내부적으로 한번에 스크립트를 사용하여 제어합니다.
3. 실제 사용자 동작을 예뮬레이션 합니다.
동작 내용을 확인해 보면 아실수 있겠지만 WebElement 등을 클릭할때 마우스로 인한 포커싱이 되는 모습을 확인
이가능합니다.
4. 기존보다 스크립트 실행 속도가 빠릅니다.
- 해당은 제가 기존을 사용하지 않아서 확인을 못해봤습니다.
5. API 지원
WebDriver API 를 통해서 어렵지 않게 개발등이 가능합니다.
(JS로 하는에 손쉬운거 같진 않지만)
chromedriver.exe가 하는 역할은 selenium에서 webdriver명령을 보낼때 크롬을 제어 하는 방법 을 제공해주는데
이를 크롬 57버전까지는 자동화 확장 기능을 사용하여 크롬과 통신을 원할하게 하였지만
크롬 58 버전 부터는 확장 기능을 제거하고 WebSocket 통신을 사용하고 원격 디버깅을 지원하는 크롬의 dev tool api 에서 모든것을 제어하는 방법으로 바뀌었습니다.
그러므로 자동화 실행시에는 위의 크롬은 현재 자동화 테스트 소프트웨어로 인해 제어되고 있습니다. 라는 메시지가 나타납니다.
또한 최근에(?) 만들어지는 Selenium 개발자가 직접 프로젝트를 합쳐서 만드는 4.0 Alpha 버전에 대한
지원 레밸 정의입니다.
대충 보면
이슈를 재기해도 고치진 않을것이고 fix되지 않은 API 에 대한 보장은 해주지 않겠지만
최선을 다해서 내부적으로 이슈를 찾아서 고칠 것이며 selenium 은 플랫폼 API 와 호환 API 를 릴리즈 한다.
Support Level Definitions
supported: A selenium-webdriver release will be API compatible with the platform API, without the use of runtime flags.
best effort: Bugs will be investigated as time permits. API compatibility is only guaranteed where required by a supported release. This effectively means the adoption of new JS features, such as ES2015 modules, will depend on what is supported in Node's LTS.
unsupported: Bug submissions will be closed as will-not-fix and API compatibility is not guaranteed.
const _url = "https://www.naver.com/"; // require 가 Builder보다 위에 있어야 함 공식 홈페이지 require('chromedriver'); const webdriver = require('selenium-webdriver'); const {By,Util} = webdriver; // 드라이버 빌드 var driver = new webdriver.Builder() .forBrowser('chrome') .build(); const register_pc = false; (async () => { try { // 페이지 이동 await driver.get(_url); // 윈도우 최대화 headless 옵션 사용시 는 의미없음 await driver.manage().window().maximize(); // input값 가져옴 let inputId = await driver.findElement(By.css('input#id')); // ID 입력 await inputId.sendKeys('id'); // password 값 가져옴 let inputpw = await driver.findElement(By.css('input#pw')); // password 입력 await inputpw.sendKeys('pw'); // login 버튼 가져와서 클릭 let loginBtn = await driver.findElement(By.css("input[type='submit']")); await loginBtn.click(); // 최초 실행 PC일 경우 해당 페이지가 나타나기 때문에 존재한다면 등록 유무 선택 let page_ = await driver.findElements(By.css('fieldset.login_form a')); if(!!page_){ // 등록 page_[0] 등록 안함 page_[1] !!register_pc ?console.log("등록합니다.") :await page_[1].click(); } // selenium-js 에서는 switchTo.frame을 통해서 프레임을 변경 한다. await driver.switchTo().frame('minime'); // 변경 후 프로필에 메일을 가져오고 클릭 let mail_profile = await driver.findElement(By.id('mail_count_profile')); // 메일 클릭 // 화면 제어가 빠른 경우에 대한 sleep -> 추후 isContentsLoaded 또는 WebElement Condition 으로 변경 await driver.sleep(1500); await mail_profile.click(); // 기존 프레임으로 다시 돌아오는 경우 (page이동이없었을때) // await driver.switchTo().defaultContent(); // 임시 테스트용 Sleep await driver.sleep(2000); console.log(await driver.getTitle()); console.log(await driver.getCurrentUrl()); let newUrl = await driver.getCurrentUrl(); await driver.navigate().to(newUrl); // 가장 최상단 메일 의 Subject를 가져옴 let mailTitle = await driver.findElement(By.css('ol.mailList.sender_context li .subject')); // 셀레니엄 JS에서 getText는 innerText를 가져온다고 되어있습니다. console.log(await mailTitle.getText()); // 페이지 뒤로가기 // await driver.navigate().back(); } catch(err){ // Node Debug시 메시지가 너무길어 한글로 처음과 끝을 지정해서 보여지기 쉽게 처리 console.log("자동화 도중 에러 ",err + " 에러메시지 끝 "); } finally { await driver.sleep(2000); await driver.quit(); } })();
정확히는 헤들리스 브라우저 라기보단 헤들리스 옵션으로 사용할수 있는 lib 들을 표현하였습니다.
헤들리스 옵션은 자동화 테스트 진행시에 UI 없이 브라우저가 실행되게 하는 옵션 입니다. PhantomJS의 CapserJS는
PhantomJS 를 조금 더 세밀하게 제어할수 있는 lib 입니다.
장점에 셀레니움 이슈들이 존재 하지 않는다고 되어 있는 부분들은 셀레니엄 IDE(Java)등에서 사용되는 여러 방법이 있는데 해당 에서 발생하는 side-effect 들에 대한 이슈없이 단순히 lib에서 발생하는 이슈만 있기 때문에 조금 더 최적의 상태? 를 사용할수 있다고는 하지만 실제로 다 써본건 아니니 참고만 하려고합니다.
2. 셀레니움 의존
셀레니엄 관련 lib들을 가져와서 사용하는 것으로 Python,Ruby,Java,C#,js (vanilla)
js말고도 다른 언어들이 셀레니엄 lib를 통해서 사용할수 있는 것으로 여러 맞는 언어들을 나에게 맞게 사용할수 있는 장점이 있기 때문에 원하시는 언어로 사용해보시면 될것 같습니다.
저는 JS를 현재 공부중에 있다보니 js기반인 selenium-webdriver npm 에서 받아서 사용 하겠습니다.
기존에 UI 자동화를 위해서 이것저것 사용은 해봤습니다. guitar라든지 관련 자동화 스크립트 등등
하지만 결국 자동화를 위해서 는 코드를 기반으로 짜주어야 하며 위에서와 같이 pyhton,ruby,java,C# 너무많이 있습니다.
사실 js를 사용하기 때문에 했다기보다는 Node.js위에서 npm 을 통한 자동화 테스트 코드를 만드는것이 가장 유연성이
높다고 판단되었기 때문입니다.
실제로 자동화에 접목시키기 위해서 아는 지식선에서는 js가 가장 좋아보였습니다.(정확히는 데이터 전송등 유연하다고 생각되었습니다.)
그래서 일단 간단하게 Naver Login 후에 메일 에 대한 내용을 가져오는 방법에 대해서 작성하려고 합니다.