В предыдущей статье мы рассмотрели определение WinForms элементов. Проект автоматизации можно скачать по ссылке GitHub.
Ниже представлен листинг класса App.cs, который представляет тестируемое приложение:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
using ArtOfTest.WebAii.Wpf; using White.Core; using White.Core.UIItems.WindowItems; namespace SampleApp.Tests.Framework.Elements { public class App { public WpfApplication ApplicationWebAii { get; private set; } public Application ApplicationWhite { get; private set; } public App(WpfApplication webAiiApp, Application whiteApp) { ApplicationWebAii = webAiiApp; ApplicationWhite = whiteApp; } public MainWindow MainWindow { get { return new MainWindow( ApplicationWebAii.WaitForWindow(MainWindow.WINDOW_NAME).Find); } } public OpenFile OpenFile { get { return new OpenFile(GetWindowByName("Open")); } } public MessageBox MessageBox { get { return new MessageBox(GetWindowByName("")); } } private Window GetWindowByName(string windowName) { // Workaround as method GetWindow(string title) is not working foreach (Window window in ApplicationWhite.GetWindows()) { if (windowName.Equals(window.Name)) { return window; } } return null; } } } |
Конструктор принимает объект приложений Telerik Testing Framework (WpfApplication) и TestStack White (Application).
Доступ к объектам
Каждое окно в приложении представлено свойством в классе App. Объекты WPF приложения используют метод VisualFind для своей инициализации. Это достигается путем следующего объявления окна с помощью фреймворка Telerik:
1 |
public WpfWindow WaitForWindow(string caption); |
Объектам WinForms соответственно нужен White объект для определения Window.
1 |
public virtual Window GetWindow(string title); |
Этот стандартный метод срабатывает не всегда, поэтому можно использовать следующий вариант:
1 |
private Window GetWindowByName(string windowName); |
Использование экземпляра объекта
В приведенном выше примере каждое действие требует создания нового экземпляра объекта. В некоторых случаях создание объекта может требовать определенного времени или могут понадобится некоторые его, сохраненные во время выполнения кода. В таких случаях вы можете использовать паттерн проектирования Singleton и создавать экземпляр только одного объекта в процессе его использования.
1 2 3 4 5 6 7 8 9 10 11 12 |
private MessageBox messageBox = null; public MessageBox MessageBox { get { if (messageBox == null) { messageBox = new MessageBox(GetWindowByName("")); } return messageBox; } } |
Оба подхода имеют свои плюсы и минусы. В случае создания нового объекта, вы всегда работает со свежей версией, – без сохранения предыдущего состояния. Также это может потребовать больших временных затрат.
Базовый тест
Наконец, чтобы сделать всю работу мы должны создать экземпляр приложения. Экземпляр создается в классе BaseTest.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
using ArtOfTest.WebAii.Core; using SampleApp.Tests.Framework.Elements; using White.Core; namespace SampleApp.Tests.Framework.Tests { public class BaseTest { protected App App { get; set; } private string applicationPath = "C:\\SampleApp\\SampleApp\\bin\\Debug\\SampleApp.exe"; protected void Start() { if (App == null) { Application appWhite = Application.Launch(applicationPath); Manager manager = new Manager(false); manager.Start(); App = new App( manager.ConnectToApplication(appWhite.Process), appWhite); } } protected void Stop() { if (App != null && App.ApplicationWhite != null) { App.ApplicationWhite.Kill(); } App = null; } } } |
Все тесты наследуются от базового тестового класса. Также в нем осуществляется инициализация и разрушение объекта приложения. Он должен вызываться для того, чтобы создать экземпляр класса App.
Для того, чтобы запустить приложение, мы должны указать полный путь к файлу EXE. Открытие приложение выполняется с помощью метода White:
1 |
public static Application Launch(string executable); |
Чтобы использовать фреймворки White и Telerik вместе, необходимо использовать объект Manager для объединения двух процессов:
1 |
public WpfApplication ConnectToApplication(Process proc, string pid = null); |
Использование объектов
Как только вызван метод Start (), тестируемое приложение запускается и оба фреймворка подключаются к нему. В тестах уже можно использовать методы для работы с приложением:
1 |
App.MainWindow.ClickBrowseButton(); |
Этот код находит и создает новый экземпляр MainWindow и затем он в свою очередь находит и нажимает на кнопку “Browse”. Используемые фреймворки содержат всевозможные действия над элементами, которые затем используются в реальных тестах. После того как все работы по написанию основы тестового фреймворка были сделаны, можно приступать к написанию тестов.
Разрушение объекта приложения
Метод Stop() вызывается в конце каждого теста для того, чтобы закрыть приложение и разрушить процесс приложения.
Написание тестов
Для заруска наших тестов будем использовать MS Unit Testing Framework:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
using Microsoft.VisualStudio.TestTools.UnitTesting; using SampleApp.Tests.Framework.Tests; namespace SampleApp.Tests { [TestClass] public class UnitTest1 : BaseTest { [TestInitialize] public void Initialise() { Start(); } [TestMethod] public void OpenFile_OnCancel_GivesMessage() { App.MainWindow.ClickBrowseButton(); App.OpenFile.ClickCancelButton(); Assert.AreEqual("Problem occured, try again later", App.MessageBox.GetText()); App.MessageBox.ClickOkButton(); } [TestMethod] public void OpenFile_OnAttachFile_GivesMessageAndFileIsShown() { string filePath = @"C:\SampleApp\SampleApp\bin\Debug\HappyFace.jpg"; App.MainWindow.ClickBrowseButton(); App.OpenFile.EnterFileName(filePath); App.OpenFile.ClickOpenButton(); Assert.AreEqual("Successfully done", App.MessageBox.GetText()); App.MessageBox.ClickOkButton(); Assert.AreEqual(filePath, App.MainWindow.GetFilePathAtIndex(1)); } [TestCleanup] public void CleanUp() { Stop(); } } } |
Наш тестовый фреймворк предназначен для запуска тестов в случайном порядке. Перед каждым тестом запускается метод с аннотацией [TestInitialize], – осуществляется запуск приложения. После выполнения каждого тестового метода вызывается [TestCleanup]. В нашем случае закрытие приложения. Мы не создаем юнит (unit) тесты, мы используем функциональное тестирование интерфейса.
В следующей статье речь пойдет о том, как запускать наши тесты.