iOS-এর জন্য গেম লুপ টেস্ট শুরু করা

গেম লুপ টেস্টের মাধ্যমে, আপনি নিজের গেম ইঞ্জিনের নেটিভ টেস্ট লিখতে এবং তারপর আপনার বেছে নেওয়া ডিভাইসে Test Lab-এ সেগুলি চালাতে পারবেন। এইভাবে, আপনাকে আলাদা UI বা টেস্টিং ফ্রেমওয়ার্কের জন্য কোড লেখার ব্যাপারে চিন্তা করতে হবে না। গেম লুপ টেস্ট আসল প্লেয়ারের অ্যাকশন সিমুলেট করে এবং আপনি Test Lab-এ এটি রান করলে, আপনার গেম ব্যবহারকারীদের জন্য ভাল পারফর্ম করছে কিনা তা যাচাই করার জন্য এটি দ্রুত এবং স্কেলেবল উপায় প্রদান করে।

এই পৃষ্ঠায় আপনি দেখতে পাবেন কীভাবে গেম লুপ টেস্ট রান করতে হয়, তারপর Firebase কনসোলের Test Lab পৃষ্ঠায় আপনার টেস্টের ফলাফল দেখতে ও ম্যানেজ করতে পারবেন। এছাড়াও, আপনি ঐচ্ছিক ফিচারের মাধ্যমে আপনার টেস্ট আরও কাস্টমাইজ করতে পারবেন, যেমন কাস্টম টেস্ট ফলাফল লেখা অথবা আপনার টেস্ট তাড়াতাড়ি শেষ করা।

গেম লুপ টেস্ট কী?

লুপ হল আপনার গেমিং অ্যাপে আপনার পরীক্ষার সম্পূর্ণ বা আংশিক রান-থ্রু। আপনি স্থানীয়ভাবে একটি সিমুলেটরে বা Test Lab-এ ডিভাইসের সেটে একটি গেম লুপ পরীক্ষা চালাতে পারেন। গেম লুপ টেস্ট এইসব কাজে ব্যবহার করা যেতে পারে:

  • ব্যবহারকারী যেভাবে খেলবেন সেইভাবে আপনার গেমটি খেলুন। আপনি ব্যবহারকারীর ইনপুট স্ক্রিপ্ট করতে পারেন, ব্যবহারকারীকে নিষ্ক্রিয় থাকতে দিতে পারেন বা ব্যবহারকারীকে AI দিয়ে প্রতিস্থাপন করতে পারেন (উদাহরণস্বরূপ, আপনি যদি কোনও কার রেসিং গেমে AI প্রয়োগ করেন, তাহলে আপনি ব্যবহারকারীর ইনপুটের দায়িত্বে একজন AI ড্রাইভারকে রাখতে পারেন)।

  • কোন কোন ডিভাইস আপনার গেম সবচেয়ে ভাল কোয়ালিটি সেটিংয়ে চালাতে পারবে তা জানতে, গেমটি সবচেয়ে ভাল কোয়ালিটি সেটিংয়ে চালান।

  • টেকনিক্যাল টেস্ট রান করুন, যেমন একাধিক শেডার কম্পাইল করা, সেগুলি এক্সিকিউট করা এবং আউটপুট প্রত্যাশিত কিনা তা চেক করা।

ধাপ ১: Test Lab-এর কাস্টম URL স্কিম রেজিস্টার করা

প্রথমে, আপনার অ্যাপে Firebase Test Lab-এর কাস্টম URL স্কিম রেজিস্টার করতে হবে:

  1. Xcode-এ, প্রোজেক্ট টার্গেট বেছে নিন।

  2. তথ্য ট্যাবে ক্লিক করুন, তারপর নতুন URL-এর ধরন যোগ করুন।

  3. URL স্কিম ফিল্ডে firebase-game-loop লিখুন। এছাড়াও, আপনার প্রোজেক্টের Info.plist কনফিগারেশন ফাইলের <dict> ট্যাগের মধ্যে যেকোনও জায়গায় কাস্টম URL স্কিম যোগ করে সেটি রেজিস্টার করতে পারবেন:

    <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 ব্যবহার করে টেস্ট চালানোর জন্য কনফিগার করা হয়েছে।

ধাপ ২ (ঐচ্ছিক): একাধিক লুপ চালানোর জন্য আপনার অ্যাপ কনফিগার করুন

আপনার অ্যাপে একাধিক কাস্টম URL স্কিম রেজিস্টার করা থাকলে এবং আপনি টেস্টে একাধিক লুপ (ওরফে সিনারিও) রান করার পরিকল্পনা করলে, লঞ্চ করার সময় আপনার অ্যাপে কোন লুপ রান করতে চান তা আপনাকে উল্লেখ করতে হবে।

আপনার অ্যাপ ডেলিগেটে, 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:).
  }
}

আপনার টেস্টে একাধিক লুপ রান করলে, বর্তমান লুপটি অ্যাপ লঞ্চ করার জন্য ব্যবহৃত URL-এ প্যারামিটার হিসেবে পাস করা হয়। আপনি কাস্টম URL স্কিম আনার জন্য ব্যবহৃত URLComponents অবজেক্ট পার্স করে বর্তমান লুপ নম্বরও পেতে পারেন:

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

ধাপ ৩: টেস্ট তৈরি ও রান করা

Test Lab-এর কাস্টম URL স্কিম রেজিস্টার করার পরে, আপনি Firebase কনসোল বা gcloud beta CLI-এর মাধ্যমে আপনার টেস্ট চালাতে পারবেন। আপনি আগে থেকে না করে থাকলে, আপনার অ্যাপের জন্য একটি IPA ফাইল তৈরি করুন (পরে এটি খুঁজে পেতে হবে)।

Firebase কনসোলে টেস্ট রান করুন

  1. Firebase কনসোলে, DevOps ও এনগেজমেন্ট > Test Lab বিকল্পে যান।

  2. আপনার প্রথম টেস্ট রান করুন > iOS গেম লুপ রান করুন বিকল্পে ক্লিক করুন।

  3. অ্যাপ আপলোড করুন বিভাগে, ব্রাউজ করুন বিকল্পে ক্লিক করুন, তারপর আপনার অ্যাপের IPA ফাইল বেছে নিন (আপনি আগে থেকে না করে থাকলে, আপনার অ্যাপের জন্য একটি IPA ফাইল তৈরি করুন)।

  4. (ঐচ্ছিক) আপনি যদি একবারে একাধিক লুপ (ওরফে সিনারিও) চালাতে চান বা চালানোর জন্য নির্দিষ্ট লুপ বেছে নিতে চান, তাহলে সিনারিও ফিল্ডে লুপ নম্বর লিখুন।

    যেমন, আপনি 1-3, 5 লিখলে, Test Lab লুপ রান করে 1, 2, 3 এবং 5। ডিফল্ট হিসেবে (আপনি সিনারিও ফিল্ডে কিছু না লিখলে), Test Lab শুধু 1 লুপ রান করে।

  5. ডিভাইস বিভাগে, আপনি যে ফিজিক্যাল ডিভাইসে অ্যাপ পরীক্ষা করতে চান, সেটি বেছে নিন, তারপর পরীক্ষা শুরু করুন বিকল্পে ক্লিক করুন।

gcloud beta CLI-এর মাধ্যমে টেস্ট রান করুন

  1. আপনি আগে থেকে না করে থাকলে, আপনার লোকাল gcloud SDK এনভায়রনমেন্ট কনফিগার করুন, তারপর gcloud বিটা কম্পোনেন্ট ইনস্টল করতে ভুলবেন না।

  2. gcloud beta firebase test ios run কমান্ড রান করুন এবং রান কনফিগার করতে নিম্নলিখিত ফ্ল্যাগ ব্যবহার করুন:

গেম লুপ টেস্টের জন্য ফ্ল্যাগ
--type

প্রয়োজনীয়: আপনি যে ধরনের iOS টেস্ট চালাতে চান তা নির্দিষ্ট করে। আপনি পরীক্ষার ধরন xctest (ডিফল্ট) বা game-loop লিখতে পারেন।

--app

প্রয়োজনীয়: আপনার অ্যাপের IPA ফাইলের অ্যাবসোলিউট পাথ (Google Cloud Storage বা ফাইলসিস্টেম)। গেম লুপ টেস্ট রান করার সময় শুধুমাত্র এই ফ্ল্যাগটি বৈধ।

--scenario-numbers

আপনার অ্যাপে যে লুপ (ওরফে সিনারিও) চালাতে চান। আপনি একটি লুপ, তালিকা বা লুপ বা লুপের রেঞ্জ লিখতে পারেন। ডিফল্ট লুপ হল ১।

যেমন, --scenario-numbers=1-3,5 লুপ ১, ২, ৩ ও ৫ রান করে।

--device-model

আপনি যে ফিজিক্যাল ডিভাইসে টেস্ট রান করতে চান (কোন উপলভ্য ডিভাইস আপনি ব্যবহার করতে পারবেন তা খুঁজে দেখুন)।

--timeout

আপনি সর্বাধিক কত সময় ধরে পরীক্ষা চালাতে চান। সেকেন্ডে সময়সীমা দেখানোর জন্য আপনি পূর্ণসংখ্যা লিখতে পারেন অথবা আরও বেশি সময়সীমা দেখানোর জন্য পূর্ণসংখ্যা ও এনিউমারেশন লিখতে পারেন।

যেমন:

  • --timeout=200 আপনার টেস্ট ২০০ সেকেন্ড পর্যন্ত চললে, সেটি বন্ধ করতে বাধ্য করে।
  • --timeout=1h আপনার টেস্ট এক ঘণ্টা পর্যন্ত চললে সেটি বন্ধ করতে বাধ্য করে।

যেমন, নিম্নলিখিত কমান্ডটি একটি গেম লুপ টেস্ট রান করে যা iPhone 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

gcloud CLI সম্পর্কে আরও তথ্যের জন্য, রেফারেন্স ডকুমেন্টেশন দেখুন।

স্থানীয়ভাবে টেস্ট রান করুন

আপনার টেস্ট লোকালি রান করতে, সিমুলেটরে আপনার গেমিং অ্যাপ লোড করুন এবং রান করুন:

xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://
  • instruments -s devices কমান্ড রান করে আপনি সিমুলেটরের UDID খুঁজে পেতে পারেন।

  • শুধুমাত্র একটি সিমুলেটর চললে, SIMULATOR_UDID-এর জায়গায় বিশেষ স্ট্রিং "booted" লিখুন।

আপনার টেস্টে একাধিক লুপ থাকলে, আপনি কোন লুপ চালাতে চান তা scenario ফ্ল্যাগে লুপ নম্বর পাস করে নির্দিষ্ট করতে পারেন। মনে রাখবেন যে লোকাল টেস্ট চালানোর সময় আপনি একবারে শুধু একটি লুপ চালাতে পারবেন। যেমন, আপনি যদি ১, ২ ও ৫ নম্বর লুপ চালাতে চান, তাহলে প্রতিটি লুপের জন্য আপনাকে আলাদা কমান্ড চালাতে হবে:

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

নির্ধারিত সময়ের আগে টেস্ট শেষ করা

ডিফল্ট হিসেবে, গেম লুপ টেস্ট টাইমআউট হওয়ার পাঁচ মিনিট পর্যন্ত চলতে থাকে, এমনকি সব লুপ এক্সিকিউট হয়ে গেলেও। টাইমআউট হয়ে গেলে, টেস্ট শেষ হয়ে যায় এবং যেকোনও পেন্ডিং লুপ বাতিল হয়ে যায়। আপনার অ্যাপের AppDelegate-এ Test Lab-এর কাস্টম URL স্কিম firebase-game-loop-complete কল করে আপনি টেস্টের গতি বাড়াতে অথবা এটি তাড়াতাড়ি শেষ করতে পারবেন। যেমন:

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 Lab আপনার টেস্টিং ডিভাইসে (যা আপনাকে নিজে তৈরি করতে হবে) GameLoopsResults ডিরেক্টরিতে ফলাফলের ফাইল সেভ করে। পরীক্ষা শেষ হলে, Test Lab GameLoopResults ডিরেক্টরি থেকে সব ফাইল আপনার প্রোজেক্টের বাকেটে সরিয়ে দেয়। আপনার টেস্ট সেট-আপ করার সময় নিম্নলিখিত বিষয়গুলি মনে রাখবেন:

  • ফাইলের ধরন, সাইজ বা পরিমাণ যাই হোক না কেন, সব ফলাফল ফাইল আপলোড করা হয়।

  • আপনার টেস্টের সব লুপ রান করা শেষ না হওয়া পর্যন্ত Test Lab আপনার টেস্টের ফলাফল প্রসেস করে না, তাই আপনার টেস্টে যদি একাধিক লুপ থাকে যা আউটপুট লেখে, তাহলে নিশ্চিত করুন যে আপনি সেগুলিকে একটি অনন্য ফলাফল ফাইলে যোগ করেছেন বা প্রতিটি লুপের জন্য একটি ফলাফল ফাইল তৈরি করেছেন। এইভাবে, আপনি আগের লুপ থেকে ফলাফল ওভাররাইট করা এড়াতে পারেন।

কাস্টম পরীক্ষার ফলাফল লিখতে আপনার পরীক্ষা সেট-আপ করতে:

  1. আপনার অ্যাপের Documents ডিরেক্টরিতে, GameLoopResults নামের একটি ডিরেক্টরি তৈরি করুন।

  2. আপনার অ্যাপের কোডের যেকোনও জায়গা থেকে (যেমন, আপনার অ্যাপ ডেলিগেট), নিম্নলিখিত কোডটি যোগ করুন:

    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];
        }
    }