Подтвердить что ты не робот

Как протестировать пользовательский интерфейс WPF?

Использование форм выигрыша с MVC/MVP, Я бы обычно использовал класс, чтобы обернуть представление для проверки пользовательского интерфейса при использовании mocks для модели и контроллера/презентатора. Класс обертки сделает большинство в пользовательском интерфейсе видимым свойством для тестового бегуна через свойства и события.

Будет ли это жизнеспособным подходом к тестированию WPF-приложения? Есть ли способ лучше? Есть ли какие-либо проблемы, требующие внимания?

4b9b3361

Ответ 1

Что касается самого тестирования, вам, вероятно, лучше всего использовать среду автоматизации пользовательского интерфейса. Или, если вы хотите более гибкий и независимый от wpf/winforms/win32/swt способ использования инфраструктуры, вы можете загрузить White из Codeplex (при условии, что вы в состоянии использовать открытый исходный код в своей среде).

Для гочей; Если вы пытаетесь проверить свои представления, вы, вероятно, столкнетесь с некоторыми проблемами многопоточности. Например, если вы работаете с NUnit, стандартный тестовый прогон будет работать в MTA (многопоточная квартира), тогда как WPF должен работать как STA (однопоточная квартира). Mike Two действительно легко приступил к модульному тестированию WPF, но без учета проблем с многопоточностью. У Джоша Смита есть некоторые соображения по поводу темы потоков в этом посте, и он также указывает на эту статью Криса Хедгейта. Крис использует модифицированную версию Peter Provost CrossThreadTestRunner для более дружественного решения проблем MTA/STA.

Ответ 2

@Matt David,

Прочитайте документацию и посмотрите образцы кода для Microsoft CompositeWPF (он же Prism). Это проект, созданный специально для обучения методам работы с архитектурой MVP/MVC в тестовом режиме. Их примерное приложение содержит модульные тесты для презентаторов\контроллеров и очень классные приемочные тесты для пользовательского интерфейса (они используют White framework для имитации действий пользователя)

Ответ 3

Вручную. Я не большой поклонник автоматизированного тестирования пользовательского интерфейса, если это то, что вы получаете. Я не уверен в руководстве WPF (нужно читать через ссылки aku).. потому что они все еще затвердевают, так сказать... WPF не стабилизировался с точки зрения "что это правильный путь". Если вы не используете одну из этих эволюционирующих фреймворков. Я был бы консервативным w.r.t. усилие

  • Тестирование (автоматизированное, предпочтительно TDDed) логических/презентаторов/контроллеров безжалостно. Я не сторонник небрежности или летаргии.
  • Держите пользовательский интерфейс тонким и получите несколько неприятных тестеров, чтобы пойти (ручная) трещина на нем с помощью разведочных испытаний - ничто не так хорошо, как "тестер из ада", когда дело доходит до пользовательских интерфейсов, Усилия: коэффициент усиления от автоматизации такого рода тестирования огромен, не поймает все и не имеет смысла... кроме как умиротворить более высокий "Look Mgr". Без рук! самоконтроля пользовательских интерфейсов!

PS: вы можете посмотреть это (Mary Poppendieck Google Talk on Lean).. особенно часть о том, что автоматизировать в тестировании

Ответ 4

Обновление 2016: используйте бесплатный каркас TestStack.White для автоматизации тестирования пользовательского интерфейса WPF.

  • Project White был заброшен, но его преемник TestStack.White доступен через пакет NuGet.
  • TestStack.White содержит служебные методы для запуска приложений 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();
    }
    

Ответ 5

Prism (Composite WPF) построена в первую очередь с учетом "Testability". Пойдите для этого, если вы считаете, что это подходит вашему развитию.

Также здесь эпизод dotnetrocks, который вы могли бы прослушать, если вам нужна дополнительная информация о Prism в аудио.

Ответ 6

Для основ вы также можете посмотреть несколько коротких видеороликов на канале9 здесь и здесь.

Ответ 7

Вы также можете попробовать Guia. Это позволяет вам напрямую unit test одиночные WPF UserControls.

Ответ 8

Это будет работать просто отлично, проще, чем с выигрышными формами.

Проверьте "Руководство по качеству приложений WPF", он довольно много тестирует интерфейс WPF. Также не забудьте класс AutomationPeer.

Ответ 9

Определенно посмотрите на TestAutomationFX.com. Можно инвестировать (хорошо, я сделал) много времени, пытаясь захватить/записать события с White. (В начале моего квеста я проигнорировал сообщение или два в других местах, ссылающихся на него).

Я, конечно, второй, другие точки, о лучшем типе тестирования, не являющемся тестированием пользовательского интерфейса.

Но если кто-то собирается сделать что-то автоматизированное в пользовательском интерфейсе, чтобы обойти недостатки в других типах тестирования, TAFX кажется самым быстрым маршрутом там.

Ответ 10

Попробуйте Ranorex V2.0 для автоматизации WPF. С кодом идентификации хранилища RanoreXPath и Ranorex можно полностью отделить от информации идентификации. Ranorex также предоставляет редактор захвата/воспроизведения, основанный на объектах RanoreXPath.

Ответ 11

Вместо использования автоматических тестеров вы можете создать настоящие модульные тесты для вашего графического интерфейса с IcuTest.

Ответ 12

Я бы рекомендовал TestAutomationFX также для простой автоматизации тестирования ui. TestAutomationFX позволяет работать с инструментами netAdvantage для wpf, а также работать с белым и QTP. TestAutomationFX имеет простой в использовании интерфейс, он интегрируется с визуальной студией и имеет хороший рекордер для записи пользовательских событий.

Ответ 14

Поскольку срок действия инфраструктуры кодированного пользовательского интерфейса истекает после версии Visual Studio 2019 (устаревший кодированный пользовательский интерфейс), Microsoft рекомендует Appium с WinAppDriver для тестирования приложений Windows (для настольных ПК и UWP).

Вот краткое описание работы с WinAppDriver:

  • загрузите и установите WinAppDriver:

    WinAppDriver Release

  • запустите WinAppDriver:

    C:\Program Files (x86)\Драйвер приложения Windows\WinAppDriver.exe

  • создать новый проект модульного тестирования Visual Studio 2019 (.NET Framework)

  • добавить пакет NuGet: Appium.WebDriver

  • добавить новый класс DesktopSession:
    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().ImplicitlyWait(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.NotepadTest).

Инструменты:

Другие ссылки:

WinAppDriver с или без Appium

Appium