В этой статье я расскажу вам о Xamarin.UITest — фреймворке для приемочного UI тестирования от Xamarin.
Что это такое и как его готовить
Xamarin.UITest сделан на основе Calabash и имеет сходный с ним принцип работы. Однако, тесты на данном фреймворке пишутся на С# и NUnit (в отличие от Calabash, в котором используется Gherkin+Ruby). Фреймворк кроссплатформенный и, следовательно, он позволяет писать тесты как для платформы iOS, так и для Android. Windows Phone не поддерживается, что я лично считаю недостатком данного инструмента. Зато в нем вполне поддерживается тестирование нативных приложений на Java и Objective-C.
![image](https://habrastorage.org/files/bc9/293/8a5/bc92938a5b984c4ab7d5aba9651670df.png)
Почему именно Xamarin.UITest
Конечно, многие из вас могут возразить, мол, для Java и Objective-C существуют свои нативные фреймворки, которые прекрасно справляются с возложенной на них задачей. Но если вам необходимо написать приемочные UI тесты одновременно для двух платформ, Xamarin.UITest придется как нельзя кстати. Более того, в нем есть изкоробочная поддержка Xamarin Test Cloud. Сам тестклауд — штука весьма полезная, но довольно дорогая.
Подробнее о том, как это работает
Механизм работы на iOS и Android отличатется. На iOS в приложение встраивается Nuget пакет, который поднимает http сервер внутри вашего приложения. Вот как это работает на iOS:
![](https://habrastorage.org/files/177/fed/39e/177fed39e30d41c38b26aa2e7fb3672d.png)
При работе с Android дела обстоят немного иначе. По сути, при сборке и запуске тестов на устройство устанавливаются два приложения: ваше и Test Cloud server. Оба они подписываются одним и тем же ключом, поэтому Test Cloud server имеет права на управление вашим приложением. Выглядит это следующим образом:
![](https://habrastorage.org/files/6b4/cec/249/6b4cec2498c649c7a33baa1e2bb70f4a.png)
Встраивается Xаmarin.UITest в солюшн довольно просто, практически за пару кликов. Всего-то и нужно, что создать еще один проект для UI тестов.
![](https://habrastorage.org/files/f26/e54/fa4/f26e54fa4ac44f8bae93fee3356a4cb9.png)
После этих нехитрых действий добавляется проект с шаблоном инициализации и установленными пакетами. Затем, в iOS проект необходимо добавить Nuget пакет Xamarin Test Cloud Agent NuGet, а в AppDelegate мы прописываем следующие строки:
#if DEBUG Xamarin.Calabash.Start(); #endif return true;
Если вы используете замариновскую IDE, то на этом процесс интеграции можно считать завершенным. Для Visual studio придется все делать вручную, но и тут все довольно просто. Помимо манипуляций с iOS проектом, нужно добавить PCL проект и установить в него пакеты Nunit и Xamarin.UITest.
Теперь поговорим о конфигурировании наших тестов
Нас будут интересовать два класса: Tests и Appinitializer. Начнем со второго:
public class AppInitializer { public static IApp StartApp (Platform platform) { // TODO: If the iOS or Android app being tested is included in the solution // then open the Unit Tests window, right click Test Apps, select Add App Project // and select the app projects that should be tested. if (platform == Platform.Android) { return ConfigureApp .Android // TODO: Update this path to point to your Android app and uncomment the // code if the app is not included in the solution. //.ApkFile ("../../../Droid/bin/Debug/xamarinforms.apk") .StartApp (); } return ConfigureApp .iOS // TODO: Update this path to point to your iOS app and uncomment the // code if the app is not included in the solution. //.AppBundle ("../../../iOS/bin/iPhoneSimulator/Debug/XamarinForms.iOS.app") .StartApp (); } }
Кроме указанного в TODO пути к файлам apk и ipa, еще есть целый ряд параметров, например, идентификатор устройства, на котором будут запускаться тесты, api ключ для Xamarin Test Cloud и другие. Сам класс определяет платформу для запуска и стартует тесты на выбранной платформе. Теперь давайте рассмотрим класс Tests:
public class Tests { IApp app; Platform platform; public Tests(Platform platform) { this.platform = platform; } [SetUp] public void BeforeEachTest() { app = AppInitializer.StartApp(platform); } [Test] public void AppLaunches() { app.Repl(); } }
Метод с атрибутом SetUp и будет запускать наши тесты, передавая в StartApp плаформу. К сожалению, “изкоробочный” вариант будет работать только для проекта на Xamarin.Forms. А на MVVM-Cross можно выкрутится как-то так:
public void SetUp () { #if TestiOS Path = "path/to/app"; _app = ConfigureApp.iOS .AppBundle(Path) //Xcode ->Window ->Devices -> Identifier .DeviceIdentifier("Identifier") .StartApp(); #else Path = "path/to/apk"; _app = ConfigureApp .Android .ApkFile (Path) //.EnableLocalScreenshots () .StartApp (); #endif }
Соответственно, нужно создать таргеты TestiOS и TestDroid.
Ну что ж… настроили, запустили, самое время начать писать тесты!
Тесты обычно имеют вполне стандартную структуру Arrange-Act-Assert тот же Nunit, только в профиль. Следует начать с создания теста, сдержащего метод Repl (read-eval-print-loop). Он запускает консольку, в которой с помощью запросов мы можем увидеть структуру видимой части нашего приложения. Делается это вот так:
[Test] public void AppLaunches() { app.Repl(); }
Данный метод вызывает консоль REPL. Для наглядности я выполнил в ней комманду tree, выдодящюю информацию по всем видимым элементам:
![](https://habrastorage.org/files/597/963/897/5979638975bb4a628338c079284a4894.png)
А само приложение при этом выглядит вот так:
![](https://habrastorage.org/files/1dc/b94/0d1/1dcb940d16034cfea64926f2f7dc6023.png)
Для того чтобы взаимодействовать с управляющими элементами, нам нужно использовать методы интерфейса IApp. В данной статье мы рассмотрим всего три из них: Tap(), WaitForElement() и Query(). Хотя их значительно больше, и полный их список со всеми свойствами можно посмотрть здесь.
Для начала нам нужно получить идентификаторы элементов типа AppQuery. Делается это примерно так:
static readonly Func<AppQuery, AppQuery> InitialMessage = c => c.Marked("MyLabel").Text("Hello, Habrahabr!"); static readonly Func<AppQuery, AppQuery> Button = c => c.Marked("MyButton"); static readonly Func<AppQuery, AppQuery> DoneMessage = c => c.Marked("MyLabel").Text("Was clicked");
Итак, мы получили AppQuery для всех элементов и теперь можем с ними взаимодействовать. Давайте же провалидируем стартовое сообщение, тапнем по кнопке и провалидируем полученное сообщение.
[Test] public void AppLaunches() { app.Repl(); // Arrange - Nothing to do because the queries have already been initialized. AppResult[] result = app.Query(InitialMessage); Assert.IsTrue(result.Any(), "The initial message string isn't correct - maybe the app wasn't re-started?"); // Act app.Tap(Button); app.WaitForElement (DoneMessage, "Timeout", TimeSpan.FromSeconds (2)); // Assert result = app.Query(DoneMessage); Assert.IsTrue(result.Any (), "The 'clicked' message is not being displayed."); }
Как видно из примера, методы IApp (экземпляром в данном сучае является app) принимают в качестве входных параметров данные типа AppQuery и возвращают результат типа AppResult[]. Linq выражения при этом применимы только к AppResult[], в связи с чем ассерты выглядят следующим образом. А сам AppResult[] выглядит вот так:
![](https://habrastorage.org/files/643/d26/cf9/643d26cf932846a8a39797e7019813e9.png)
В данном примере при локальном запуске тесты могут запускаться паралельно на обеих платформах, и все результаты будут сыпаться в одну консоль (что, имхо, не очень удобно). Кроме того, можно в пару кликов интегрировать замариновский сервис TestCloud и запускать тесты в облаке. Запуск тестов производится из панели юнит тестов, что довольно удобно.
Помимо агента для запуска тестов в TestCloud необходимо добавить api key (в данном семпле я его не добавлял). Как его получить и применить подробно описано здесь.
На этом, пожалуй, стоит завершить наш краткий экскурс в Xamarin.UITest. Надеюсь, мой обзор был вам полезен. Всем спасибо за внимание.
Ссылка на семпл, который использовался в статье.
Полезные ссылки по теме:
developer.xamarin.com/api/namespace/Xamarin.UITest
developer.xamarin.com/guides/testcloud/uitest/intro-to-uitest
www.nunit.org/index.php?p=quickStart&r=2.6.3
msdn.microsoft.com/ru-ru/library/bb397926.aspx
ссылка на оригинал статьи http://habrahabr.ru/post/269389/
Добавить комментарий