Selenium 프로젝트의 도구 제품군의 일부인 Selenium Remote Control(RC)은 웹 애플리케이션을 위한 자동화된 테스트 프레임워크이다. Selenium RC는 많은 프로그래밍 언어와 거의 모든 브라우저를 지원한다. Selenium RC의 가장 중요한 장점은 브라우저가 구동되는 메소드이다. 다른 웹 UI 자동화 도구와 달리 Selenium RC는 JavaScript로 브라우저를 구동하므로 테스트가 마우스 이벤트의 방해를 받지 않는다. 테스터는 테스트를 실행하는 동안 다른 태스크를 수행할 수 있다.
Selenium Grid는 다른 서버에서 병렬로 테스트를 실행하여 Selenium RC를 확장한다. 이는 여러 운영 체제 하에 다양한 브라우저에서 테스트를 실행하기 위한 시간을 단축시켜 결과적으로 비용을 절감한다.
Selenium 도구 제품군은 형식 문서와 안내서가 제한된 오픈 소스 프로젝트이므로 학습하기 어려울 수 있다. 이 기사에서는 Java에서 Selenium Grid(버전 1.0.6) 프로그래밍으로 테스트하는 것과 TestNG 테스팅 프레임워크로 실행하는 것을 학습한다.
Selenium Grid는 Selenium Hub와 Remote Control이라는 두 가지 컴포넌트가 있다. 허브는 테스트에서 요청을 수신한(Selenium RC와 동일함) 다음에 해당 허브로 등록된 원격 제어를 각 테스트에 지정한다. 이는 다음 그림 1에 표시된다.
그림 1. Selenium Grid에서 Selenium Hub 및 Selenium RC의 관계
테스터는 Selenium Grid에서 코드를 변경하지 않고 테스트를 실행할 수 있다. 전체 프로세스는 투명하다. 즉, 테스터는 실제 인프라에 대해 알거나 신경 쓸 필요가 없다.
Selenium RC에 대해 익숙하다면, Selenium Grid로 간편하게 테스트를 실행할 수 있을 것이다. 여러 머신에서 병렬로 기존 코드를 실행할 수도 있으며, 이는 테스트 실행 시간을 절약하고 테스트 결과의 피드백을 신속하게 제작한다. 하지만, Selenium Grid 자체는 전략을 실행 중인 병렬을 제공하지 않는다. Selenium Grid를 활용하려면 병렬 모드에서 Selenium 테스트를 써야 한다.
Selenium Grid를 시작하려면 먼저 이를 다운로드하여 설치해야 한다(링크는 참고자료 참조). Selenium Grid는 라이브러리 JAR 파일, 예제 파일, Ant의 빌드 파일 및 다른 파일이 들어있는 폴더이다. Selenium Grid에서 테스트를 실행하려면 다음이 필요하다.
- Java 애플리케이션 컴파일, 어셈블리, 테스트 및 실행을 위해 사용되는 Ant 버전 1.7 이상(대상 및 확장 지점으로 빌드 파일에 설명됨).
- JDK 5+.
- Selenium Grid는 Selenium RC를 기반으로 하므로 Selenium RC의 기초 지식. (Selenium RC에 대한 정보는 참고자료를 참조한다.) 테스터는 Selenium RC를 사용한 테스트 쓰기 및 실행 방법을 알아야 한다.
이 기사에서 예제는 프로그래밍 언어와 테스트 프레임워크로서 Java 기술 및 TestNG를 사용한다. TestNG는 넓은 테스팅 요구 범위의 간소화 및 JUnit 확장을 위해 제작되었다. (TestNG에 대한 자세한 정보는 참고자료를 참조한다.)간단한 TestNG 구성 파일은 리스트 1에 나와있다.
리스트 1. 간단한 TestNG 구성 파일
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite1" parallel="methods" thread-count="2">
<test name="Testcase20" >
<classes>
<class name="com.test.workflow.device.testcase20"/>
</classes>
</test>
</suite>
|
<suite> 태그는 하나 이상의 테스트가 들어있는 하나의 TestNG
XML 파일을 표현할 수 있다. <test> 태그를 통해 테스트에
하나 이상의 TestNG 클래스를 포함할 수 있다. <class>
태그는 TestNG 클래스가 하나 이상의 테스트 메소드를 포함할 수 있음을 의미한다. (태그에 대한
더 자세한 정보는 참고자료를 참조한다.) 테스트 메소드는 Java 파일로
정의되며, 이는 다음 리스트 2에 표시된다.
리스트 2. Java 파일로 정의된 테스트 메소드
@Test
public void testMethod()
{
....
}
|
테스터들은 테스트 스크립트를 쓰기 위해 Java 프로그래밍 언어와 테스팅 프레임워크를 사용하고 Ant를 사용하여 명령행으로부터 TestNG 클래스를 실행한다. Ant를 사용하여 TestNG를 실행하는 전체 프로세스에 대해 살펴보자.
- 명령행에서
ant(target name) [build file name]을 실행한다. - Ant는 build.xml 파일을 읽어 프로젝트 매개변수, 가져오기 파일, 클래스패스 정의, 대상 정의 및 기타 등등을 얻는다.
- Ant는 Java 소스 코드를 TestNG 클래스로 따른다.
- Ant는 실행할 대상에 집중하여 대상 구성을 얻는다.
- TestNG 구성 파일을 읽어 매개변수, 테스트 클래스 이름 및 기타 등등을 얻는다.
- TestNG 구성 파일에 구성된 대로 TestNG 클래스를 실행한다.
이 기사는 TestNG 및 Ant와 통합된 Selenium Grid를 사용하여 병렬로 테스트를 실행하는 방법에 주목하므로 PHP 페이지를 기반으로 간단한 애플리케이션을 사용할 것이다. 테스트 케이스는 페이지에서 탭을 간단하게 클릭하도록 제작되었다. 그림 2에서 예제 애플리케이션 웹 페이지가 표시된다.
그림 2. 애플리케이션 웹 페이지의 일부
리스트 3에서 탭용 예제 소스 코드를 제공한다.
리스트 3. 탭용 소스 코드
<div class="Tabs" style="width: 100%;"> <a class="Current">Test Case</a> <a>View Time</a> <a>Run Scripts</a> <a>Long Run</a> <a>LA</a> <a>s-CAT</a> <a>Jmeter</a> </div> |
테스트 머신이 다음과 같이 준비된다.
| IP | OS Type |
|---|---|
| 9.181.138.75 | win2003 |
| 9.181.138.186 | win2003 |
| 9.181.128.184 | Linux |
컨텐츠가 그림 3에 표시되는 테스트 폴더를 selenium-grid-1.0.6 디렉토리에 놓는다.
그림 3. 테스트 케이스 폴더 컨텐츠
src 디렉토리에 Java 소스 코드 파일이 들어있다. 대상 디렉토리에는 모든 클래스 파일, 컴파일 이후 그리고 보고서 파일이 들어있다. 리스트 4에 표시된 build.xml 파일은 대상 구성을 정의하는 Ant 빌드 파일이다. 이는 호출할 TestNG 구성 파일, 프로젝트 매개변수, lib 파일 경로 및 기타 등등이 들어있다. testng.xml 파일은 예제 테스트 케이스에 대한 TestNG 구성 파일이다.
리스트 4. build.xml
<project name="Selenium Grid Test" default="run" basedir=".">
<description>Selenium Grid Test</description>
<property name="rootdir" value="${basedir}/.."/>
<property file="${rootdir}/project.properties"/>
<property name="name" value="Selenium Grid Demo"/>
<property name="artifact" value="selenium-grid-demo"/>
<property name="version" value="SNAPSHOT"/>
<property name="selenium.version" value="SET ME"/>
<property name="build.src" location="src"/>
<import file="${rootdir}/lib/build/common-build.xml" />
<path id="compile.classpath">
<fileset dir="${rootdir}/vendor">
<include name="selenium-java-client-driver-${selenium.version}.jar"/>
<include name="testng-5.7-jdk15.jar"/>
<include name="commons-logging-1.0.4.jar"/>
</fileset>
<pathelement location="${rootdir}/tools/target/classes"/>
<pathelement location=
"${rootdir}/tools/target/dist/lib/selenium-grid-tools-standalone-${version}.jar"/>
<pathelement location="${rootdir}/lib/selenium-grid-tools-standalone-${version}.jar"/>
<pathelement path="${java.class.path}/"/>
</path>
<path id="runtime.classpath">
<path refid="compile.classpath"/>
<pathelement path="${build.output}/"/>
</path>
<target name="run" depends="compile" description="test">
<java classpathref="runtime.classpath"
classname="org.testng.TestNG"
failonerror="true">
<sysproperty key="java.security.policy" file="${rootdir}/lib/testng.policy"/>
<arg value="-d" />
<arg value="${basedir}/target/reports" />
<arg value="-suitename" />
<arg value="suite1" />
<arg value="testng.xml"/>
</java>
</target>
<target name="build" depends="compile"/>
<target name="dist" depends="build"/>
<target name="coverage-analysis" />
</project>
|
이제 환경 및 테스트 데이터가 준비되었으므로 병렬 테스팅의 다음 세 가지 다른 시나리오를 실행할 수 있다.
- 동일한 테스트 케이스가 하나의 서버에서 다른 브라우저에 실행
- 다른 테스트 케이스가 다른 브라우저의 다른 서버에 병렬로 실행
- 다른 테스트 케이스가 동일한 브라우저의 다른 서버에 병렬로 실행
동일한 테스트 케이스가 하나의 서버에서 다른 브라우저에 실행
동일한 케이스를 하나의 서버에서 다른 브라우저에 실행하려면 다음 Selenium Grid 분배 디렉토리로 이동한다.
ant launch-hub |
동일한 머신 또는 다른 머신의 새 창에 다음을 입력한다.
ant launch-remote-control ant Denvironment=*iehta launch-remote-control |
또는
ant -Dhost=9.181.138.186 DhubURL=http://9.181.138.75:4444 launch-remote-control
ant -Dhost=9.181.138.186 DhubURL=http://9.181.138.75:4444
-Denvironment=*iehta launch-remote-control
|
브라우저에서 http://localhost:4444/console에 Hub의 콘솔로 다시 돌아간다. 이제 사용 가능하도록 나열된 두 개의 원격 제어가 있어야 하며, 이는 그림 5와 유사하다.
그림 4. Selenium Grid Hub 콘솔
리스트 5로부터 테스트 클래스 소스 코드를 src 디렉토리에 놓는다.
리스트 5. 테스트 케이스 Java 소스 코드
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;
import org.testng.annotations.Parameters;
public class GridTest2 {
String url = "http://9.181.138.186/index.php";
private Selenium selenium= null;
@Parameters({ "bs" })
@BeforeClass
public void startBroswer(String broswer)
{
selenium= new DefaultSelenium("localhost", 4444, broswer, url);
selenium.start();
selenium.open(url);
selenium.windowMaximize();
}
@Test
public void test() throws InterruptedException
{
selenium.click("xpath=//a[contains(text(),\'LA\')]");
Thread.sleep(10000);
}
@AfterClass
public void clear() {
selenium.stop();
}
}
|
testng.xml의 컨텐츠를 변경한다. 이는 다음 리스트 6에 표시된다.
리스트 6. TestNG 구성 파일 컨텐츠
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="suite1" verbose="1" annotations="JDK" parallel="tests" thread-count="2">
<test name="test1">
<parameter name="bs" value="*firefox"/>
<classes>
<class name="GridTest2" />
</classes>
</test>
<test name="test2">
<parameter name="bs" value="*iehta"/>
<classes>
<class name="GridTest2" />
</classes>
</test>
</suite>
|
testing.xml 파일의 bs 매개변수는
test1이 Firefox 브라우저에서 실행하는 것과 test2가 Internet
Explorer에서 실행하는 것을 정의한다. parallel 속성은
테스트가 병렬로 실행하는 것을 정의한다. thread-count
속성은 실행할 스레드 수를 정의한다. 두 가지 테스트만 정의되어 있으므로 두 가지
테스트는 동시에 실행할 것이다.
창을 열고 다음 테스트 디렉토리로 이동한다.
ant run |
테스트 케이스가 자동으로 실행될 것이다.
다른 케이스가 다른 브라우저의 다른 서버에 병렬로 실행
다른 테스트 케이스를 다른 브라우저의 다른 서버에 병렬로 실행하려면 다음 Selenium Grid 분배 디렉토리로 이동한다.
ant launch-hub |
동일한 머신의 새 창이나 다른 머신의 창에 다음을 입력한다.
ant launch-remote-control ant Dport=6666 Denvironment=*iehta launch-remote-control |
머신 9.181.138.186의 창에 다음을 입력한다.
ant -Dhost=9.181.138.186 DhubURL=http://9.181.138.75:4444 launch-remote-control |
머신 9.181.138.184의 창에 다음을 입력한다.
ant -Dhost=9.181.138.184 DhubURL=http://9.181.138.75:4444 launch-remote-control |
브라우저에서 http://localhost:4444/console에 Hub의 콘솔로 다시 돌아간다. 이제 사용 가능한 대로 네 개의 원격 제어가 나열되어야 한다. 이는 그림 5과 유사하다.
그림 5. Selenium Grid Hub 콘솔
리스트 7의 테스트 클래스 소스 코드를 src 디렉토리에 놓는다.
리스트 7. 테스트 케이스 Java 소스 코드
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;
public class GridTest2(3/4) {
String url = "http://9.181.138.186/index.php";
private Selenium selenium= null;
@Parameters({ "bs" })
@BeforeClass
public void startBroswer()
{
selenium= new DefaultSelenium("localhost", 4444, broswer, url);
selenium.start();
selenium.open(url);
selenium.windowMaximize();
}
@Test
public void test() throws InterruptedException
{
selenium.click("xpath=//a[contains(text(),\'View Time\')]");
//any code is ok
Thread.sleep(10000);
}
@AfterClass
public void clear() {
selenium.stop();
}
}
|
testng.xml 파일의 컨텐츠를 변경한다. 이는 다음 리스트 8에 표시된다.
리스트 8. TestNG 구성 파일 컨텐츠
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="suite1" verbose="1" annotations="JDK" parallel="tests" thread-count="2" >
<test name="test2" junit="false" >
<parameter name="bs" value="*iehta"/>
<classes>
<class name="GridTest2" />
</classes>
</test>
<test name="test3" junit="false">
<parameter name="bs" value="*firefox"/>
<classes>
<class name="GridTest3" />
</classes>
</test>
<test name="test4" junit="false">
<parameter name="bs" value="*firefox"/>
<classes>
<class name="GridTest4" />
</classes>
</test>
</suite>
|
정의된 스레드가 두 가지 뿐이므로 동시에 두 가지 테스트 케이스만 실행할 것이다. 네 가지 원격 제어가 있지만, 허브는 RC1을 선택하여 GridTest2를 실행하고 나머지 두 개의 원격 제어를 선택하여 GridTest3 및 GridTest4를 실행할 것이다. 두 가지 테스트의 병렬 실행은 무작위이다. 그림 6은 허브의 실행 상태를 보여준다.
그림 6. Selenium Grid Hub 콘솔
한 번에 이 세 가지 테스트를 모두 실행하려면
thread-count를 3으로 변경하면 된다.
다른 메소드를 동일한 브라우저로 다른 서버에 병렬로 실행
다른 테스트 케이스를 동일한 브라우저의 다른 서버에 병렬로 실행하려면 다음 Selenium Grid 분배 디렉토리로 이동한다.
ant launch-hub |
머신 9.181.138.186에서 창을 열고 다음을 입력한다.
ant -Dhost=9.181.138.186 DhubURL=http://9.181.138.75:4444 launch-remote-control |
머신 9.181.138.184의 창에 다음을 입력한다.
ant -Dhost=9.181.138.184 DhubURL=http://9.181.138.75:4444 launch-remote-control |
브라우저에서 http://localhost:4444/console에 Hub의 콘솔로 다시 돌아간다. 이제 사용 가능한 것으로 나열되는 세 개 또는 네 개의 원격 제어가 있어야 한다. 리스트 9로부터 테스트 클래스 소스 코드를 src 디렉토리에 놓는다.
리스트 9. 테스트 케이스 Java 소스 코드
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;
import static com.thoughtworks.selenium.grid.tools.
ThreadSafeSeleniumSessionStorage.closeSeleniumSession;
import static com.thoughtworks.selenium.grid.tools.
ThreadSafeSeleniumSessionStorage.session;
import static com.thoughtworks.selenium.grid.tools.
ThreadSafeSeleniumSessionStorage.startSeleniumSession;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
public class GridTest {
String url = "http://9.181.138.186/index.php";
private Selenium selenium;
@BeforeMethod(alwaysRun = true)
protected void startSession() {
startSeleniumSession("localhost", 4444, "*firefox", url);
selenium = session();
selenium.open("/");
selenium.windowMaximize();
}
@AfterMethod(alwaysRun = true)
protected void closeSession() {
closeSeleniumSession();
}
@Test
public void test() throws InterruptedException
{
selenium.click("xpath=//a[contains(text(),\'View Time\')]");
Thread.sleep(10000);
}
@Test
public void test2() throws InterruptedException
{
selenium.click("xpath=//a[contains(text(),\'LA\')]");
Thread.sleep(10000);
}
@Test
public void test3() throws InterruptedException
{
selenium.click("xpath=//a[contains(text(),\'Test Case\')]");
Thread.sleep(10000);
}
}
|
testng.xml 파일의 컨텐츠를 변경한다. 이는 리스트 10에 표시된다.
이 소스 코드는 일반 selenium RC 스크립트와는 매우 다르다. 메소드가 개별적으로 실행되어야 하므로 이는 세션 오브젝트로서 Selenium 오브젝트를 초기화하므로 Selenium은 메소드 이전에 세션을 시작하고 메소드 이후에 세션을 종료해야 한다.
리스트 10. TestNG 구성 파일 컨텐츠
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="suite1" verbose="1" parallel="methods" thread-count="2">
<test name="test" junit="false">
<classes>
<class name="GridTest" />
</classes>
</test>
</suite>
|
parallel 속성이
methods로 변경되며, 이는 클래스에서 메소드가 병렬로
실행될 것임을 의미한다. 클래스는 순차적으로 실행될 것이다.
테스트 결과를 보는 것은 매우 간단하다. build.xml 파일에 정의된 대상 폴더로 이동한 다음 보고서 폴더로 이동한다. index.html을 열고 suite name 링크를 클릭한다. 결과는 그림 7과 같이 표시되어야 한다. 이는 세 번째 테스트 샘플의 결과이다.
그림 7. 테스트 결과
더 자세한 내용은 왼쪽의 chronological 링크를 클릭한다. 다음 그림 8와 같이 자세한 정보를 얻을 수 있다.
그림 8. 자세한 테스트 결과
이 기사에서는 Selenium 테스트를 병렬로 실행하기 위해 Selenium Grid를 사용하는 방법에 대해 살펴봤다. Selenium Grid로 자동화된 웹 애플리케이션 테스팅을 수행하면 시간을 많이 줄일 수 있고 자원을 절약하여 사용할 수 있다. 예를 들어, 두 번째 시나리오에서 설명한 대로 테스터가 100개의 테스트 케이스가 있고 10개의 스레드를 구성하여 테스트 케이스를 실행하면 시간과 노력을 10배 절약할 것이다. 당연히 원격 제어의 숫자는 제한적이다.
병렬 테스팅은 회귀 테스팅을 더 편리하게 만들 수도 있다. 이 기사에서 학습한 내용을 취하여 웹 애플리케이션 테스팅의 속도를 효율적으로 높일 수 있기를 바란다.
교육
-
SeleniumHQ: 많은 플랫폼에 걸쳐 웹 앱 테스팅을
자동화하는 Selenium 도구 제품군에 대해 모두 학습하자.
-
Selenium and Selenium RC
문서: 이 사용자 안내서는 Selenium을 소개하고, 기능을 설명하고
Selenium 커뮤니티에서 축적된 일반적으로 사용되는 우수 사례를 보여준다.
-
Selenium Grid: 여러 머신에서
Selenium Grid가 테스트를 어떻게 분배할 수 있는지에 대해 자세히 읽어보면서 테스트를
병렬로 실행할 수 있다.
-
TestNG:
TestNG 및 TestNG Ant 태스크를 정의하는 방법에 대해 자세히 학습한다.
-
Apache Ant: Apache
Ant 프로젝트에 대해 모두 읽어보자.
-
IBM 기술 이벤트 및 웹 캐스트: developerWorks 기술 이벤트 및
웹 캐스트에 대한 최신 정보를 얻을 수 있다.
제품 및 기술 얻기
-
Selenium Grid:
Selenium Grid를 다운로드하자.
-
TestNG: 유연한 테스팅 프레임워크이자
Selenium의 테스트를 구동하는 데에도 사용할 수 있는 TestNG를 얻을 수 있다.
-
Apache Ant: Apache
Ant, Java 라이브러리 및 명령행 도구를 얻고 대상 및
서로 의존하는 확장 지점으로서 빌드 파일에 설명된 프로세스를 구동하자.
토론
-
Selenium
Grid 커뮤니티: Selenium Grid 커뮤니티에 참여하자.
- 지금 developerWorks 프로파일을 작성하고 Selenium에 대한 관심목록을 설정해보자. developerWorks 커뮤니티에서 최신 정보를 확인하자.
- 웹 개발에 관심이 있는 다른 developerWorks 구성원을 찾아보자.
-
웹 주제를
중점적으로 다루는 developerWorks 그룹 중 하나에 참여하자:
지식을 공유하자.
-
Web 2.0 및 미들웨어: Roland Barcia는 자신의 블로그에서
Web 2.0 및 미들웨어에 대해 설명한다.
- developerWorks 멤버의 공유해
놓은 웹 주제에 대한 책갈피를 따라가 보자.
- Web 2.0 Apps forum을 방문하자: 빠른 대답을 들을 수 있다.
- Ajax forum을 방문하자: 빠른 대답을 들을 수 있다.

