با تست های Game Loop برای iOS شروع کنید

با تست‌های Game Loop، می‌توانید تست‌های بومی موتور بازی خود را بنویسید و سپس آنها را در Test Lab روی دستگاه‌هایی که انتخاب می‌کنید اجرا کنید. به این ترتیب، لازم نیست نگران نوشتن برای UI های مختلف یا فریمورک های آزمایشی باشید. تست Game Loop اقدامات یک بازیکن واقعی را شبیه‌سازی می‌کند و وقتی آن را در Test Lab اجرا می‌کنید، راهی سریع و مقیاس‌پذیر برای تأیید اینکه بازی شما به خوبی برای کاربران شما کار می‌کند ارائه می‌کند.

این صفحه به شما نشان می دهد که چگونه یک تست Game Loop را اجرا کنید، سپس نتایج آزمایش خود را در صفحه Test Lab کنسول Firebase مشاهده و مدیریت کنید. همچنین می‌توانید تست‌های خود را با ویژگی‌های اختیاری، مانند نوشتن نتایج آزمون سفارشی یا پایان دادن زودهنگام تست ، سفارشی کنید.

تست حلقه بازی چیست؟

یک حلقه آزمایش کامل یا جزئی از آزمایش شما در برنامه بازی شما است. شما می توانید یک تست Game Loop را به صورت محلی روی یک شبیه ساز یا روی مجموعه ای از دستگاه ها در Test Lab اجرا کنید. از تست های حلقه بازی می توان برای موارد زیر استفاده کرد:

  • همانطور که کاربر نهایی آن را بازی می کند، بازی خود را اجرا کنید. می توانید ورودی کاربر را اسکریپت کنید، اجازه دهید کاربر بیکار باشد، یا کاربر را با یک هوش مصنوعی جایگزین کنید (به عنوان مثال، اگر هوش مصنوعی را در یک بازی اتومبیل رانی پیاده سازی کرده اید، می توانید یک راننده هوش مصنوعی را مسئول ورودی کاربر قرار دهید) .

  • بازی خود را با بالاترین کیفیت اجرا کنید تا بدانید کدام دستگاه ها می توانند از آن پشتیبانی کنند.

  • یک تست فنی مانند کامپایل کردن چندین سایه زن، اجرای آنها و بررسی اینکه خروجی مطابق انتظار است را اجرا کنید.

مرحله 1: طرح URL سفارشی آزمایشگاه تست را ثبت کنید

ابتدا، باید طرح URL سفارشی Firebase Test Lab را در برنامه خود ثبت کنید:

  1. در Xcode، یک هدف پروژه را انتخاب کنید.

  2. روی برگه Info کلیک کنید، سپس یک نوع URL جدید اضافه کنید.

  3. در قسمت URL Schemes ، firebase-game-loop را وارد کنید. همچنین می‌توانید طرح URL سفارشی را با افزودن آن به فایل پیکربندی Info.plist پروژه خود در هر نقطه از تگ <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>
    

اکنون برنامه شما برای اجرای آزمایشی با استفاده از Test Lab پیکربندی شده است.

مرحله 2 (اختیاری): برنامه خود را برای اجرای چندین حلقه پیکربندی کنید

اگر برنامه شما دارای چندین طرح URL سفارشی ثبت شده است و قصد دارید چندین حلقه (معروف به سناریوها) را در آزمایش خود اجرا کنید، باید مشخص کنید که می خواهید کدام حلقه ها را در زمان راه اندازی در برنامه خود اجرا کنید.

در نماینده برنامه خود، روش application(_:open:options:) لغو کنید:

سریع

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
}

هدف-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:).
  }
}

هنگامی که چندین حلقه را در آزمایش خود اجرا می کنید، حلقه فعلی به عنوان یک پارامتر به URL مورد استفاده برای راه اندازی برنامه ارسال می شود. همچنین می توانید با تجزیه شیء URLComponents مورد استفاده برای واکشی طرح URL سفارشی، عدد حلقه فعلی را بدست آورید:

سریع

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).
}

هدف-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).
        }
    }
}

مرحله 3: یک تست ایجاد و اجرا کنید

پس از ثبت طرح URL سفارشی Test Lab، می توانید آزمایش خود را در کنسول Firebase یا با gcloud beta CLI اجرا کنید. اگر قبلاً این کار را نکرده‌اید، یک فایل IPA برای برنامه خود ایجاد کنید (بعداً باید آن را پیدا کنید).

آزمایشی را در کنسول Firebase انجام دهید

  1. اگر قبلاً این کار را نکرده‌اید، کنسول Firebase را باز کرده و یک پروژه ایجاد کنید.

  2. در صفحه Test Lab کنسول Firebase، روی Run Your First Test > Run an iOS Game Loop کلیک کنید.

  3. در بخش آپلود برنامه ، روی مرور کلیک کنید، سپس فایل IPA برنامه خود را انتخاب کنید (اگر قبلاً این کار را نکرده اید، یک فایل IPA برای برنامه خود ایجاد کنید).

  4. اختیاری : اگر می‌خواهید چندین حلقه (معروف به سناریوها) را در یک زمان اجرا کنید یا حلقه‌های خاصی را برای اجرا انتخاب کنید، اعداد حلقه‌ها را در قسمت سناریوها وارد کنید.

    به عنوان مثال، وقتی "1-3، 5" را وارد می کنید، آزمایشگاه تست حلقه های 1، 2، 3 و 5 را اجرا می کند. به طور پیش فرض (اگر چیزی در قسمت سناریوها وارد نکنید)، تست آزمایشگاه فقط حلقه 1 را اجرا می کند.

  5. در بخش Devices ، یک یا چند دستگاه فیزیکی را که می‌خواهید برنامه خود را روی آن آزمایش کنید، انتخاب کنید، سپس روی Start Tests کلیک کنید.

آزمایشی را با gcloud beta CLI انجام دهید

  1. اگر قبلاً این کار را نکرده‌اید، محیط gcloud SDK محلی خود را پیکربندی کنید، سپس مطمئن شوید که مؤلفه gcloud beta را نصب کرده‌اید.

  2. دستور اجرای gcloud beta firebase test ios run کنید و از پرچم‌های زیر برای پیکربندی اجرا استفاده کنید:

پرچم برای تست های حلقه بازی
--type

Required : نوع تست iOS را که می خواهید اجرا کنید را مشخص می کند. می توانید انواع تست xctest (پیش فرض) یا game-loop را وارد کنید.

--app

مورد نیاز : مسیر مطلق (Google Cloud Storage یا سیستم فایل) به فایل IPA برنامه شما. این پرچم فقط هنگام اجرای تست های Game Loop معتبر است.

--scenario-numbers

حلقه هایی (معروف به سناریوها) که می خواهید در برنامه خود اجرا کنید. می‌توانید یک حلقه، یک لیست یا حلقه‌ها یا طیفی از حلقه‌ها را وارد کنید. حلقه پیش فرض 1 است.

برای مثال، --scenario-numbers=1-3,5 حلقه های 1، 2، 3 و 5 را اجرا می کند.

--device-model

دستگاه فیزیکی که می خواهید آزمایش خود را روی آن اجرا کنید (ببینید از کدام دستگاه های موجود می توانید استفاده کنید).

--timeout

حداکثر مدت زمانی که می خواهید آزمون شما اجرا شود. می توانید یک عدد صحیح برای نمایش مدت زمان در ثانیه یا یک عدد صحیح و یک عدد برای نمایش مدت زمان به عنوان یک واحد زمان طولانی تر وارد کنید.

مثلا:

  • --timeout=200 آزمایش شما را مجبور می کند تا زمانی که حداکثر 200 ثانیه طول بکشد خاتمه یابد.
  • --timeout=1h آزمایش شما را مجبور می کند تا زمانی که حداکثر یک ساعت اجرا شود، خاتمه یابد.

به عنوان مثال، دستور زیر یک تست Game Loop را اجرا می کند که حلقه های 1، 4، 6، 7 و 8 را در آیفون 8 پلاس اجرا می کند:

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

برای اطلاعات بیشتر در مورد gcloud CLI، به مستندات مرجع مراجعه کنید.

آزمایشی را به صورت محلی اجرا کنید

برای اجرای تست خود به صورت محلی، برنامه بازی خود را در یک شبیه ساز بارگیری کنید و اجرا کنید:

xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://
  • با اجرای دستور instruments -s devices می توانید UDID شبیه ساز خود را پیدا کنید.

  • اگر فقط یک شبیه‌ساز در حال اجرا است، رشته ویژه "booted" را به جای SIMULATOR_UDID وارد کنید.

اگر تست شما حاوی چندین حلقه است، می توانید با ارسال شماره حلقه به پرچم scenario مشخص کنید که کدام حلقه را می خواهید اجرا کنید. توجه داشته باشید که زمانی که تست خود را به صورت محلی اجرا می کنید، می توانید هر بار فقط یک حلقه را اجرا کنید. به عنوان مثال، اگر می خواهید حلقه های 1، 2 و 5 را اجرا کنید، باید برای هر حلقه یک دستور جداگانه اجرا کنید:

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

یک آزمایش را زودتر تمام کنید

به‌طور پیش‌فرض، آزمایش حلقه بازی تا زمانی که به پنج دقیقه باز می‌گردد، اجرا می‌شود، حتی زمانی که همه حلقه‌ها اجرا شده باشند. زمانی که به مهلت پایان رسید، آزمایش پایان می‌یابد و حلقه‌های معلق را لغو می‌کند. می توانید با فراخوانی طرح URL سفارشی firebase-game-loop-complete در AppDelegate برنامه آزمایشی آزمایش خود را سرعت بخشیده یا آن را زود به پایان برسانید. مثلا:

سریع

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

هدف-C

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

تست حلقه بازی شما حلقه فعلی را خاتمه می دهد و حلقه بعدی را اجرا می کند. هنگامی که حلقه دیگری برای اجرا وجود ندارد، آزمایش به پایان می رسد.

نتایج آزمون سفارشی را بنویسید

می‌توانید تست حلقه بازی خود را برای نوشتن نتایج آزمایشی سفارشی در سیستم فایل دستگاه خود پیکربندی کنید. به این ترتیب، هنگامی که تست شروع به اجرا می کند، Test Lab فایل های نتیجه را در یک پوشه GameLoopsResults در دستگاه تست شما (که باید خودتان ایجاد کنید) ذخیره می کند. هنگامی که آزمایش به پایان می رسد، آزمایشگاه تست همه فایل ها را از دایرکتوری GameLoopResults به سطل پروژه شما منتقل می کند. هنگام تنظیم تست به نکات زیر توجه کنید:

  • همه فایل های نتیجه بدون در نظر گرفتن نوع، اندازه یا کمیت فایل آپلود می شوند.

  • Test Lab تا زمانی که تمام حلقه‌های تست شما به پایان نرسیده است، نتایج آزمایش شما را پردازش نمی‌کند، بنابراین اگر آزمایش شما شامل چندین حلقه است که خروجی نوشتن دارند، مطمئن شوید که آنها را به یک فایل نتیجه منحصربفرد اضافه کرده‌اید یا یک فایل نتیجه برای هر حلقه ایجاد کنید. به این ترتیب، می توانید از بازنویسی نتایج حلقه قبلی جلوگیری کنید.

برای تنظیم تست خود برای نوشتن نتایج تست سفارشی:

  1. در دایرکتوری Documents برنامه خود، دایرکتوری به نام GameLoopResults ایجاد کنید.

  2. از هر کجای کد برنامه خود (به عنوان مثال، نماینده برنامه خود)، موارد زیر را اضافه کنید:

    سریع

    /// 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.
      }
    }
    

    هدف-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];
        }
    }