programing

WPF 사용자 인터페이스를 테스트하는 방법

showcode 2023. 4. 20. 23:22
반응형

WPF 사용자 인터페이스를 테스트하는 방법

MVC/MVP 아키텍처에서 win 폼을 사용하면 보통 클래스를 사용하여 UI를 테스트하고 모델 및 컨트롤러/프레젠터의 mock을 사용합니다.래퍼 클래스는 속성 및 이벤트를 통해 UI의 대부분의 항목을 테스트 주자가 관찰할 수 있는 속성으로 만듭니다.

이것이 WPF 앱을 테스트하기 위한 실행 가능한 접근법일까요?더 좋은 방법이 있을까요?조심해야 할 게 있나요?

테스트 자체는 UI Automation 프레임워크를 사용하는 것이 좋습니다.또는 보다 유연하고 wpf/winforms/win32/swt에 의존하지 않는 프레임워크 사용 방법을 원하는 경우 Codeplex에서 White를 다운로드할 수 있습니다(고객 환경에서 오픈 소스 코드를 사용할 수 있는 경우).

gotchas의 경우: 뷰를 테스트하려고 하면 스레드화 문제가 발생할 수 있습니다.예를 들어 NUnit을 실행하는 경우 기본 테스트 러너는 MTA(Multi-Threaded Appartment)에서 실행되지만 WPF는 STA(Single-Threaded Appartment)로 실행되어야 합니다.Mike Two는 유닛 테스트를 쉽게 시작할 수 있지만 스레드 문제는 고려하지 않습니다.Josh Smith는 이 투고에서 스레드화 문제에 대해 몇 가지 생각을 가지고 있으며, Chris Hedgate의 이 기사를 지적하기도 합니다.크리스는 피터 프로보스트의 십자가를 수정한 버전을 사용합니다.ThreadTestRunner를 통해 MTA/STA 문제를 좀 더 알기 쉽게 정리할 수 있습니다.

2016년 업데이트:무료 TestStack을 사용합니다.WPF UI 테스트를 자동화하는 화이트 프레임워크

  • 프로젝트 화이트는 포기되었지만 후속 프로젝트인 TestStack은 포기되었습니다.흰색은 NuGet 패키지를 통해 제공됩니다.
  • 테스트 스택화이트에는 WPF 앱 부팅, 윈도/사용자 제어 요소 검색, 버튼/요소 클릭, 마우스키보드 이벤트 시뮬레이션, 대기 유틸리티 방법이 있습니다.
  • WPF 앱을 실행하고 버튼을 클릭한 후 결과를 확인하는 예는 다음과 같습니다.

    using TestStack.White;
    using TestStack.White.UIItems;
    using TestStack.White.Factory;
    
    [TestMethod]
    public void TestDoSomething()
    {
        //Opens the app
        var app = Application.Launch("MyApp.exe");
    
        //Finds the main window (this and above line should be in [TestInitialize])
        var window = app.GetWindow("My App Window Title", InitializeOption.NoCache);
    
        //Finds the button (see other Get...() methods for options)
        var btnMyButton = window.Get<Button>("btnMyButtonWPFname");
    
        //Simulate clicking
        btnMyButton.Click();
    
        //Gets the result text box 
        //Note: TextBox/Button is in TestStack.White.UIItems namespace
        var txtMyTextBox = window.Get<TextBox>("txtMyTextBox");
    
        //Check for the result
        Assert.IsTrue(txtMyTextBox.Text == "my expected result");
    
        //Close the main window and the app (preferably in [TestCleanup])
        app.Close();
    }
    

@Matt David,

문서를 읽고 Microsoft Composite WPF(일명 프리즘) 코드 샘플을 확인하십시오.이 프로젝트는 MVP/MVC 아키텍처를 테스트 방식으로 처리하는 방법을 가르치기 위해 특별히 만들어진 프로젝트입니다.샘플 어플리케이션에는 발표자/컨트롤러용 유닛 테스트와 UI용 매우 쿨한 수용 테스트가 포함되어 있습니다(사용자 액션을 시뮬레이트하기 위해 화이트 프레임워크를 사용합니다).

수작업으로.저는 자동 UI 테스트를 별로 좋아하지 않습니다.WPF 가이드라인에 대해서는 잘 모르겠습니다(aku의 링크를 읽을 필요가 있습니다).말하자면 아직 굳어지고 있기 때문에...WPF는 '무엇이 옳은 길인가'라는 관점에서 안정되지 않았다.이러한 진화하는 프레임워크 중 하나를 사용하지 않는 한..난 R.T. 노력 없이 보수적으로 살 거야

  • 로직/발표자/컨트롤러를 무자비하게 테스트(가급적 자동 TDD)합니다.는 게으름이나 무기력을 옹호하는 것이 아니다.
  • UI 스킨을 얇게 유지한 채 탐색 테스트를 통해 (수동으로) 시험해 보도록 하십시오. UI에 관한 한 '지옥에서 온 테스터'만큼 좋은 것은 없습니다.이러한 종류의 테스트를 자동화함으로써 얻을 수 있는 비율은 매우 높고, 모든 것을 파악할 수 있는 것은 아니며, 의미가 없습니다.'Look Mgr! No hands! self-testing UIs!'라는 높은 업을 누그러뜨리는 것 빼고는.

추신: 이걸 보세요(Mary Popendick의 Google Talk on Lean). 특히 테스트에서 무엇을 자동화해야 하는지에 대한 부분

코드화된 UI 프레임워크는 Visual Studio 버전 2019(사용되지 않는 코드화된 UI) 이후 만료되므로 Microsoft는 Windows 애플리케이션(데스크탑 및 UWP) 테스트에 WinAppDriver를 사용하는 Appium을 권장합니다.Appium(WinAppDriver 포함) 또는 WinAppDriver를 직접 사용하여 테스트를 실행할 수 있습니다(Appium 유무에 관계없이 WinAppDriver).

직접 WinAppDriver

다음은 WinAppDriver를 직접 사용하기 위한 간단한 설명입니다.

  • WinAppDriver 다운로드 및 설치:

    WinAppDriver 릴리즈

  • 윈도우즈에서 개발자 모드 사용 설정

  • WinAppDriver 를 기동합니다.

    C:\Program Files (x86)\Windows 응용 프로그램 드라이버\WinAppDriver.실행

  • 새로운 Visual Studio 2019 유닛 테스트 프로젝트(.NET 프레임워크)

  • NuGet-Package 추가:아피움Web Driver Microsoft.WinAppDriver.Appium.WebDriver (Microsoft 코멘트:WinAppDriver NuGet 패키지를 사용하여 액션 API에서 고급 입력을 최대한 활용할 것을 권장합니다.)

  • 새 클래스 Desktop Session 추가:

    public class DesktopSession
    {
        protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
        private const string NotepadAppId = @"C:\Windows\System32\notepad.exe";
    
        protected static WindowsDriver<WindowsElement> session;
        protected static WindowsElement editBox;
    
        public static void Setup(TestContext context)
        {
            // Launch a new instance of Notepad application
            if (session == null)
            {
                // Create a new session to launch Notepad application
                var appCapabilities = new DesiredCapabilities();
                appCapabilities.SetCapability("app", NotepadAppId);
                appCapabilities.SetCapability("platformName", "Windows");
                appCapabilities.SetCapability("deviceName ", "WindowsPC");
                session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);
                Assert.IsNotNull(session);
                Assert.IsNotNull(session.SessionId);
    
                // Set implicit timeout to 1.5 seconds to make element search to retry every 500 ms for at most three times
                session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1.5);
    
                // Keep track of the edit box to be used throughout the session
                editBox = session.FindElementByClassName("Edit");
                Assert.IsNotNull(editBox);
            }
        }
    
        public static void TearDown()
        {
            // Close the application and delete the session
            if (session != null)
            {
                session.Close();
    
                try
                {
                    // Dismiss Save dialog if it is blocking the exit
                    session.FindElementByName("Nicht speichern").Click();
                }
                catch { }
    
                session.Quit();
                session = null;
            }
        }
    
        [TestInitialize]
        public void TestInitialize()
        {
            // Select all text and delete to clear the edit box
            editBox.SendKeys(Keys.Control + "a" + Keys.Control);
            editBox.SendKeys(Keys.Delete);
            Assert.AreEqual(string.Empty, editBox.Text);
        }
    } 
  • UnitTest1 클래스에서 코드를 변경합니다.
        [TestClass]
        public class UnitTest1 : DesktopSession
        {
            [TestMethod]
            public void EditorEnterText()
            {
                Thread.Sleep(TimeSpan.FromSeconds(2));
                editBox.SendKeys("abcdeABCDE 12345");
                Assert.AreEqual(@"abcdeABCDE 12345", editBox.Text);
            }
    
            [ClassInitialize]
            public static void ClassInitialize(TestContext context)
            {
                Setup(context);
            }
    
            [ClassCleanup]
            public static void ClassCleanup()
            {
                TearDown();
            }
        }
  • 테스트 실행

(샘플 코드는 주로 WinAppDriver에서 복사됩니다).메모장 테스트).

Appium with WinAppDriver

Appium을 사용하여 테스트를 실행하려면 올바른 버전의 WinAppDriver를 컴퓨터에 설치해야 합니다.Appium 설치 관리자는 올바른 버전의 WinAppDriver도 컴퓨터에 설치해야 합니다(모든 사용자를 위해 Appium을 설치하십시오).제 경우, 안타깝게도 이것은 효과가 없었습니다.그래서 파일을 살펴봅니다.

C:\Program Files\Appium\resources\app\node_modules\appium\node_modules\appium-windows-driver\lib\installer.js

여기서 올바른 버전과 다운로드 경로를 확인할 수 있습니다.

const WAD_VER = "1.1";
const WAD_DL = `https://github.com/Microsoft/WinAppDriver/releases/download/v${WAD_VER}/WindowsApplicationDriver.msi`;

올바른 WinAppDriver가 설치되어 있으면 Appium을 시작할 수 있습니다.

중요: ApplicationDriverUrl을 변경해야 합니다.

protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723/wd/hub";

도구:

Windows AppDriverUI Recoder 릴리스 또는 WinAppDriver 저장소를 Donwload하여 WinAppDriver 구축UIRecorder.서브디렉토리 툴의 slnUIRecorder(UIRecorder)

WinAppDriver UI 레코더 소개

  • inspect.exe:Windows SDK가 필요합니다(C:\Program Files(x86)\ 참조).Windows 키트\10\bin)

기타 링크:WinAppDriver FAQ Appium

그 질문은 여전히 관련이 있지만, 많은 답변들이 쓸모없게 되었다.@deadpikle댓글로 매우 좋은 해결책을 제시했는데, 제가 시도해 봤는데 더 많은 사람들이 볼 수 있도록 답변으로 만들고 싶습니다.

여기 도서관 https://github.com/FlaUI/FlaUI이 있습니다.다음은 WPF 앱의 빠른 시작 안내서입니다.

  1. FlaUI 를 인스톨 합니다.Nuget의 UIA3

  2. 앱이 올바르게 실행되는지 테스트하려면 이 글을 쓰십시오(단 문자열 리터럴을 삽입).

    using FlaUI.Core;
    using FlaUI.Core.AutomationElements;
    using FlaUI.UIA3;
    using FluentAssertions;
    using System;
    using Xunit;
    
    namespace Functional
    {
        public sealed class General : IDisposable
        {
            private readonly Application _app = Application.Launch(@"..\App.exe");
    
            [Fact]
            public void AppStarts()
            {
                using var automation = new UIA3Automation();
                Window window = _app.GetMainWindow(automation, TimeSpan.FromSeconds(3));
    
                window.Should().NotBeNull("null means the window failed to load");
    
                window.Title.Should().Be("App title",
                    "otherwise, it could be message box with error in case of the wrong configuration");
            }
    
            public void Dispose()
            {
                _app.Close();
                _app.Dispose();
            }
        }
    }
    

이 코드는 GitHub Actions 파이프라인에서도 잘 동작합니다.

TestAutomationFX.com을 꼭 봐주세요.화이트와 함께 이벤트를 캡처/녹화하려고 많은 시간을 투자할 수 있습니다(퀘스트 시작 시 다른 곳에서 게시물을 한두 개 무시했습니다).

물론 UI 테스트가 아닌 최상의 테스트 유형에 대한 다른 점은 찬성합니다.

그러나 다른 유형의 테스트 적용 범위에 대한 단점을 극복하기 위해 UI에서 자동화할 수 있는 작업을 수행하려는 경우 TAFX가 가장 빠른 경로로 보입니다.

WPF 자동화를 위해 Ranorex V2.0을 사용해 보십시오.RanoreXPath 및 Ranorex 저장소 테스트 자동화 코드를 식별 정보에서 완전히 분리할 수 있습니다.RanoreXPath 오브젝트에 기반한 캡처/재생 에디터도 제공합니다.

간단한 UI 테스트 자동화를 위해 Test Automation FX도 추천합니다.Test Automation FX를 사용하면 wpf용 netAdvantage 도구를 사용할 수 있습니다.wpf는 흰색 및 QTP와 함께 사용할 수 없습니다.테스트 자동화FX는 사용하기 쉬운 인터페이스를 갖추고 있으며 비주얼 스튜디오와 통합되어 사용자 이벤트를 기록하기 위한 좋은 레코더를 갖추고 있습니다.

언급URL : https://stackoverflow.com/questions/58340/how-to-test-a-wpf-user-interface

반응형