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

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

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

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

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

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

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

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

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

ابتدا، باید طرح 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" را وارد می کنید، Test Lab حلقه های 1، 2، 3 و 5 را اجرا می کند. به طور پیش فرض (اگر چیزی در قسمت سناریوها وارد نکنید)، Test Lab فقط حلقه 1 را اجرا می کند.

  5. در بخش دستگاه‌ها ، یک یا چند دستگاه فیزیکی را که می‌خواهید برنامه خود را روی آن آزمایش کنید، انتخاب کنید، سپس روی 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 برنامه Test Lab آزمایش خود را سرعت بخشیده یا آن را زود به پایان برسانید. به عنوان مثال:

سویفت

/// 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 در دستگاه تست شما (که باید خودتان ایجاد کنید) ذخیره می کند. وقتی آزمایش به پایان می رسد، Test Lab همه فایل ها را از پوشه 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];
        }
    }