미니옵빠의 code stubs
Selendroid 따라해보기 본문
Selendroid 따라해보기
- Selendroid가 무엇인지, 어떻게 동작하는지 이해하기 위해 간단히 따라해보기 위한 목적
Selendroid: Selenium for Android
- 앱 / 모바일 웹 테스트 자동화 프레임워크
- http://selendroid.io
- Architecture: http://selendroid.io/architecture.html
- https://github.com/selendroid
- Selenium의 AndroidDriver가 selendroid로 통합
- 가상 머신(VM) 또는 실제 기기 위에 앱을 구동하고, 해당 앱 내 버튼 등을 실제 클릭하는 등의 시나리오를 실행 가능
- Selenium과 유사
Getting started
- http://selendroid.io/quickStart.html 참고
- 본 문서에서는 Windows + Eclipse IDE 환경을 기준으로 함
준비물
- Java SDK (1.6 이상). 이 문서는 jdk1.8.0_51 기준
Android SDK
- https://developer.android.com/studio/index.html 여기에서 Android Studio를 다운 받아 설치. 이 문서는 Studio 2.2.3 (145.3537739) / SDK 25.0.2 기준
- 가이드에는 SDK만 필요하다고 되어 있으나, 실제 실행에 필요한 build-tools/aapt.exe 파일 등이 설치되지 않음
설치 추천 위치
- Studio:
C:\Android Studio
SDK:
C:\Android
- Studio:
- Selendroid standalone jar 다운로드
- http://selendroid.io/setup.html#launchingSelendroid
- 이 문서는 selendroid-standalone-0.17.0-with-dependencies.jar 기준
- 파일 추천 위치:
C:\selendroid
- selendroid test app 다운로드
- http://selendroid.io/setup.html#getAut
- 이 문서는 selendroid-test-app-0.17.0.apk 기준
- 파일 추천 위치:
C:\selendroid
시스템 환경 변수 설정
- JAVA_HOME 설정. jdk Path를 설정. jre로는 실행 안됨
- 예)
JAVA_HOME=C:\Program Files\Java\jdk1.8.0_51
- 예)
- ANDROID_HOME 설정. SDK Path를 설정
- 예)
ANDROID_HOME=C:\Android\sdk
- 예)
설정법 참고
시스템 속성 > 환경 변수
이 경우는 PC를 껐다 켜거나, 새로운 명령 프롬프트(cmd.exe)를 켜면 적용됨
또는 명령 프롬프트에서 명령어로 직접 설정
set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_51 set ANDROID_HOME=C:\Android\sdk
- 새로운 명령 프롬프트를 실행할 때마다 reset 됨. 해당 창마다 session 단위
- JAVA_HOME 설정. jdk Path를 설정. jre로는 실행 안됨
- Android virtual devices (avd) 다운로드
- 참고: https://developer.android.com/studio/run/managing-avds.html
- Andriod Studio 실행 - AVD Manager 실행 후 설치
- Studio가 아닌 SDK에 포함된
AVD Manager.exe
실행으로는 설치되지 않음
- Studio가 아닌 SDK에 포함된
- 이 문서는 Nexus 5 API 24 기준
- Junit 테스트를 위해 Eclipse IDE + Maven plugin 준비
Selendroid Standalone 구동
- 명령 프롬프트에서
C:\selendroid
로 이동 아래 명령어 실행
java -jar selendroid-standalone-0.17.0-with-dependencies.jar -app selendroid-test-app-0.17.0.apk
아래와 같은 오류 메시지가 엄청나게 뜨는데, 무시해도 됨
Executing shell command: C:\Android\sdk\build-tools\25.0.1\aapt.exe remove C:\Users\tod2\AppData\Local\Temp\android-driver3618093378546726334.apk META-INF/MANIFEST.MF Executing shell command: C:\Android\sdk\build-tools\25.0.1\aapt.exe remove C:\Users\tod2\AppData\Local\Temp\android-driver3618093378546726334.apk META-INF/ANDROIDD.RSA
https://github.com/selendroid/selendroid/issues/1029#issuecomment-175031563
아래와 같이 서버 정상 구동 확인
12월 19, 2016 11:55:18 오전 io.selendroid.standalone.android.impl.DefaultAndroidEmulator getScreenSizeFromSkin 경고: Failed to get dimensions for skin: 12월 19, 2016 11:55:18 오전 io.selendroid.standalone.server.model.DeviceStore addEmulators 정보: Adding: AndroidEmulator [screenSize=null, targetPlatform=null, serial=null, avdName=Nexus_5_API_24, model=, apiTargetType=android] 12월 19, 2016 11:55:18 오전 io.selendroid.standalone.server.SelendroidStandaloneServer start 정보: Selendroid standalone server has been started on port: 4444
http://localhost:4444/wd/hub/status 에 접속하여 설정 정보 확인
{ "value":{ "os":{ "name":"Windows 7", "arch":"x86", "version":"6.1" }, "build":{ "browserName":"selendroid", "version":"0.17.0" }, "supportedDevices":[ ], "supportedApps":[ { "mainActivity":"io.selendroid.testapp.HomeScreenActivity", "appId":"io.selendroid.testapp:0.17.0", "basePackage":"io.selendroid.testapp" }, { "mainActivity":"io.selendroid.androiddriver.WebViewActivity", "appId":"io.selendroid.androiddriver:0.17.0", "basePackage":"io.selendroid.androiddriver" } ] }, "status":0 }
- supportedDevices는 USB로 연결된 기기가 있을 경우 노출
Junit을 이용한 실제 테스트
- 앞의 Selendroid Standalone 은 종료
- Eclipse > 신규 Maven Project 생성
Maven Dependency 설정
예)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>selendriod</groupId> <artifactId>modoo</artifactId> <version>0.0.1-SNAPSHOT</version> <repositories> <repository> <id>snapshot</id> <name>snapshot repository</name> <url>https://oss.sonatype.org/content/repositories/snapshots/</url> <layout>default</layout> <snapshots> <enabled>true</enabled> </snapshots> <releases> <enabled>false</enabled> </releases> </repository> </repositories> <dependencies> <dependency> <groupId>io.selendroid</groupId> <version>0.17.0</version> <artifactId>selendroid-standalone</artifactId> </dependency> <dependency> <groupId>io.selendroid</groupId> <version>0.17.0</version> <artifactId>selendroid-client</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
테스트 코드 작성
- 모바일 웹
- Test 파일 생성
src/test/java
하위에 원하는 파일명으로 생성- 여기서는 selendroid.MobileWebTest.java 파일을 생성
- 테스트 코드 작성
- webview (브라우저)를 열어
http://m.ebay.de
에 접속 > 검색어Nexus 5
입력 > Document.title 출력
- webview (브라우저)를 열어
- Test 파일 생성
package selendriod; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.DesiredCapabilities; import io.selendroid.client.SelendroidDriver; import io.selendroid.common.SelendroidCapabilities; import io.selendroid.standalone.SelendroidConfiguration; import io.selendroid.standalone.SelendroidLauncher; /** * @author tod2 */ public class MobileWebTest { private SelendroidLauncher selendroidServer = null; private WebDriver driver = null; @Test public void shouldSearchWithEbay() { // And now use this to visit ebay driver.get("http://m.ebay.de"); // Find the text input element by its id WebElement element = driver.findElement(By.id("kw")); // Enter something to search for element.sendKeys("Nexus 5"); // Now submit the form. WebDriver will find the form for us from the element element.submit(); // Check the title of the page System.out.println("Page title is: " + driver.getTitle()); driver.quit(); } @Before public void startSelendroidServer() throws Exception { if (selendroidServer != null) { selendroidServer.stopSelendroid(); } SelendroidConfiguration config = new SelendroidConfiguration(); selendroidServer = new SelendroidLauncher(config); selendroidServer.launchSelendroid(); DesiredCapabilities caps = SelendroidCapabilities.android(); driver = new SelendroidDriver(caps); } @After public void stopSelendroidServer() { if (driver != null) { driver.quit(); } if (selendroidServer != null) { selendroidServer.stopSelendroid(); } } }
- Junit 실행
- Jre 설정으로 인해 테스트 실행 실패할 경우, Run Configurations > Environment 내
JAVA_HOME
으로 JDK 경로를 추가
- Jre 설정으로 인해 테스트 실행 실패할 경우, Run Configurations > Environment 내
결과
- 모바일 앱 (Native)
- apk 파일 복사
selendroid-test-app-0.17.0.apk
파일을src/test/resources
하위에 복사
- Test 파일 생성
src/test/java
하위에 원하는 파일명으로 생성- 여기서는 UserRegistrationTest.java 파일을 생성
- 테스트를 위해 UserDO.java 파일도 생성
- 테스트 코드 작성
- webview (브라우저)를 열어 앱 구동 > 값 입력 확인
- apk 파일 복사
// UserDO.java package selendriod; /** * @author tod2 */ public class UserDO { public String username; public String email; public String password; public String name; public String programmingLanguage; public UserDO(String username, String email, String password, String name, String programmingLanguage) { super(); this.username = username; this.email = email; this.password = password; this.name = name; this.programmingLanguage = programmingLanguage; } }
// UserRegistrationTest.java package selendriod; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import io.selendroid.client.SelendroidDriver; import io.selendroid.common.SelendroidCapabilities; /** * @author tod2 */ public class UserRegistrationTest { private WebDriver driver = null; @Before public void setup() throws Exception { driver = new SelendroidDriver(new SelendroidCapabilities("io.selendroid.testapp:0.17.0")); } @Test public void assertUserAccountCanRegistered() throws Exception { // Initialize test data UserDO user = new UserDO("u$erNAme", "me@myserver.com", "mySecret", "John Doe", "Python"); registerUser(user); verifyUser(user); } private void registerUser(UserDO user) throws Exception { driver.get("and-activity://io.selendroid.testapp.RegisterUserActivity"); WebElement username = driver.findElement(By.id("inputUsername")); username.sendKeys(user.username); driver.findElement(By.name("email of the customer")).sendKeys(user.email); driver.findElement(By.id("inputPassword")).sendKeys(user.password); WebElement nameInput = driver.findElement(By.xpath("//EditText[@id='inputName']")); Assert.assertEquals(nameInput.getText(), "Mr. Burns"); nameInput.clear(); nameInput.sendKeys(user.name); driver.findElement(By.tagName("Spinner")).click(); driver.findElement(By.linkText(user.programmingLanguage)).click(); driver.findElement(By.className("android.widget.CheckBox")).click(); driver.findElement(By.linkText("Register User (verify)")).click(); Assert.assertEquals(driver.getCurrentUrl(), "and-activity://VerifyUserActivity"); } private void verifyUser(UserDO user) throws Exception { Assert.assertEquals(driver.findElement(By.id("label_username_data")).getText(), user.username); Assert.assertEquals(driver.findElement(By.id("label_email_data")).getText(), user.email); Assert.assertEquals(driver.findElement(By.id("label_password_data")).getText(), user.password); Assert.assertEquals(driver.findElement(By.id("label_name_data")).getText(), user.name); Assert.assertEquals(driver.findElement(By.id("label_preferedProgrammingLanguage_data")) .getText(), user.programmingLanguage); Assert.assertEquals(driver.findElement(By.id("label_acceptAdds_data")).getText(), "true"); } @After public void teardown() { driver.quit(); } }
- 상단의 Selendroid Standalone 구동
- Junit 실행
결과
- 모바일 웹