윈도우 운영체제 NRE에서 단위 테스트 실행하기

WinAppDriver 연동 기능은 넥사크로플랫폼 17에서 제공하는 UIAutomation 인터페이스를 사용해 NRE에서 실행하는 앱의 속성을 읽거나 쓰고 파라미터를 지정해 메소드를 실행하는 것을 지원합니다. 셀레니움 같은 UI 자동화 테스트 도구를 사용해 단위 테스트를 작성하고 테스트할 수 있습니다.

이번 장에서는 WinAppDriver를 설치하고 비주얼 스튜디오와 이클립스에서 기본적인 C#, Java 프로젝트를 생성해 넥사크로플랫폼 앱에 연결하는 단계를 살펴봅니다.

WinAppDriver는 윈도우 10 이상 환경에서 동작합니다.

https://github.com/Microsoft/WinAppDriver#system-requirements

WinAppDriver 연동 기능은 17.0.0.1500 이후 버전에서만 지원합니다.

지원 버전이 아니라면 넥사크로플랫폼을 업데이트해주어야 합니다.

WinAppDriver 연동 환경 설정하기

WinAppDriver 설치하기

1

윈도우 운영체제 [설정 > 개발자 기능 사용]에서 "개발자 모드"를 활성화합니다.

해당 모드를 최초 활성화하는 경우에는 운영체제 설정 작업에 약간의 시간이 걸릴 수 있습니다. 시간 여유를 가지고 모드를 활성화해주세요.

2

WinAppDriver 설치 파일(WindowsApplicationDriver.msi)을 내려받습니다.

https://github.com/Microsoft/WinAppDriver

https://github.com/Microsoft/WinAppDriver/releases

3

내려받은 설치 파일(WindowsApplicationDriver.msi)을 실행해 WinAppDriver를 설치합니다.

4

설치 경로에서 WinAppDriver를 관리자 권한으로 실행합니다.

일반적인 설치 경로는 아래와 같습니다.

C:\Program Files (x86)\Windows Application Driver\

5

정상적으로 실행이 되는지 확인합니다.

ip, port 설정을 변경하고자 한다면 아래와 같이 실행합니다.

> WinAppDriver.exe [ip] [port]

개발 도구 설치하기

C# 또는 Java 언어를 사용해 단위테스트 프로젝트를 만들 수 있습니다.

비주얼 스튜디오 설치하기

C# 언어를 사용하고 비주얼 스튜디오를 설치하지 않은 경우 무료로 제공되는 개발 도구를 설치할 수 있습니다.

1

비주얼 스튜디오 커뮤니티 설치 파일(vs_community__xxxx.xxxx.exe)을 내려받습니다.

Visual Studio Community

https://visualstudio.microsoft.com/vs/community/

2

내려받은 설치 파일(vs_community__xxxx.xxxx.exe)을 실행해 비주얼 스튜디오를 설치합니다.

설치 시 필요한 패키지를 내려받는 과정에서 약간의 시간이 걸릴 수 있습니다. 시간 여유를 가지고 설치를 진행해주세요.

3

Workloads 항목에서 "Universal Windows Platform development"를 선택하고 설치를 진행합니다.

개발 환경은 설치 후에도 추가할 수 있습니다.

실행 시 마이크로소프트 계정 로그인하는 창이 표시되는데, 로그인 없이도 테스트는 해볼 수 있습니다.

이클립스 설치하기

Java 언어를 사용하고 이클립스를 설치하지 않은 경우 무료로 제공되는 개발 도구를 설치할 수 있습니다.

1

이클립스 설치 파일(eclipse-inst-win64.exe)을 내려받습니다.

eclipse.org

https://www.eclipse.org/downloads/

2

내려받은 설치 파일(eclipse-inst-win64.exe)을 실행해 이클립스를 설치합니다.

3

개발 유형 선택 단계에서는 "Java Developers" 항목을 선택합니다.

단위테스트 만들고 실행하기

넥사크로플랫폼 앱 만들고 배포하기

간단한 넥사크로플랫폼 앱을 만들고 배포합니다.

이미 설치한 넥사크로플랫폼 앱을 사용하려는 경우에는 이 단계는 지나갑니다.

1

넥사크로 스튜디오를 실행합니다.

2

프로젝트를 생성하고 간단한 폼 화면을 작성합니다.

Button 컴포넌트와 Edit 컴포넌트만 화면에 배치합니다.

3

Button 컴포넌트의 onclick 이벤트 함수를 작성합니다.

Button 컴포넌트 onclick 이벤트가 발생하면 Edit 컴포넌트에 value 속성값을 변경합니다.

this.Button00_onclick = function(obj:nexacro.Button,e:nexacro.ClickEventInfo)
{
	this.Edit00.set_value("BUTTON CLICK");
};

4

메뉴 [Deploy > Packing (Archive&Update)] 항목을 선택하고 배포할 아카이브 파일을 생성합니다.

서버 연결 없이 실행할 수 있도록 Update Type은 "Local"로 지정합니다.

5

[Packing] 버튼을 클릭해 아카이브 파일을 생성되면 [Build App] 버튼을 클릭합니다.

6

Build App 창에서 [Build] 버튼을 클릭해 설치 파일을 생성합니다.

7

생성한 설치 파일을 실행해 넥사크로플랫폼 앱을 설치합니다.

단위테스트 프로젝트 만들기

비주얼 스튜디오에서 단위테스트 프로젝트 만들기

1

비주얼 스튜디오를 실행합니다.

2

새로운 프로젝트 만들기에서 "Unit Test Project"를 선택하고 새로운 프로젝트를 생성합니다.

3

Appium WebDriver 라이브러리를 설치합니다.

메뉴 [Project > Manage NuGet Package]를 선택하고 검색창에서 "Appium"을 입력해서 검색 결과에서 Appium WebDriver 라이브러리를 확인합니다. [Install] 버튼을 클릭하면 라이브러리를 설치합니다.

4

Updates 탭에서 Selenium 관련 패키지를 확인합니다.

최신 버전이 설치된 경우에는 코드가 동작하지 않을 수 있습니다. 최신 버전인 경우에는 3.0.1 버전으로 마이너 업데이트해주세요.

https://github.com/Microsoft/WinAppDriver/issues/497

5

생성된 C# 소스코드파일을 아래와 같이 수정합니다.

아래 코드에서 넥사크로플랫폼 앱 관련 설정을 수정합니다. 앱이 설치된 경로, nexacro.exe 실행 파일 경로, nexacro.exe 실행 옵션을 실제 설치 경로에 맞게 수정합니다.


value

WindowsApplicationDriverUrl

http://127.0.0.1:4723/

NexacroAppDr

C:\\Program Files\\nexacro\\17\\app0201

NexacroAppId

C:\\Program Files\\nexacro\\17\\app0201\\nexacro.exe

NexacroAppAg

-k 'UnitTest' -s 'C:\\Program Files\\nexacro\\17\\app0201\\app0201\\start.json'
using System;
using System.Threading;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium.Windows;
using OpenQA.Selenium.Remote;

namespace UnitTestProject1
{
	[TestClass]
	public class NexaTestSession
	{
		// winappdriver url
		protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723/";
		// app path
		private const string NexacroAppDr = "C:\\Program Files\\nexacro\\17\\app0201";
		// nexacro.exe path
		private const string NexacroAppId = "C:\\Program Files\\nexacro\\17\\app0201\\nexacro.exe";
		// nexacro.exe argument
		private const string NexacroAppAg = "-k 'UnitTest' -s 'C:\\Program Files\\nexacro\\17\\app0201\\app0201\\start.json'";
		// search root
		private const string FindNexacro = "Root";
		// OS/Device
		private const string TestOs = "Windows";
		private const string TestDevice = "WindowsPC";

		// Session Object : WindowsDriver 
		protected static WindowsDriver<WindowsElement> session;

		// WinAppDriver Session Create
		[ClassInitialize]
		public static void Setup(TestContext context)
		{
			// Launch a new instance of nexacro application or find nexacro application
		}

		// WinAppDriver Session Delete
		public static void TearDown()
		{
            // Close the application and delete the session
            if (session != null)
            {
                // Close Session – Close Application
                session.Close();
                // Quit Session
                session.Quit();
                // Delete Session
                session = null;
            }
		}

		[TestMethod]
		public void Test_Session()
		{
            Debug.WriteLine("session:" + session);
            Debug.WriteLine("session.SessionId:" + session.SessionId);
		}
	}
}

6

넥사크로플랫폼 앱을 실행하고 세션을 생성하는 코드를 추가합니다.

위의 코드에서 Setup 메소드를 아래와 같이 수정합니다.

// WinAppDriver Session Create
[ClassInitialize]
public static void Setup(TestContext context)
{
	// Launch a new instance of nexacro application or find nexacro application
	if (session == null)
	{
		// Create a new session to launch nexacro application
		DesiredCapabilities appCapabilities = new DesiredCapabilities();
		TimeSpan time = new TimeSpan(0, 0, 10);

		// Launch Nexacro
		appCapabilities.SetCapability("app", NexacroAppId);
		appCapabilities.SetCapability("appArguments", NexacroAppAg);
		appCapabilities.SetCapability("appWorkingDir", NexacroAppDr);
		appCapabilities.SetCapability("platformName", TestOs);
		appCapabilities.SetCapability("deviceName", TestDevice);

		// Request Remote WinAppDriver Service
	session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities, time);

		// Set implicit timeout to 1.5 seconds to make element search to retry every 500 ms for at most three times
		session.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0.5));
		Thread.Sleep(TimeSpan.FromSeconds(1.0));
	}
}

TimeSpan 설정값에 따라 타임아웃 오류가 발생하는 경우가 있습니다. 그런 경우에는 아래와 같이 설정값을 변경해서 테스트를 진행합니다.


TimeSpan time = new TimeSpan(0, 0, 30);

7

메뉴 [Test > Run > All Tests] 항목을 선택하면 테스트를 진행합니다. 설치한 앱이 실행되는 것을 확인할 수 있습니다.

WinAppDriver을 실행한 콘솔 화면에서 접속 정보와 세션이 생성된 것을 확인할 수 있습니다.

8

비주얼 스튜디오 테스트 탐색기에서는 성공한 테스트 정보를 확인할 수 있습니다.

이클립스에서 단위테스트 프로젝트 만들기

1

이클립스를 실행합니다.

2

메뉴 [File > New > Java Project]를 선택하고 새로운 프로젝트를 생성합니다.

3

필요한 라이브러리를 내려받습니다. 압축된 파일(.zip)은 압축을 해제합니다.

라이브러리

다운로드 경로

Appium Client Libraries

http://appium.io/downloads.html

java-client-7.0.0.jar

Selenium Client

https://www.seleniumhq.org/download/

selenium-java-3.141.59.zip

Apache Commons Lang

http://commons.apache.org/proper/commons-lang/download_lang.cgi

commons-lang3-3.8.1-bin.zip

Apache Commons Lang 라이브러리는 실행 중 아래와 같은 오류 발생 시 내려받아 설치합니다.

개발 환경에 따라 필요없을 수도 있습니다.

java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils

4

JUnit 라이브러리를 추가합니다. 메뉴 [Project > Properties > Java Build Path > Libraries] 탭을 선택하고 [Add Library] 버튼을 클릭합니다.

5

Appium, Selenium 라이브러리를 추가합니다. [Add External JARs] 버튼을 클릭하고 내려받은 라이브러리 파일에서 JAR 파일을 추가합니다.

6

[Apply and Close] 버튼을 클릭해 변경한 내용을 적용합니다.

7

메뉴 [File > New > Class]를 선택하고 새로운 클래스 파일을 생성합니다. Name 항목만 입력하고 다른 옵션은 수정하지 않습니다.

8

생성된 Java 소스코드파일을 아래와 같이 수정합니다.

아래 코드에서 넥사크로플랫폼 앱 관련 설정을 수정합니다. 앱이 설치된 경로, nexacro.exe 실행 파일 경로, nexacro.exe 실행 옵션을 실제 설치 경로에 맞게 수정합니다.


value

WindowsApplicationDriverUrl

http://127.0.0.1:4723/

NexacroAppDr

C:\\Program Files (x86)\\nexacro\\17\\app0201

NexacroAppId

C:\\Program Files (x86)\\nexacro\\17\\app0201\\nexacro.exe

NexacroAppAg

-k 'UnitTest' -s 'C:\\Program Files (x86)\\nexacro\\17\\app0201\\app0201\\start.json'
import org.junit.*;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebElement;
import io.appium.java_client.windows.WindowsDriver;
import java.util.concurrent.TimeUnit;
import java.net.URL;

public class UnitTest {

	// winappdriver url
	private String WindowsApplicationDriverUrl = "http://127.0.0.1:4723/";
	// app path
	private String NexacroAppDr = "C:\\Program Files (x86)\\nexacro\\17\\app0201";
	// nexacro.exe path
	private String NexacroAppId = "C:\\Program Files (x86)\\nexacro\\17\\app0201\\nexacro.exe";
	// nexacro.exe argument
	private String NexacroAppAg = "-k 'UnitTest' -s 'C:\\Program Files (x86)\\nexacro\\17\\app0201\\app0201\\start.json'";
	// search root
	// private String FindNexacro = "Root";

	// OS/Device
	private String TestOs = "Windows";
	private String TestDevice = "WindowsPC";

	// Session Object : WindowsDriver
	private static WindowsDriver<RemoteWebElement> session = null;
	

	@Before
	public void setUp() throws Exception {
		// Launch a new instance of nexacro application or find nexacro application
	}

	@After
	public void tearDown() throws Exception {
		if (session != null) {
			// Nexacro17Session.quit();
		}
	}

	@Test
    public void Test_01_Session()
    {
        System.out.println("session : " + session);
		System.out.println("session.SessionId : " + session.getSessionId());        
    }
}

9

넥사크로플랫폼 앱을 실행하고 세션을 생성하는 코드를 추가합니다.

위의 코드에서 Setup 메소드를 아래와 같이 수정합니다.

@Before
public void setUp() throws Exception {
	// Launch a new instance of nexacro application or find nexacro application
	try {
		// Create a new session to launch nexacro application
		DesiredCapabilities appCapabilities = new DesiredCapabilities();

		appCapabilities.setCapability("app", NexacroAppId);
		appCapabilities.setCapability("appArguments", NexacroAppAg);
		appCapabilities.setCapability("appWorkingDir", NexacroAppDr);
		appCapabilities.setCapability("platformName", TestOs);
		appCapabilities.setCapability("deviceName", TestDevice);

		// Request Remote WinAppDriver Service
		session = new WindowsDriver<RemoteWebElement>(new URL(WindowsApplicationDriverUrl), appCapabilities);
		session.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);

	} catch (Exception e) {
		e.printStackTrace();
	} finally {
	}
}

10

메뉴 [Run > Run As > JUnit Test] 항목을 선택하면 테스트를 진행합니다. 설치한 앱이 실행되는 것을 확인할 수 있습니다.

WinAppDriver을 실행한 콘솔 화면에서 접속 정보와 세션이 생성된 것을 확인할 수 있습니다.

11

JUnit 패널에서 성공한 테스트 정보를 확인할 수 있습니다.

단위테스트 실행하기

1

단위테스트를 실행할 코드를 아래와 같이 추가합니다.

현재 세션에서 Button 컴포넌트를 찾고 마우스 클릭 명령을 처리합니다.

$r_title(C#)
[TestMethod]
public void Test_Button()
{
	WindowsElement element = session.FindElementByAccessibilityId("mainframe.WorkFrame.form.Button00");
	Assert.IsNotNull(element);
	Thread.Sleep(TimeSpan.FromSeconds(0.1));
	element.Click();
}
$r_title(Java)
@Test
public void Test_Button() throws Exception {
	WebElement element = session.findElementByAccessibilityId("mainframe.WorkFrame.form.Button00");
	Assert.assertNotNull(element);
	Thread.sleep(1000);
	element.click();
}

2

테스트를 실행하면 설치한 앱이 실행되고 Button 컴포넌트 위에 마우스 커서가 위치하고 클릭 명령을 실행하는 것을 확인할 수 있습니다.

AccessibilityId 속성값 확인하기

컴포넌트나 컨트롤에 접근하기 위해서 FindElementByAccessibilityId 메소드를 사용하는데 이때 AccessibilityId 속성값을 확인해야 합니다.

컴포넌트 속성값 확인하기

Form에 배치된 컴포넌트 자체에 접근하는 방식은 아래와 같습니다.

[MainFrame id 속성값].[ChildFrame id 속성값].form.[Component id 속성값]

id 속성값이 "Button00"인 Button 컴포넌트의 엘리먼트를 얻기 위해서는 아래와 같이 코드를 작성합니다.

$r_title(C#)

WindowsElement element = session.FindElementByAccessibilityId("mainframe.ChildFrame00.form.Button00");

Div 컴포넌트 안에 배치한 컴포넌트는 아래와 같이 접근할 수 있습니다.

$r_title(C#)

WindowsElement element = session.FindElementByAccessibilityId("mainframe.ChildFrame00.form.Div00.form.CheckBox00");

컨트롤, 아이템 속성값 확인하기

예를 들어 Div 컴포넌트 안에 배치된 Combo 컴포넌트의 dropbutton은 아래와 같이 엘리먼트를 얻을 수 있습니다.

$r_title(C#)

WindowsElement element = session.FindElementByAccessibilityId("mainframe.ChildFrame00.form.Div00.form.Combo00.dropbutton");

단위 테스트를 진행하기 위해서는 Combo 컴포넌트의 드롭다운목록을 펼치고 아이템을 선택해야 합니다. 드롭다운목록을 펼치기 위해서는 Combo 컴포넌트 내 ButtonControl에 접근해야 하고 해당 컨트롤의 속성값을 확인해야 합니다.

컨트롤 속성값은 넥사크로 스튜디오에서 Help(단축키 F1)을 실행하면 컴포넌트 개요에서 확인할 수 있습니다. Combo 컴포넌트에서 드롭다운목록을 펼치기 위해 클릭하는 버튼의 id 속성값이 "dropbutton"이라는 것을 확인할 수 있습니다.

Inspect로 속성값 확인하기

도움말에서 노출되지 않는 속성값(하위 컨트롤)은 제품 버전에 따라 변경될 수 있습니다.

해당 속성값 변경 시 작성된 테스트가 동작하지 않을 수 있습니다.

하지만 드롭다운목록을 펼친 후에 Item 3에 접근하려면 어떻게 해야 하는지는 알려주지 않습니다. 이런 경우에는 "Inspect" 라는 도구를 사용합니다. "Inspect"는 윈도우 SDK가 설치되어 있다면 설치 경로에서 찾을 수 있습니다.

Inspect

https://docs.microsoft.com/en-us/windows/desktop/winauto/inspect-objects

1

윈도우 SDK 설치 경로에서 inspect.exe 파일을 실행합니다.

2

넥사크로플랫폼 앱을 실행하고 마우스 커서를 원하는 위치로 가져갑니다.

3

Combo 컴포넌트의 dropdown 버튼을 클릭해서 드롭다운 목록을 펼칩니다.

4

원하는 아이템 영역에 마우스 커서를 가져갑니다. 아래 그림처럼 Inspect가 인식한 대상 영역에 테두리선이 표시되고 Inspect 창에 관련 정보가 표시됩니다.

여러 정보가 보여지는데 그 중에서 AccessibilityId 속성값으로 사용할 항목은 "AutomationId"입니다.

드롭다운목록에서 2번째 아이템을 선택할 때는 아래와 같이 엘리먼트를 얻을 수 있습니다.

$r_title(C#)

WindowsElement element = session.FindElementByAccessibilityId("mainframe.ChildFrame00.form.Div00.form.Combo00.combolist.item_1");

아이템에 해당하는 엘리먼트는 드롭다운목록이 펼쳐진 후에 접근할 수 있습니다. 목록을 펼치기 전에 해당 아이템에 접근하려 한다면 테스트 실패로 처리됩니다.

테스트 코드에서 아래와 같이 먼저 dropbutton 엘리먼트를 찾아서 마우스 클릭 이벤트를 처리하고 드롭다운목록이 펼쳐지면 그때 원하는 아이템에 접근합니다.

$r_title(C#)

[TestMethod]
public void Test_00_FindElementItem()
{
	WindowsElement element = session.FindElementByAccessibilityId("mainframe.ChildFrame00.form.Div00.form.Combo00.dropbutton");
	Assert.IsNotNull(element);
	element.Click();
	Thread.Sleep(TimeSpan.FromSeconds(0.1));
	WindowsElement elementItem = session.FindElementByAccessibilityId("mainframe.ChildFrame00.form.Div00.form.Combo00.combolist.item_1");
	Assert.IsNotNull(elementItem);
	Debug.WriteLine("elementItem.Text:" + elementItem.Text);
}

기능별 데모 단위 테스트 실행하기

기능별 데모를 실행하기 위한 넥사크로플랫폼 앱 설치파일과 Java, C# 샘플 파일을 내려받을 수 있습니다.

1

웹브라우저에서 아래 주소로 접속합니다.

https://github.com/TOBESOFT-DOCS/sample_nexacroplatform_17_winappdriver

2개의 폴더와 하나의 설치파일을 확인할 수 있습니다.

2

nexacro17_SetupRuntime_x86.exe 파일을 내려받습니다. 파일명을 마우스로 클릭하면 [Download] 버튼을 확인할 수 있습니다.

3

내려받은 설치파일을 실행해 앱을 설치합니다. 아래 경로에 앱이 설치됩니다.

C:\Program Files (x86)\nexacro\17\app0201

4

단위테스트 프로젝트 만들기에서 만든 프로젝트에 C#, Java 샘플을 붙여넣습니다.

5

단위테스트를 실행합니다. 정상적으로 단위테스트가 처리되는지 확인합니다.

지원 인터페이스

SeleniumRC, Appium 인터페이스를 모두 지원하지는 않습니다.

넥사크로 플랫폼에서 지원할 수 없거나 WinAppDriver에서 지원하지 않는 기능은 제외했습니다.

아래 항목은 클라이언트에서 별도 인터페이스를 지원하지 않고 웹브라우저에서 직접 호출하거나 HttpWebResponse 등을 사용해 호출한 경우 사용할 수 있습니다.

HTTP

WebDriver

WinAppDriver

GET

/status

/status

GET


/sessions

GET

/session/{session id}/window

/session/:sessionId/window

GET

/session/{session id}/window/handles

/session/:sessionId/window/handles

POST

/session/{session id}/window/maximize

/session/:sessionId/window/maximize

Session

세션 생성하기

winappdriver 정보로 세션을 생성하고 앱을 실행합니다.

C#

session = new WindowsDriver(new Uri(WinAppDriverUrl), appCapabilities);

Java

session = new WindowsDriver(new URL(WindowsApplicationDriverUrl), appCapabilities);

통신

POST /session { …capabilities json data… }

세션 종료하기

세션을 종료하고 해당 앱을 종료합니다.

C#

session.Quit();

Java

session.quit();

통신

DELETE /session/:session_id

WinAppDriver에서 제공하는 인터페이스 중 일부는 넥사크로플랫폼에서 지원하지 않습니다.

Timeout

타임아웃 설정하기

세션 동작 시 적용할 timeout 값을 설정합니다.

C#

session.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0.5));

Java

session.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);

통신

POST /session/:session_id/timeouts {"type":"implicit","ms":500.0}

Frame

Mainframe 정보 확인하기

MainFrame 오브젝트의 titletext 속성값을 반환합니다.

C#

session.Title;

Java

session.getTitle();

통신

GET /session/:sessionId/title

Window

활성화된 윈도우 변경하기

현재 윈도우를 변경합니다. Windowhandle은 session.WindowHandles에서 얻을 수 있습니다. 최초 실행시에는 MainFrame 오브젝트가 현재 윈도우로 설정됩니다.

C#

session.SwitchTo().Window(session.WindowHandles[0]);

Java

Set<String> handles = session.getWindowHandles();
Set handles = session.getWindowHandles();

통신

POST /session/:sessionId/window {"name":"0x000A12BC"}

활성화된 윈도우 종료하기

현재 윈도우를 종료합니다.

C#

session.Close();

Java

session.close();

통신

DELETE /session/:sessionId/window

활성화된 윈도우 핸들 얻기

현재 윈도우 핸들 오브젝트를 반환합니다.

C#

handle = session.CurrentWindowHandle;

Java

Handle = session.getWindowHandle();

통신

GET /session/:sessionId/window_handle

윈도우 핸들 배열 얻기

모든 윈도우 핸들 오브젝트를 배열 형태로 반환합니다.

C#

handlearray = session.WindowHandles;

Java

Set handles = session.getWindowHandles();

통신

GET /session/:sessionId/window_handles

윈도우 크기 정보 확인하기

윈도우 크기를 Size 오브젝트 형태로 반환합니다.

C#

session.Manage().Window.Size;

Java

session.getWindowHandles().size()

통신

GET /session/:sessionId/window/:windowHandle/size

윈도우 크기 변경하기

윈도우 크기를 변경합니다.

C#

session.Manage().Window.Size = new Size(width,height);

Java

session.manage().window().setSize(new Dimension(width, height));

통신

POST /session/:sessionId/window/:windowHandle/size

윈도우 위치 정보 확인하기

윈도우 위치를 Point 오브젝트 형태로 반환합니다.

C#

point = session.Manage().Window.Position;

Java

point = session.manage().window().getPosition()

통신

GET /session/:sessionId/window/:windowHandle/position

윈도우 위치 변경하기

윈도우 좌표를 변경합니다.

C#

session.Manage().Window.Position = new Point(left,top);

Java

session.manage().window().setPosition(new Point(left, top))

통신

POST /session/:sessionId/window/:windowHandle/position

윈도우 최대화

윈도우 크기를 최대화합니다.

C#

session.Manage().Window.Maxmize();

Java

session.manage().window().maximize();

통신

POST /session/:sessionId/window/:windowHandle/maximize

Element

Element는 WinAppDriver 동작의 최소단위입니다. 넥사크로플랫폼에서는 컴포넌트, 컨트롤의 구성요소인 nexacro Element를 Element로 처리합니다.

ControlElement가 컴포넌트를 둘러싸고 있고 그 안에 ContainerElement, InputElement, IconTextElement, TextElement 등의 Element가 자리잡고 있습니다. Button 컴포넌트의 경우는 아래와 같이 구성됩니다.

엘리먼트 얻기

컴포넌트, 컨트롤의 ControlElement 오브젝트를 반환합니다.

C#

element = session.FindElementByAccessibilityId("mainframe.ChildFrame00.form.Button00");

Java

element = session.findElementByAccessibilityId("mainframe.ChildFrame00.form.Button00");

통신

POST /session/:sessionId/element 
{ "using":"accessibilityid", "value":"mainframe.ChildFrame00.form.Button00" }

넥사크로 플랫폼에서 open 메소드 실행 시 objParentFrame 파라미터값을 null로 설정한 경우에는 ChildFrame ID를 기준으로 접근합니다.

$r_title(C#)

// parent null 지정시 : nexacro.open("openframe", url, null, ...) 
nexaButton00 = session.FindElementByAccessibilityId("openframe.form.Button00");

// parent frame 지정시 : nexacro.open("openframe", url, ownerframe, ...)
nexaButton00 = session.FindElementByAccessibilityId("mainframe.ChildFrame00.openframe.form.Button00");

엘리먼트 배열 얻기

컴포넌트, 컨트롤의 ControlElement 오브젝트 목록을 배열값으로 반환합니다.

C#

element = session.FindElementsByAccessibilityId("mainframe.ChildFrame00.form.Button00");

Java

element = session.findElementsByAccessibilityId("mainframe.ChildFrame00.form.Button00");

통신

POST /session/:sessionId/elements 
{ "using":"accessibilityid", "value":"mainframe.ChildFrame00.form.Button00" }

엘리먼트 id값 확인하기

WinAppDriver Element의 id값을 반환합니다.

C#

id = element.Id;

Java

id = element.getTagName()

통신

GET /session/:sessionId/element/:id/name

엘리먼트에 표시되는 텍스트 정보 확인하기

Element의 텍스트값을 반환합니다.

C#

text = element.Text;

Java

text = element.getText();

통신

GET /session/:sessionId/element/:id/text

넥사크로플랫폼에서 지정한 속성값은 화면에 보여지는 텍스트를 우선적으로 처리합니다. 우선순위는 아래와 같습니다.

displaytext > text > titletext > value

엘리먼트 마우스 클릭 이벤트 처리하기

Element의 가운데 위치에서 마우스 클릭 이벤트가 발생합니다.

C#

element.Click();

Java

element.click();

통신

POST /session/:sessionId/element/:id/click

엘리먼트의 가운데 위치에서 마우스 클릭 이벤트가 발생하기 때문에 MaskEdit 컴포넌트 같은 경우 캐럿 위치가 맨 앞으로 이동하지 않습니다. 이런 경우에는 CTRL+"A" 키를 입력해서 입력 영역 전체 선택 후 문자열을 입력하는 방법을 사용할 수 있습니다.

$r_title(C#)

[TestMethod]
public void Test_10_MaskEditInput()
{
	WindowsElement nexaMaskEdit00 = session.FindElementByAccessibilityId("mainframe.ChildFrame00.form.MaskEdit00");
	Assert.IsNotNull(nexaMaskEdit00);
	Thread.Sleep(TimeSpan.FromSeconds(0.1));

	nexaMaskEdit00.Clear();
	nexaMaskEdit00.Click();
	nexaMaskEdit00.SendKeys(Keys.Control + "a");
	Thread.Sleep(TimeSpan.FromSeconds(0.1));
	nexaMaskEdit00.SendKeys("abcde1234"+Keys.Enter);
	Assert.AreEqual("abcde-1234", nexaMaskEdit00.Text);
}

엘리먼트 입력값 지우기

텍스트 편집 영역을 가지고 있는 컴포넌트의 입력값을 지웁니다.

C#

element.Clear();

Java

element.clear();

통신

POST /session/:sessionId/element/:id/clear

엘리먼트에 키보드 입력값 전달하기

키보드 입력값을 처리합니다.

C#

element.SendKeys(KeyString)

Java

element.sendKeys(KeyString)

통신

POST /session/:sessionId/element/:id/value

컴포넌트에 따라 입력값이 처리되는 방식이 다릅니다.

제품 도움말에서 컴포넌트의 "Basic Key Action" 항목을 참고해주세요.


키보드 입력 값 전달 시에는 해당 앱이 활성화되어 있어야 하고 2개 이상의 윈도우가 표시된 경우 동작 대상 윈도우가 활성화되어야 합니다.

동작 대상 엘리먼트에 마우스 클릭 이벤트를 처리한 후 키보드 입력 값을 전달해야 정상적으로 동작합니다.

2개 이상의 디스플레이를 사용하는 경우 키보드 입력 값이 정상적으로 전달되지 않는 경우가 있습니다. 디스플레이를 하나만 사용하던지, WinAppDriver를 다시 시작해주세요.

엘리먼트 선택 여부 확인하기

Element의 Selected 상태값을 반환합니다.

C#

isSelected = element.Selected;

Java

isSelected = element.isSelected();

통신

GET /session/:sessionId/element/:id/selected

넥사크로플랫폼에서 지원하는 컴포넌트, 컨트롤은 아래와 같습니다.

CheckBox, RadioButton, TabButton, ListBoxItem, MenuItem, TreeCell, GridCell

엘리먼트 사용 가능 여부 확인하기

Element의 Enabled 상태값을 반환합니다.

C#

isEnabled = element.Enabled;

Java

isEnabled = element.isEnabled();

통신

GET /session/:sessionId/element/:id/enabled

엘리먼트 화면 표시 여부 확인하기

Element의 화면 표시 여부를 반환합니다.

C#

isDisplayed = element.Displayed;

Java

isDisplayed = element.isDisplayed();

통신

GET /session/:sessionId/element/:id/displayed

컴포넌트의 visible 속성값을 반환하는 것이 아니라 실제 화면에서의 표시 여부를 반환합니다.

element.Displayed

입력동작

true

visible = true

화면 영역에 컴포넌트 전부 또는 일부가 보여지는 경우

false

visible = false

visible = true 이지만 상위 컨테이너 컴포넌트의 스크롤바를 이동하지 않으면 화면에 보이지 않는 영역에 위치한 경우

컴포넌트의 visible 속성값을 false로 설정하고 앱이 시작하는 경우 해당 Element를 찾을 수 없습니다. 넥사크로플랫폼에서는 visible 속성값이 true인 경우에만 Element를 생성하기 때문입니다.

앱 로드 시에는 visible 속성값을 true로 설정하고 onload 이벤트 함수 내에서 컴포넌트의 visible 속성값을 false로 변경하면 Element를 처리할 수 있습니다.

엘리먼트 크기 정보 확인하기

Element 크기를 Size 오브젝트 형태로 반환합니다.

C#

size = element.Size;

Java

size = element.getSize();

통신

GET /session/:sessionId/element/:id/size

엘리먼트 위치 정보 확인하기 (상위 엘리먼트 기준)

Element 위치를 상위 Element 기준에서 Point 오브젝트 형태로 반환합니다.

C#

size = element.Location;

Java

size = element.getLocation();

통신

GET /session/:sessionId/element/:id/location

엘리먼트 위치 정보 확인하기 (Screen 기준)

Element 위치를 Screen 기준에서 Point 오브젝트 형태로 반환합니다.

C#

size = element.LocationOnScreenOnceScrolledIntoView;

Java

지원하지 않음

통신

GET /session/:sessionId/element/:id/location_in_view

활성화된 엘리먼트 얻기

현재 활성화된 Element를 반환합니다.

C#

element = session.SwitchTo().ActiveElement();

Java

element = session.switchTo().activeElement();

통신

GET /session/:sessionId/element/active

2개의 엘리먼트 비교하기

Element를 비교해서 같은 Element인지 확인합니다.

C#

isEqual = element.Equals(element2);

Java

isEqual = element.equals(element2);

통신

GET /session/:sessionId/element/:id/equals

엘리먼트의 UIA 인터페이스 속성값 확인하기

Element의 UIA Interface의 attribute 값을 제공합니다.

C#

element.GetAttribute("AutomationId");

Java

element.getAttribute("AutomationId");

통신

GET /session/:sessionId/element/:id/attribute/:name

Automation Element Property Identifiers

https://docs.microsoft.com/en-us/windows/desktop/WinAuto/uiauto-automation-element-propids

ScreenShot

윈도우, 엘리먼트 스크린샷 얻기

Screen 윈도우 영역 또는 Element를 Screenshot 오브젝트로 반환합니다.

C#

Screenshot sessionshot = session.GetScreenshot();

Java

Screenshot sessionshot = session.getScreenshotAs();

통신

GET /session/:sessionId/screenshot 
GET /session/:sessionId/element/:id/screenshot

SaveAsFile 메소드, AsBase64EncodedString 속성을 사용해 이미지 파일 또는 Base64 형태로 변환할 수 있습니다.

윈도우가 최상위에 노출되어야 정상적인 스크린샷을 얻을 수 있습니다.

Java 코드에서는 권한이 있는 저장소만 접근할 수 있습니다.

$r_title(Java)

FileHandler.copy(sessionshot, new File(System.getProperty("user.home")+"\\Downloads\\SessionScreenShot.png"));

관련 링크 정보

WebDriver Interface

http://www.w3.org/TR/webdriver1/
https://www.seleniumhq.org/projects/webdriver/
https://developer.mozilla.org/en-US/docs/Web/WebDriver

AppDriver Interface

https://github.com/Microsoft/WinAppDriver
https://appium.io/docs/en/drivers/windows/
https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/

UIA Interface

https://docs.microsoft.com/en-us/windows/desktop/WinAuto/entry-uiauto-win32
https://docs.microsoft.com/en-us/windows/desktop/winauto/testing-tools
https://en.wikipedia.org/wiki/Microsoft_UI_Automation

MSAA Interface

https://docs.microsoft.com/en-us/windows/desktop/WinAuto/microsoft-active-accessibility
https://docs.microsoft.com/en-us/windows/desktop/winauto/testing-tools
https://en.wikipedia.org/wiki/Microsoft_Active_Accessibility