Pierwsze kroki z testami pętli gry na iOS

Dzięki testom pętli gry możesz pisać testy natywne dla silnika gry, a następnie uruchamiać je w Test Lab na wybranych urządzeniach. W ten sposób nie musisz się martwić pisaniem kodu dla różnych interfejsów ani frameworków testowych. Test pętli gry symuluje działania prawdziwego gracza. Gdy uruchomisz go w Test Lab, uzyskasz szybki i skalowalny sposób na sprawdzenie, czy Twoja gra działa dobrze dla użytkowników.

Z tej strony dowiesz się, jak przeprowadzić test pętli gry, a następnie wyświetlić wyniki testu i zarządzać nimi na stronie Test Lab w konsoli Firebase. Możesz też dostosować testy za pomocą funkcji opcjonalnych, takich jak zapisywanie niestandardowych wyników testów czy wcześniejsze zakończenie testu.

Co to jest test pętli gry?

Pętla to pełne lub częściowe wykonanie testu w grze mobilnej. Test pętli gry możesz uruchomić lokalnie w symulatorze lub na zestawie urządzeń w Test Lab. Testy pętli gry można wykorzystać do:

  • przejścia przez grę tak, jak zrobiłby to użytkownik końcowy; możesz napisać skrypt danych wejściowych użytkownika, pozwolić użytkownikowi na bezczynność lub zastąpić użytkownika sztuczną inteligencją (np. jeśli zaimplementujesz sztuczną inteligencję w grze wyścigowej, możesz powierzyć sterowanie kierowcy AI);

  • uruchomienia gry w najwyższej jakości, aby sprawdzić, które urządzenia mogą ją obsługiwać;

  • przeprowadzenia testu technicznego, np. skompilowania wielu shaderów, ich wykonania i sprawdzenia, czy dane wyjściowe są zgodne z oczekiwaniami.

Krok 1. Zarejestruj niestandardowy schemat URI adresu URL Test Lab

Najpierw musisz zarejestrować Firebase Test Lab's niestandardowy schemat URI adresu URL w swojej aplikacji:

  1. W Xcode wybierz cel projektu.

  2. Kliknij kartę Informacje, a następnie dodaj nowy typ adresu URL.

  3. W polu Schematy adresów URL wpisz firebase-game-loop. Niestandardowy schemat URI adresu URL możesz też zarejestrować, dodając go do pliku konfiguracyjnego projektu Info.plist w dowolnym miejscu w tagu <dict>:

    <key>CFBundleURLTypes</key>
     <array>
         <dict>
             <key>CFBundleURLName</key>
             <string></string>
             <key>CFBundleTypeRole</key>
             <string>Editor</string>
             <key>CFBundleURLSchemes</key>
             <array>
                 <string>firebase-game-loop</string>
             </array>
         </dict>
     </array>
    

Twoja aplikacja jest teraz skonfigurowana do przeprowadzania testów za pomocą Test Lab.

Krok 2 (opcjonalnie). Skonfiguruj aplikację do uruchamiania wielu pętli

Jeśli w aplikacji zarejestrowano kilka schematów niestandardowych adresów URL i planujesz uruchomić w teście kilka pętli (czyli scenariuszy), musisz określić, które pętle chcesz uruchomić w aplikacji w momencie jej uruchomienia.

W delegacie aplikacji zastąp metodę application(_:open:options:):

Swift

func application(_app: UIApplication,
                 open url: URL
                 options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    let components = URLComponents(url: url, resolvingAgainstBaseURL: true)!
    if components.scheme == "firebase-game-loop" {
        // ...Enter Game Loop Test logic to override application(_:open:options:).
    }
    return true
}

Objective-C

- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary &lt;UIApplicationOpenURLOptionsKey, id&gt; *)options {
  if ([url.scheme isEqualToString:(@"firebase-game-loop")]) {
      // ...Enter Game Loop Test logic to override application(_:open:options:).
  }
}

Gdy w teście uruchamiasz kilka pętli, bieżąca pętla jest przekazywana jako parametr do adresu URL używanego do uruchamiania aplikacji. Możesz też uzyskać numer bieżącej pętli, analizując obiekt URLComponents używany do pobierania niestandardowego schematu URI adresu URL:

Swift

if components.scheme == "firebase-game-loop" {
    // Iterate over all parameters and find the one with the key "scenario".
    let scenarioNum = Int(components.queryItems!.first(where: { $0.name == "scenario" })!.value!)!
    // ...Write logic specific to the current loop (scenarioNum).
}

Objective-C

if ([url.scheme isEqualToString:(@"firebase-game-loop")]) {
    // Launch the app as part of a game loop.
    NSURLComponents *components = [NSURLComponents componentsWithURL:url
                                             resolvingAgainstBaseURL:YES];
    for (NSURLQueryItem *item in [components queryItems]) {
        if ([item.name isEqualToString:@"scenario"]) {
            NSInteger scenarioNum = [item.value integerValue];
            // ...Write logic specific to the current loop (scenarioNum).
        }
    }
}

Krok 3. Utwórz i uruchom test

Po zarejestrowaniu niestandardowego schematu URI adresu URL Test Lab możesz uruchomić test w konsoli Firebase lub za pomocą interfejsu wiersza poleceń gcloud beta. Jeśli jeszcze tego nie zrobisz, wygeneruj plik IPA aplikacji (będziesz musiał go później znaleźć).

Uruchamianie testu w konsoli Firebase

  1. W konsoli Firebase otwórz DevOps i zaangażowanie > Laboratorium testów.

  2. Kliknij Uruchom pierwszy test > Uruchom pętlę gry na iOS.

  3. W sekcji Prześlij aplikację kliknij Przeglądaj, a następnie wybierz plik IPA aplikacji (jeśli jeszcze tego nie zrobisz, wygeneruj plik IPA aplikacji).

  4. (Opcjonalnie) Jeśli chcesz uruchomić kilka pętli (czyli scenariuszy) naraz lub wybrać konkretne pętle do uruchomienia, wpisz numery pętli w polu Scenariusze.

    Jeśli na przykład wpiszesz 1-3, 5, Test Lab uruchomi pętle 1, 2, 3 i 5. Domyślnie (jeśli nie wpiszesz nic w polu Scenariusze ) Test Lab uruchomi tylko pętlę 1.

  5. W sekcji Urządzenia wybierz co najmniej 1 urządzenie fizyczne, na którym chcesz przetestować aplikację, a następnie kliknij Rozpocznij testy.

Uruchamianie testu za pomocą interfejsu wiersza poleceń gcloud beta

  1. Jeśli jeszcze tego nie zrobisz, skonfiguruj lokalne środowisko gcloud SDK, a następnie zainstaluj komponent gcloud beta.

  2. Uruchom polecenie gcloud beta firebase test ios run i użyj tych flag, aby skonfigurować uruchomienie:

Flagi do testów pętli gry
--type

Wymagane: określa typ testu na iOS, który chcesz uruchomić. Możesz wpisać test types xctest (default) or game-loop.

--app

Wymagane: ścieżka bezwzględna (Google Cloud Storage lub system plików) do pliku IPA aplikacji. Ta flaga jest prawidłowa tylko wtedy, gdy uruchamiasz testy pętli gry.

--scenario-numbers

Pętle (czyli scenariusze), które chcesz uruchomić w aplikacji. Możesz wpisać 1 pętlę, listę pętli lub zakres pętli. Domyślna pętla to 1.

Na przykład --scenario-numbers=1-3,5 uruchamia pętle 1, 2, 3 i 5.

--device-model

Urządzenie fizyczne, na którym chcesz uruchomić test (sprawdź, których dostępnych urządzeń możesz użyć).

--timeout

Maksymalny czas działania testu. Możesz wpisać liczbę całkowitą, która będzie reprezentować czas trwania w sekundach, lub liczbę całkowitą i wyliczenie, które będą reprezentować czas trwania w dłuższej jednostce czasu.

Na przykład:

  • --timeout=200 wymusza zakończenie testu po 200 sekundach.
  • --timeout=1h wymusza zakończenie testu po godzinie.

Na przykład to polecenie uruchamia test pętli gry, który wykonuje pętle 1, 4, 6, 7 i 8 na iPhonie 8 Plus:

gcloud beta firebase test ios run
 --type game-loop --app path/to/my/App.ipa --scenario-numbers 1,4,6-8
 --device-model=iphone8plus

Więcej informacji o gcloud CLI znajdziesz w dokumentacji.

Uruchamianie testu lokalnie

Aby uruchomić test lokalnie, załaduj swoją grę mobilną w symulatorze i uruchom:

xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://
  • UDID symulatora znajdziesz, uruchamiając polecenie instruments -s devices.

  • Jeśli działa tylko 1 symulator, zamiast SIMULATOR_UDID wpisz specjalny ciąg znaków "booted".

Jeśli test zawiera kilka pętli, możesz określić, którą pętlę chcesz uruchomić, przekazując numer pętli do flagi scenario. Pamiętaj, że podczas uruchamiania testu lokalnie możesz uruchomić tylko 1 pętlę naraz. Jeśli na przykład chcesz uruchomić pętle 1, 2 i 5, musisz uruchomić osobne polecenie dla każdej pętli:

xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=1
xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=2
xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=5

Wcześniejsze zakończenie testu

Domyślnie test pętli gry jest uruchamiany do momentu osiągnięcia limitu czasu wynoszącego 5 minut, nawet jeśli wszystkie pętle zostały już wykonane. Po osiągnięciu limitu czasu test kończy się i anuluje wszystkie oczekujące pętle. Możesz przyspieszyć test lub zakończyć go wcześniej, wywołując w AppDelegate aplikacji niestandardowy schemat URI adresu URL Test Lab firebase-game-loop-complete. Przykład:

Swift

/// End the loop by calling our custom url scheme.
func finishLoop() {
    let url = URL(string: "firebase-game-loop-complete://")!
    UIApplication.shared.open(url)
}

Objective-C

- (void)finishLoop {
  UIApplication *app = [UIApplication sharedApplication];
  [app openURL:[NSURL URLWithString:@"firebase-game-loop-complete://"]
      options:@{}
completionHandler:^(BOOL success) {}];
}

Test pętli gry kończy bieżącą pętlę i wykonuje następną. Gdy nie ma już pętli do uruchomienia, test się kończy.

Zapisywanie niestandardowych wyników testów

Możesz skonfigurować test pętli gry tak, aby zapisywał niestandardowe wyniki testów w systemie plików urządzenia. Gdy test zacznie się uruchamiać, Test Lab zapisze pliki wyników w katalogu GameLoopsResults na urządzeniu testowym (musisz go utworzyć samodzielnie). Po zakończeniu testu Test Lab przeniesie wszystkie pliki z katalogu GameLoopResults do zasobnika projektu. Podczas konfigurowania testu pamiętaj o tych kwestiach:

  • Wszystkie pliki wyników są przesyłane bez względu na typ pliku, rozmiar i ilość.

  • Test Lab nie przetwarza wyników testu, dopóki nie zostaną uruchomione wszystkie pętle w teście. Jeśli więc test zawiera kilka pętli, które zapisują dane wyjściowe, dopilnuj, aby dołączać je do unikalnego pliku wyników lub utworzyć plik wyników dla każdej pętli. W ten sposób unikniesz zastąpienia wyników z poprzedniej pętli.

Aby skonfigurować test tak, aby zapisywał niestandardowe wyniki testów:

  1. W katalogu Documents aplikacji utwórz katalog o nazwie GameLoopResults.

  2. W dowolnym miejscu w kodzie aplikacji (np. w delegacie aplikacji) dodaj te elementy:

    Swift

    /// Write to a results file.
    func writeResults() {
      let text = "Greetings from game loops!"
      let fileName = "results.txt"
      let fileManager = FileManager.default
      do {
    
      let docs = try fileManager.url(for: .documentDirectory,
                                     in: .userDomainMask,
                                     appropriateFor: nil,
                                     create: true)
      let resultsDir = docs.appendingPathComponent("GameLoopResults")
      try fileManager.createDirectory(
          at: resultsDir,
          withIntermediateDirectories: true,
          attributes: nil)
      let fileURL = resultsDir.appendingPathComponent(fileName)
      try text.write(to: fileURL, atomically: false, encoding: .utf8)
      } catch {
        // ...Handle error writing to file.
      }
    }
    

    Objective-C

    /// Write to a results file.
    - (void)writeResults:(NSString *)message {
        // Locate and create the results directory (if it doesn't exist already).
        NSFileManager *manager = [NSFileManager defaultManager];
        NSURL* url = [[manager URLsForDirectory:NSDocumentDirectory
                                      inDomains:NSUserDomainMask] lastObject];
        NSURL* resultsDir = [url URLByAppendingPathComponent:@"GameLoopResults"
                                                 isDirectory:YES];
        [manager createDirectoryAtURL:resultsDir
          withIntermediateDirectories:NO
                           attributes:nil
                                error:nil];
    
        // Write the result message to a text file.
        NSURL* resultFile = [resultsDir URLByAppendingPathComponent:@"result.txt"];
        if ([manager fileExistsAtPath:[resultFile path]]) {
            // Append to the existing file
            NSFileHandle *handle = [NSFileHandle fileHandleForWritingToURL:resultFile
                                                                     error:nil];
            [handle seekToEndOfFile];
            [handle writeData:[message dataUsingEncoding:NSUTF8StringEncoding]];
            [handle closeFile];
        } else {
            // Create and write to the file.
            [message writeToURL:resultFile
                     atomically:NO
                       encoding:NSUTF8StringEncoding error:nil];
        }
    }