Udostępnij za pośrednictwem


Xamarin.UITest

Ważne

Program Visual Studio App Center ma zostać wycofany 31 marca 2025 r. Mimo że możesz nadal używać programu Visual Studio App Center do momentu jej pełnego wycofania, istnieje kilka zalecanych alternatyw, do których można rozważyć migrację.

Dowiedz się więcej o osiach czasu pomocy technicznej i alternatywach.

Xamarin.UITest to platforma testowania języka C# korzystająca z narzędzia NUnit na potrzeby testów akceptacyjnych interfejsu użytkownika w aplikacjach dla systemów iOS i Android. Integruje się ściśle z projektami Xamarin.iOS i Xamarin.Android, ale może być również używany z natywnymi projektami systemów iOS i Android. Xamarin.UITest to biblioteka automatyzacji , która umożliwia wykonywanie testów NUnit na urządzeniach z systemami Android i iOS. Testy współdziałają z interfejsem użytkownika jako użytkownik: wprowadzanie tekstu, naciśnięcie przycisków i gestów — takich jak przesunięcia.

Zazwyczaj każdy test Xamarin.UITest jest zapisywany jako metoda, która jest nazywana [Test]. Klasa zawierająca test jest znana jako [TestFixture]. Urządzenie testowe zawiera pojedynczy test lub grupę testów. Urządzenie jest również odpowiedzialne za konfigurację w celu uruchomienia testu i czyszczenia, które należy wykonać po zakończeniu testu. Każdy test powinien być zgodny ze wzorcem Arrange-Act-Assert :

  1. Rozmieść: test skonfiguruje warunki i zainicjuje elementy, aby można było wykonać test.
  2. Act: Test będzie wchodzić w interakcje z aplikacją, wprowadzać tekst, naciskać przyciski itd.
  3. Potwierdzenie: test sprawdza wyniki akcji uruchamianych w kroku Ustawy, aby określić poprawność. Na przykład aplikacja może sprawdzić, czy jest wyświetlany określony komunikat o błędzie.

Najlepszym momentem na rozpoczęcie pracy z narzędziem Xamarin.UITest jest tworzenie aplikacji mobilnej. Testy automatyczne są zapisywane jako funkcja opracowywana zgodnie z krokami opisanymi na poniższej liście:

  1. Opracowywanie funkcji w aplikacji dla systemu Android lub iOS.
  2. Napisz testy i uruchom je lokalnie, aby zweryfikować funkcjonalność.
  3. Utwórz nowy przebieg testu w usłudze App Center Test lub użyj istniejącego przebiegu testu.
  4. Skompiluj protokół IPA lub APK, a następnie przekaż go wraz z testami do usługi App Center Test.
  5. Rozwiąż wszelkie problemy lub usterki, które są uwidocznione przez test centrum aplikacji.
  6. Powtórz ten proces, przechodząc do następnej funkcji aplikacji.

W przypadku istniejących aplikacji, które nie są już aktywne, może nie być opłacalne, aby ponownie dodać testy automatyczne. Zamiast tego lepszym rozwiązaniem jest użycie narzędzia Xamarin.UITest podczas naprawiania usterek. Rozważmy na przykład aplikację, która nie ma zautomatyzowanego testowania, a użytkownik zgłasza usterkę. Deweloper przypisany do rozwiązania tej usterki może wykonać niektóre (lub wszystkie) z następujących akcji:

  • Sprawdź usterkę lub regresję ręcznie.
  • Napisz test przy użyciu narzędzia Xamarin.UITest, który demonstruje usterkę.
  • Prześlij test do usługi App Center, aby uzyskać szczegółowe informacje na temat zakresu i wpływu usterki na odpowiednich urządzeniach.
  • Usunięcie błędu.
  • Udowodnij, że usterka została usunięta z przekazywaniem narzędzia Xamarin.UITest.
  • Prześlij poprawki i przetestuj do usługi App Center Test, aby sprawdzić, czy usterka została usunięta na odpowiednich urządzeniach.
  • Sprawdź przekazywanie testów do kontroli wersji.

Zautomatyzowane testowanie interfejsu użytkownika opiera się w dużym stopniu na lokalizowanie widoków na ekranie i interakcję z nimi. Platforma Xamarin.UITest rozwiązuje to wymaganie z dwoma ważnymi zestawami interfejsów API, które współpracują ze sobą:

  1. Akcje , które można wykonywać w widokach — Xamarin.UITest udostępnia interfejsy API, które umożliwiają testowi symulowanie typowych akcji użytkownika, takich jak naciśnięcie widoku, wprowadzanie tekstu lub przesuwanie w widoku.
  2. Zapytania dotyczące lokalizowania widoków na ekranie — część struktury Xamarin.UITest to interfejsy API, które znajdą widoki na ekranie. Zapytania lokalizują widoki w czasie wykonywania, sprawdzając atrybuty widoku i zwracając obiekt, na którym mogą działać akcje. Wykonywanie zapytań w taki sposób jest zaawansowaną techniką, która umożliwia pisanie testów dla interfejsów użytkownika niezależnie od rozmiaru, orientacji lub układu ekranu

Aby ułatwić pisanie testów, platforma Xamarin.UITest udostępnia pętlę read-eval-print-loop (REPL). RePL umożliwia deweloperom i testerom interakcję z ekranem podczas uruchamiania aplikacji i upraszcza tworzenie zapytań.

Wprowadzenie do interfejsu API Xamarin.UITest

Wszystkie interakcje testowe z aplikacją mobilną są wykonywane za pośrednictwem wystąpienia programu Xamarin.UITest.IApp. Ten interfejs definiuje metody, które mają kluczowe znaczenie dla testu w celu współpracy z aplikacją i interakcji z interfejsem użytkownika. Istnieją dwie konkretne implementacje tego interfejsu:

  • Xamarin.UITest.iOS.iOSApp Ta klasa automatyzuje testy w systemie iOS.
  • Xamarin.UITest.Android.AndroidApp Ta klasa służy do automatyzowania testów w systemie Android.

iOSApp obiekty i AndroidApp nie są tworzone bezpośrednio. Zamiast tego są tworzone przy użyciu klasy pomocnika ConfigureApp . Ta klasa jest konstruktorem, który gwarantuje, że wystąpienie iOSApp obiektu lub AndroidApp jest prawidłowo tworzone.

Zalecamy użycie nowego IApp wystąpienia dla każdego testu. Nowe wystąpienie zapobiega wyciekowi jednego testu do innego. Istnieją dwa miejsca, w których test NUnit może zainicjować wystąpienie klasy IApp:

  • W metodzie SetUp Zazwyczaj urządzenie testowe jest logicznym grupowaniem powiązanych testów, każdy z nich działa niezależnie od drugiego. W tym scenariuszu IApp element powinien zostać zainicjowany w metodzie SetUp , zapewniając dostępność nowych IApp dla każdego testu.
  • W metodzie TestFixtureSetup W niektórych sytuacjach pojedynczy test może wymagać własnego urządzenia testowego. W takim przypadku może to mieć większe znaczenie, aby zainicjować IApp obiekt raz w metodzie TestFixtureSetup .

Po IApp skonfigurowaniu test może zacząć korzystać z testowanej aplikacji. W tym celu należy uzyskać odwołania do widoków widocznych na ekranie. Wiele metod w narzędziu Xamarin.UITest bierze Func<AppQuery, AppQuery> parametr w celu zlokalizowania widoków. Na przykład poniższy fragment kodu pokazuje, jak nacisnąć przycisk:

app.Tap(c=>c.Button("ValidateButton"));

Istnieją dwie implementacje interfejsu IApp w strukturze Xamarin.UITest, jeden dla systemu iOS i jeden dla systemu Android.

Inicjowanie aplikacji IApp dla aplikacji systemu iOS

Gdy narzędzie Xamarin.UITest uruchamia test w systemie iOS, uruchamia wystąpienie symulatora systemu iOS, wdraża aplikację, uruchamia ją i rozpoczyna uruchamianie testów. Aplikacja systemu iOS musi być już skompilowana. Program Xamarin.UITest nie skompiluje aplikacji i utworzy pakiet aplikacji.

Za AppBundle pomocą metody można określić, gdzie w systemie plików można znaleźć pakiet aplikacji. Istnieją dwa sposoby, aby to zrobić, ze ścieżką bezwzględną lub ścieżką względną. Ten fragment kodu przedstawia użycie ścieżki bezwzględnej do pakietu aplikacji:

IApp app = ConfigureApp
    .iOS
    .AppBundle("/path/to/iosapp.app")
    .StartApp();

Ścieżki częściowe muszą być względne względem zestawu Xamarin.UITest. Ten fragment kodu jest przykładem:

IApp app = ConfigureApp
    .iOS
    .AppBundle("../../../iOSAppProject/bin/iPhoneSimulator/Debug/iosapp.app")
    .StartApp();

Przykład ścieżki względnej informuje AppBundle o przejściu w górę trzech katalogów z zestawu Xamarin.UITest, a następnie przejdź w dół drzewa projektu aplikacji systemu iOS, aby znaleźć pakiet aplikacji.

ConfigureApp program ma inne metody ułatwiające skonfigurowanie IAppprogramu . Aby uzyskać więcej informacji, zobacz klasę iOSAppConfigurator . Niektóre z bardziej interesujących metod opisano w poniższej tabeli:

Metoda Opis
AppBundle Ta metoda określa ścieżkę do pakietu aplikacji do użycia podczas testowania.
Debug Ta metoda włączy komunikaty rejestrowania debugowania w module uruchamiającym testy. Ta metoda jest przydatna do rozwiązywania problemów z uruchamianiem aplikacji w symulatorze.
DeviceIdentifier Konfiguruje urządzenie do użycia z identyfikatorem urządzenia. Ta metoda zostanie opisana bardziej szczegółowo poniżej.
EnableLocalScreenshots Włącz zrzuty ekranu podczas uruchamiania testów lokalnie. Zrzuty ekranu są zawsze włączone, gdy testy są uruchomione w chmurze.

Aby uzyskać więcej informacji na temat uruchamiania testów systemu iOS w określonym symulatorze systemu iOS, zobacz Określanie identyfikatora urządzenia dla symulatora systemu iOS.

Inicjowanie aplikacji IApp dla aplikacji systemu Android

Narzędzie Xamarin.UITest wdroży istniejący pakiet APK na dołączonym urządzeniu lub wystąpieniu emulatora systemu Android, który jest już uruchomiony. Aplikacja zostanie uruchomiona, a następnie zostanie uruchomiony test. Program Xamarin.UITest nie może skompilować pliku APK ani nie może uruchomić wystąpienia emulatora systemu Android.

Metoda ApkFileIApp jest używana do określenia, gdzie w systemie plików można znaleźć plik APK. Istnieją dwa sposoby, aby to zrobić, ze ścieżką bezwzględną lub ścieżką względną. Ten fragment kodu przedstawia użycie ścieżki bezwzględnej do pliku APK:

IApp app = ConfigureApp
    .Android
    .ApkFile("/path/to/android.apk")
    .StartApp();

Ścieżki częściowe muszą być względne względem zestawu Xamarin.UITest. Ten fragment kodu jest przykładem:

IApp app = ConfigureApp
    .Android
    .ApkFile("../../../AndroidProject/bin/Debug/android.apk")
    .StartApp();

Przykład ścieżki względnej informuje ApkFile o przejściu w górę trzech katalogów z zestawu Xamarin.UITest, a następnie przejdź w dół drzewa projektu aplikacji systemu Android, aby znaleźć plik apk.

Jeśli istnieje więcej niż jedno urządzenie lub emulator, program Xamarin.UITest zatrzyma wykonywanie testu i wyświetli komunikat o błędzie, ponieważ nie może rozpoznać zamierzonego celu testu. W takim przypadku należy podać identyfikator seryjny urządzenia lub emulatora, aby uruchomić test. Rozważmy na przykład następujące dane wyjściowe z adb devices polecenia zawierającego listę wszystkich urządzeń (lub emulatorów) dołączonych do komputera (wraz z ich identyfikatorem seryjnym):

$ adb devices
List of devices attached
192.168.56.101:5555 device
03f80ddae07844d3    device

Urządzenie można określić przy użyciu DeviceSerial metody :

IApp app = ConfigureApp.Android.ApkFile("/path/to/android.apk")
                               .DeviceSerial("03f80ddae07844d3")
                               .StartApp();

Interakcja z interfejsem użytkownika

Aby korzystać z widoków, wiele IApp metod deleguje Func<AppQuery, AppQuery> do lokalizowania widoku. Ten delegat używa AppQuery tego podstawowego sposobu lokalizowania widoków na platformie Xamarin.UITest.

AppQuery jest płynnym interfejsem do tworzenia zapytań w celu zlokalizowania widoków. Spośród metod, które AppQuery zapewniają, Marked metoda jest jedną z najprostszych i najbardziej elastycznych. Ta metoda używa heurystyki do próby zlokalizowania widoków i zostanie omówiona bardziej szczegółowo w poniższej sekcji. Na razie ważne jest, aby zrozumieć, że IApp istnieje wiele metod interakcji z aplikacją. Te metody używają metody , Func<AppQuery, AppQuery> aby uzyskać odwołanie do widoku do interakcji. Poniżej wymieniono niektóre z bardziej interesujących metod oferowanych przez AppQuery program :

Metoda Opis
Button Znajdź co najmniej jeden przycisk na ekranie.
Class Spróbuje zlokalizować widoki z określonej klasy.
Id Spróbuje zlokalizować widok z określonym identyfikatorem.
Index . Zwróci jeden widok z kolekcji pasujących widoków. Zwykle używane w połączeniu z innymi metodami. Pobiera indeks oparty na zerach.
Marked Zwróci widok zgodnie z heurystykami omówionymi poniżej.
Text Będzie pasuje do widoków zawierających podany tekst.
TextField Będzie zgodna z systemem Android EditText lub iOS UITextField.

Na przykład poniższa metoda pokazuje, jak symulować naciśnięcie przycisku o nazwie "SaveUserdataButton":

app.Tap(c=>c.Marked("SaveUserDataButton"));

Ponieważ AppQuery jest to płynny interfejs, można połączyć ze sobą wiele wywołań metod. Rozważmy ten bardziej skomplikowany przykład naciśnięcia widoku:

app.Tap(c=>c.Marked("Pending")
            .Parent()
            .Class("AppointmentListCell").Index(0));

AppQuery W tym miejscu najpierw znajdziesz widok oznaczony Pendingjako , a następnie wybierz pierwszy element nadrzędny tego widoku, który jest typemAppointmentListCell.

Może to być trudne podczas próby utworzenia tych zapytań, przeglądając aplikację mobilną. Narzędzie Xamarin.UITest udostępnia rozszerzenie REPL, które może służyć do eksplorowania hierarchii wyświetlania ekranu, eksperymentowania z tworzeniem zapytań i używania ich do interakcji z aplikacją.

Korzystanie z biblioteki REPL

Jedynym sposobem uruchomienia repl jest wywołanie IApp.Repl metody w istniejącym teście. Wymaga to utworzenia NUnit TestFixture, skonfigurowania wystąpienia IApp , którego można użyć w metodzie Test . Poniższy fragment kodu przedstawia przykład tego, jak to zrobić:

[TestFixture]
public class ValidateCreditCard
{
    IApp app;

    [SetUp]
    public void Setup()
    {
        app = ConfigureApp.Android.ApkFile("/path/to/application.apk").StartApp();
    }
    [Test]
    public void CreditCardNumber_TooLong_DisplayErrorMessage()
    {
        app.Repl();
    }
}

Aby uruchomić test, klikając prawym przyciskiem myszy w rynnie programu Visual Studio i wybierając polecenie Uruchom:

Zrzut ekranu przedstawiający menu podręczne z opcjami uruchamiania testu

Test zostanie uruchomiony, a po Repl wywołaniu metody program Xamarin.UITest uruchomi rozszerzenie REPL w sesji terminalu, jak pokazano na poniższym zrzucie ekranu:

Zrzut ekranu przedstawiający terminal systemu macOS z uruchomioną wersją REPL platformy Xamarin.UITest

Rozszerzenie REPL zainicjowało wystąpienie IApp o nazwie app, które wchodzi w interakcję z aplikacją. Jedną z pierwszych czynności, które należy zrobić, jest zapoznanie się z interfejsem użytkownika. Funkcja REPL ma tree polecenie, aby to zrobić. Spowoduje to wyświetlenie hierarchii widoków na wyświetlonym ekranie. Rozważmy na przykład następujący zrzut ekranu aplikacji:

Zrzut ekranu przedstawiający przykładową aplikację działającą na telefonie iPhone

Możemy użyć polecenia , tree aby wyświetlić następującą hierarchię tego ekranu:

App has been initialized to the 'app' variable.
Exit REPL with ctrl-c or see help for more commands.

>>> tree
[UIWindow > UILayoutContainerView]
  [UINavigationTransitionView > ... > UIView]
    [UITextView] id: "CreditCardTextField"
      [_UITextContainerView]
    [UIButton] id: "ValidateButton"
      [UIButtonLabel] text: "Validate Credit Card"
    [UILabel] id: "ErrorrMessagesTestField"
  [UINavigationBar] id: "Credit Card Validation"
    [_UINavigationBarBackground]
      [_UIBackdropView > _UIBackdropEffectView]
      [UIImageView]
    [UINavigationItemView]
      [UILabel] text: "Credit Card Validation"
>>>

Widzimy, że w tym widoku znajduje UIButton się element idValidateButton. Możemy użyć informacji wyświetlanych przez tree polecenie , aby ułatwić tworzenie niezbędnych zapytań w celu zlokalizowania widoków i interakcji z nimi. Na przykład poniższy kod symuluje naciśnięcie przycisku:

app.Tap(c=>c.Marked("ValidateButton"))

W miarę wprowadzania poleceń są one zapamiętane przez REPL w buforze. Funkcja REPL udostępnia copy polecenie, które spowoduje skopiowanie zawartości tego buforu do schowka. Dzięki temu możemy utworzyć prototyp testu. Możemy skopiować pracę wykonaną w programie REPL do schowka za pomocą polecenia copy, a następnie wkleić te polecenia w obiekcie [Test].

Używanie oznaczonego do lokalizowania widoków

Metoda AppQuery.Marked to wygodny i zaawansowany sposób wykonywania zapytań o widoki na ekranie. Działa to przez sprawdzenie hierarchii widoków dla widoku na ekranie, próbując dopasować właściwości widoku do podanego ciągu. Marked działa inaczej w zależności od systemu operacyjnego.

Znajdowanie widoków systemu iOS z oznaczonym

Widoki systemu iOS będą znajdować się przy użyciu jednego z następujących atrybutów:

  • widok AccessibilityIdentifier
  • widok AccessibilityLabel

Rozważmy na przykład następujący fragment kodu w języku C#, który tworzy element UILabel i ustawia element AccessibilityLabel:

UILabel errorMessagesTextField = new UILabel(new RectangleF(10, 210, 300, 40));
errorMessagesTextField.AccessibilityLabel = "ErrorMessagesTextField";
errorMessagesTextField.Text = String.Empty;

Ten widok można znaleźć za pomocą następującego zapytania:

AppResult[] results = app.Marked("ErrorMessagesTextField");

Znajdowanie widoków systemu Android z oznaczonym

Widoki systemu Android będą znajdować się na podstawie jednej z następujących właściwości:

  • widok Id
  • widok ContentDescription
  • widok Text

Rozważmy na przykład układ systemu Android, który ma zdefiniowany następujący przycisk:

<Button
    android:text="Action 1"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:id="@+id/action1_button"
    android:layout_weight="1"
    android:layout_marginLeft="5dp" />

Widać, że android:id ten przycisk jest action1_button i że android:text jest to akcja 1. Jeden z następujących dwóch zapytań będzie znajdować przycisk na ekranie:

  • app.Query(c=>c.Marked("action1_button"));
  • app.Query(c=>c.Marked("Action 1"));

Kontrolowanie aplikacji za pomocą platformy Xamarin.UITest.IApp

Po IApp skonfigurowaniu i zainicjowaniu test może rozpocząć interakcję z aplikacją. Jednym z przykładów metody przy użyciu Func<AppQuery, AppQuery> jest IApp.Query() metoda . Ta metoda wykona zapytanie i zwróci wyniki. Najprostszym przykładem jest pokazany w poniższym fragmencie kodu, który zwraca listę wszystkich widoków widocznych na ekranie:

AppResult[] results = app.Query(c=>c.All())

W poniższej tabeli przedstawiono kilka innych przykładów użycia funkcji AppQuery lokalizowania widoków na ekranie:

Składnia Wyniki
app.Query(c=>c.Class("UILabel")) Metoda .Class() będzie wykonywać zapytania dotyczące widoków, które są podklasą systemu iOS UILabel.
app.Query(c=>c.Id("txtUserName")) Metoda .Id() będzie wykonywać zapytania dotyczące widoków z wartością IdtxtUserName.
app.Query(c=>c.Class("UILabel").Text("Hello, World")) Lokalizuje wszystkie UILabel klasy z tekstem "Hello, World".
results = app.Query(c=>c.Marked("ValidateButton")) Zwraca wszystkie widoki oznaczone określonym tekstem. Metoda Marked jest przydatną metodą, która może uprościć zapytania. Zostanie on omówiony w poniższej sekcji.

W następnej tabeli wymieniono niektóre (ale nie wszystkie) metody, które IApp mogą służyć do interakcji z widokami na ekranie lub manipulowania nimi:

Przykład Opis
PressEnter Naciśnij klawisz Enter w aplikacji.
Tap Symuluje gest naciśnięcia/dotyku na dopasowanym elemecie.
EnterText Wprowadza tekst w widoku. W aplikacji systemu iOS program Xamarin.UITest wprowadzi tekst przy użyciu klawiatury miękkiej. Z kolei platforma Xamarin.UITest nie będzie używać klawiatury systemu Android. Spowoduje to bezpośrednie wprowadzenie tekstu do widoku.
WaitForElement Wstrzymuje wykonywanie testu, dopóki widoki nie pojawią się na ekranie.
Screenshot(String) Tworzy zrzut ekranu aplikacji w bieżącym stanie i zapisuje ją na dysku. Zwraca FileInfo obiekt z informacjami o wykonanym zrzucie ekranu.
Flash Ta metoda spowoduje, że wybrany widok będzie "flash" lub "migotanie" na ekranie.

Aby uzyskać więcej informacji na temat interfejsu, zobacz dokumentację interfejsuIApp API dla IApp, AndroidAppi iOSApp.

Jako przykład użycia tych metod rozważ poniższy test dla zrzutu ekranu, który został wyświetlony powyżej. Ten test wprowadzi 17-cyfrowy numer karty kredytowej w polu tekstowym, a następnie naciśnij przycisk na ekranie. Następnie sprawdzi ekran pod kątem komunikatu o błędzie informującego użytkownika, że numer jest zbyt długi, aby był prawidłowym numerem karty kredytowej:

[Test]
public void CreditCardNumber_TooLong_DisplayErrorMessage()
{
    /* Arrange - set up our queries for the views */
    // Nothing to do here, app has been instantiated in the [SetUp] method.

    /* Act */
    app.EnterText(c => c.Marked("CreditCardTextField"), new string('9', 17));
    // Screenshot can be used to break this test up into "steps".
    // The screenshot can be inspected after the test run to verify
    // the visual correctness of the screen.
    app.Screenshot("Entering a 17 digit credit card number.");

    app.Tap(c => c.Marked("ValidateButton"));
    app.Screenshot("The validation results.");

    /* Assert */
    AppResult[] result = app.Query(c => c.Class("UILabel").Text("Credit card number is too long."));
    Assert.IsTrue(result.Any(), "The error message isn't being displayed.");
}

Ten test używa Screenshot również metody do wykonywania zdjęć w kluczowych punktach podczas wykonywania testu. Po uruchomieniu tego testu usługa App Center wykona zrzuty ekranu i wyświetli je w wynikach testu. Metoda umożliwia podzielenie testu na kroki i podanie opisów zrzutów ekranu.