เริ่มต้นใช้งานการทดสอบ Game Loop

การทดสอบเกมแบบอัตโนมัติอาจทำได้ยากเมื่อแอปเล่นเกมสร้างขึ้นบนเฟรมเวิร์ก UI ที่ต่างกัน การทดสอบ Game Loop ช่วยให้คุณผสานรวมการทดสอบแบบเนทีฟกับ Test Lab และเรียกใช้การทดสอบบนอุปกรณ์ที่เลือกได้อย่างง่ายดาย การทดสอบ Game Loop จะทำการทดสอบผ่านแอปเล่นเกมของคุณขณะจำลองการดําเนินการของผู้เล่นจริง คู่มือนี้จะแสดงวิธีทำการทดสอบ Game Loop จากนั้นดูและจัดการผลการทดสอบในคอนโซล Firebase

คุณสามารถใช้การทดสอบที่มี Loop เดียวหรือหลาย Loop ทั้งนี้ขึ้นอยู่กับเครื่องมือสร้างเกม ลูปคือการทดสอบแอปเล่นเกมของคุณทั้งบางส่วนหรือทั้งหมด ลูปเกมมีไว้เพื่อดำเนินการต่อไปนี้

  • เรียกใช้ด่านของเกมในลักษณะเดียวกับที่ผู้ใช้ปลายทางจะเล่น คุณสามารถเขียนสคริปต์การป้อนข้อมูลของผู้ใช้ ปล่อยให้ผู้ใช้ไม่มีความเคลื่อนไหว หรือแทนที่ผู้ใช้ด้วย AI ก็ได้หากมีความเหมาะสมในเกมของคุณ (เช่น สมมติว่าคุณมีแอปเล่นเกมรถแข่งและใช้งาน AI อยู่แล้ว คุณสามารถใช้ AI เป็นตัวควบคุมที่รับผิดชอบอินพุตของผู้ใช้ได้อย่างง่ายดาย
  • เรียกใช้เกมที่การตั้งค่าคุณภาพสูงสุดเพื่อดูว่าอุปกรณ์รองรับหรือไม่
  • ทำการทดสอบทางเทคนิค (คอมไพล์ตัวปรับแสงเงาหลายๆ ตัว เรียกใช้ เรียกใช้ ตรวจสอบว่าเอาต์พุตเป็นไปตามที่คาดไว้ ฯลฯ)

คุณสามารถทำการทดสอบ Game Loop บนอุปกรณ์ทดสอบเครื่องเดียว ชุดอุปกรณ์ทดสอบ หรือใน Test Lab อย่างไรก็ตาม เราไม่แนะนำให้ทำการทดสอบ Game Loop บนอุปกรณ์เสมือนเนื่องจากมีอัตราเฟรมกราฟิกต่ำกว่าอุปกรณ์จริง

ก่อนเริ่มต้น

หากต้องการใช้การทดสอบ คุณต้องกําหนดค่าแอปสําหรับการทดสอบ Game Loop ก่อน

  1. ในไฟล์ Manifest ของแอป ให้เพิ่มตัวกรอง Intent ใหม่ลงใน activity ดังนี้

    <activity android:name=".MyActivity">
       <intent-filter>
           <action android:name="com.google.intent.action.TEST_LOOP"/>
           <category android:name="android.intent.category.DEFAULT"/>
           <data android:mimeType="application/javascript"/>
       </intent-filter>
       <intent-filter>
          ... (other intent filters here)
       </intent-filter>
    </activity>

    ซึ่งจะช่วยให้ Test Lab เปิดเกมได้โดยทริกเกอร์ด้วย Intent ที่เฉพาะเจาะจง

  2. ในโค้ด (เราขอแนะนำให้เพิ่มภายในประกาศเมธอด onCreate) ให้เพิ่มข้อมูลต่อไปนี้

    Kotlin+KTX

    val launchIntent = intent
    if (launchIntent.action == "com.google.intent.action.TEST_LOOP") {
        val scenario = launchIntent.getIntExtra("scenario", 0)
        // Code to handle your game loop here
    }

    Java

    Intent launchIntent = getIntent();
    if(launchIntent.getAction().equals("com.google.intent.action.TEST_LOOP")) {
        int scenario = launchIntent.getIntExtra("scenario", 0);
        // Code to handle your game loop here
    }

    ซึ่งจะช่วยให้กิจกรรมตรวจสอบ Intent ที่เปิดใช้งานได้ นอกจากนี้ คุณยังเพิ่มโค้ดนี้ในภายหลังได้หากต้องการ (เช่น หลังจากโหลดเครื่องมือเล่นเกมครั้งแรก)

  3. แนะนํา: เมื่อสิ้นสุดการทดสอบ ให้เพิ่มข้อมูลต่อไปนี้

    Kotlin+KTX

    yourActivity.finish()

    Java

    yourActivity.finish();

    การดำเนินการนี้จะปิดแอปของคุณเมื่อการทดสอบ Game Loop เสร็จสมบูรณ์ การทดสอบอาศัยเฟรมเวิร์ก UI ของแอปเพื่อเริ่มลูปถัดไป และการปิดแอปจะบอกให้ระบบทราบว่าการทดสอบเสร็จสิ้นแล้ว

สร้างและทำการทดสอบ Game Loop

หลังจากกำหนดค่าแอปสำหรับการทดสอบ Game Loop แล้ว คุณสามารถสร้างการทดสอบและเรียกใช้ในแอปเล่นเกมได้ทันที โดยเลือกที่จะทำการทดสอบใน Test Lab โดยใช้คอนโซล Firebase หรือ gcloud command line interface (CLI) หรือในอุปกรณ์เครื่องที่ใช้อยู่โดยใช้ Test Loop Manager ก็ได้

เรียกใช้ในอุปกรณ์ภายใน

Test Loop Manager ของ Test Lab เป็นแอปโอเพนซอร์สที่ช่วยให้คุณผสานรวมการทดสอบ Game Loop และเรียกใช้การทดสอบเหล่านั้นในอุปกรณ์ภายในของคุณ นอกจากนี้ยังช่วยให้ทีมตรวจสอบคุณภาพสามารถเรียกใช้ลูปเกมเดียวกันในอุปกรณ์ของตนได้อีกด้วย

วิธีทำการทดสอบในอุปกรณ์เครื่องที่ใช้อยู่โดยใช้เครื่องมือจัดการ Test Loop

  1. ดาวน์โหลด Test Loop Manager ในโทรศัพท์หรือแท็บเล็ต แล้วติดตั้งโดยเรียกใช้คำสั่งต่อไปนี้
    adb install testloopmanager.apk
  2. เปิดแอปแอป Test Loop ในโทรศัพท์หรือแท็บเล็ต แอปจะแสดงรายการแอปในอุปกรณ์ที่ทำงานกับลูปเกมได้ หากไม่เห็นแอปเกมที่นี่ ให้ตรวจสอบว่าตัวกรอง Intent ตรงกับรายการที่อธิบายไว้ในขั้นตอนแรกของส่วนก่อนเริ่มต้น
  3. เลือกแอปเล่นเกม แล้วเลือกจำนวนรอบที่ต้องการเรียกใช้ หมายเหตุ: ในขั้นตอนนี้ คุณสามารถเลือกเรียกใช้ชุดย่อยของลูปแทนที่จะเรียกใช้เพียงลูปเดียว ดูข้อมูลเพิ่มเติมเกี่ยวกับการเรียกใช้ลูปหลายรายการพร้อมกันที่ฟีเจอร์เสริม
  4. คลิกเรียกใช้การทดสอบ การทดสอบจะเริ่มทํางานทันที

ทำงานใน Test Lab

คุณสามารถทำการทดสอบ Game Loop ใน Test Lab โดยใช้คอนโซล Firebase หรือ gcloud CLI ก่อนเริ่มต้น ให้เปิดคอนโซล Firebase และสร้างโปรเจ็กต์ หากยังไม่ได้ดำเนินการ

ใช้คอนโซล Firebase

  1. ในคอนโซล Firebase ให้คลิก Test Lab จากแผงด้านซ้าย
  2. คลิกเรียกใช้การทดสอบครั้งแรก (หรือเรียกใช้การทดสอบหากโปรเจ็กต์เคยเรียกใช้การทดสอบแล้ว)
  3. เลือก Game Loop เป็นประเภทการทดสอบ แล้วคลิกต่อไป
  4. คลิกเรียกดู แล้วเรียกดูไฟล์ .apk ของแอป หมายเหตุ: ในขั้นตอนนี้ คุณเลือกเรียกใช้การวนซ้ำชุดย่อยแทนการวนซ้ำเพียงรายการเดียวได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับการเรียกใช้ลูปหลายรายการพร้อมกันได้ที่ฟีเจอร์ที่ไม่บังคับ
  5. คลิกต่อไป
  6. เลือกอุปกรณ์จริงที่จะใช้ทดสอบแอป
  7. คลิกเริ่มการทดสอบ

ดูข้อมูลเพิ่มเติมเกี่ยวกับการเริ่มต้นใช้งานคอนโซล Firebase ได้ที่เริ่มการทดสอบด้วยคอนโซล Firebase

ใช้บรรทัดคำสั่ง gcloud (CLI)

  1. ดาวน์โหลดและติดตั้ง Google Cloud SDK หากยังไม่ได้ดำเนินการ

  2. ลงชื่อเข้าใช้ gcloud CLI โดยใช้บัญชี Google โดยใช้คำสั่งต่อไปนี้

    gcloud auth login

  3. ตั้งค่าโปรเจ็กต์ Firebase ใน gcloud โดย PROJECT_ID คือรหัสของโปรเจ็กต์ Firebase ดังนี้

    gcloud config set project PROJECT_ID
    
  4. ทำการทดสอบครั้งแรก

    gcloud firebase test android run \
     --type=game-loop --app=<var>path-to-apk</var> \
     --device model=herolte,version=23
    

ดูข้อมูลเพิ่มเติมเกี่ยวกับการเริ่มต้นใช้งาน gcloud CLI ได้ที่เริ่มทดสอบจากบรรทัดคำสั่ง gcloud

ฟีเจอร์เสริม

Test Lab มีฟีเจอร์เสริมหลายอย่างที่ช่วยให้คุณปรับแต่งการทดสอบเพิ่มเติมได้ ซึ่งรวมถึงความสามารถในการเขียนข้อมูลเอาต์พุต รองรับเกมลูปหลายรายการ และป้ายกำกับสำหรับลูปที่เกี่ยวข้อง

เขียนข้อมูลเอาต์พุต

การทดสอบ Game Loop สามารถเขียนเอาต์พุตไปยังไฟล์ที่ระบุในเมธอด launchIntent.getData() หลังจากทำการทดสอบแล้ว คุณจะเข้าถึงข้อมูลเอาต์พุตนี้ได้ในส่วน Test Lab ของคอนโซล Firebase (ดูตัวอย่างไฟล์เอาต์พุตการทดสอบรอบเกม)

Test Lab ปฏิบัติตามแนวทางปฏิบัติแนะนำสำหรับการแชร์ไฟล์ระหว่างแอปตามที่อธิบายไว้ในหัวข้อการแชร์ไฟล์ ในเมธอด onCreate() ของกิจกรรมซึ่งมี Intent อยู่ คุณสามารถตรวจสอบไฟล์เอาต์พุตข้อมูลได้โดยเรียกใช้โค้ดต่อไปนี้

Kotlin+KTX

val launchIntent = intent
val logFile = launchIntent.data
logFile?.let {
    Log.i(TAG, "Log file ${it.encodedPath}")
    // ...
}

Java

Intent launchIntent = getIntent();
Uri logFile = launchIntent.getData();
if (logFile != null) {
    Log.i(TAG, "Log file " + logFile.getEncodedPath());
    // ...
}

หากต้องการเขียนลงในไฟล์จากฝั่ง C++ ของแอปเกม คุณสามารถส่งผ่านตัวระบุไฟล์แทนเส้นทางไฟล์ได้ ดังนี้

Kotlin+KTX

val launchIntent = intent
val logFile = launchIntent.data
var fd = -1
logFile?.let {
    Log.i(TAG, "Log file ${it.encodedPath}")
    fd = try {
        contentResolver
            .openAssetFileDescriptor(logFile, "w")!!
            .parcelFileDescriptor
            .fd
    } catch (e: FileNotFoundException) {
        e.printStackTrace()
        -1
    } catch (e: NullPointerException) {
        e.printStackTrace()
        -1
    }
}

// C++ code invoked here.
// native_function(fd);

Java

Intent launchIntent = getIntent();
Uri logFile = launchIntent.getData();
int fd = -1;
if (logFile != null) {
    Log.i(TAG, "Log file " + logFile.getEncodedPath());
    try {
        fd = getContentResolver()
                .openAssetFileDescriptor(logFile, "w")
                .getParcelFileDescriptor()
                .getFd();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        fd = -1;
    } catch (NullPointerException e) {
        e.printStackTrace();
        fd = -1;
    }
}

// C++ code invoked here.
// native_function(fd);

C++

#include <unistd.h>
JNIEXPORT void JNICALL
Java_my_package_name_MyActivity_native_function(JNIEnv *env, jclass type, jint log_file_descriptor) {
// The file descriptor needs to be duplicated.
int my_file_descriptor = dup(log_file_descriptor);
}

ตัวอย่างไฟล์เอาต์พุต

คุณสามารถใช้ไฟล์ข้อมูลเอาต์พุต (จัดรูปแบบตามตัวอย่างด้านล่าง) เพื่อแสดงผลการทดสอบลูปเกมได้ในส่วน Test Lab ของคอนโซล Firebase พื้นที่ที่แสดงเป็น /.../ อาจมีช่องที่กำหนดเองตามต้องการ ตราบใดที่ช่องเหล่านั้นไม่ขัดแย้งกับชื่อของช่องอื่นๆ ที่ใช้ในไฟล์นี้

{
  "name": "test name",
  "start_timestamp": 0, // Timestamp of the test start (in us).
                           Can be absolute or relative
  "driver_info": "...",
  "frame_stats": [
    {
      "timestamp": 1200000, // Timestamp at which this section was written
                               It contains value regarding the period
                               start_timestamp(0) -> this timestamp (1200000 us)
      "avg_frame_time": 15320, // Average time to render a frame in ns
      "nb_swap": 52, // Number of frame rendered
      "threads": [
        {
          "name": "physics",
          "Avg_time": 8030 // Average time spent in this thread per frame in us
        },
        {
          "name": "AI",
          "Avg_time": 2030 // Average time spent in this thread per frame in us
        }
      ],
      /.../ // Any custom field you want (vertices display on the screen, nb units …)
    },
    {
      // Next frame data here, same format as above
    }
  ],
  "loading_stats": [
    {
      "name": "assets_level_1",
      "total_time": 7850, // in us
      /.../
    },
    {
      "name": "victory_screen",
      "total_time": 554, // in us
      /.../
    }

  ],
  /.../, // You can add custom fields here
}

Game Loop หลายรายการ

คุณอาจพบว่าการเรียกใช้ Game Loop หลายรายการในแอปมีประโยชน์ โดย Loop คือการดำเนินการแอปเกมตั้งแต่ต้นจนจบอย่างสมบูรณ์ เช่น หากเกมมีหลายด่าน คุณอาจต้องการใช้ลูปเกม 1 รายการเพื่อเปิดแต่ละด่านแทนที่จะใช้ลูป 1 รายการที่วนซ้ำผ่านด่านทั้งหมด ด้วยวิธีนี้ หากแอปขัดข้องในระดับ 32 คุณสามารถเปิดลูปเกมนั้นได้โดยตรงเพื่อจำลองข้อขัดข้องและทดสอบการแก้ไขข้อบกพร่อง

วิธีเปิดใช้แอปให้เรียกใช้ลูปหลายรายการพร้อมกัน

  • หากคุณทำการทดสอบด้วย Test Loop Manager ให้ทำดังนี้

    1. เพิ่มบรรทัดต่อไปนี้ลงในไฟล์ Manifest ของแอปภายในองค์ประกอบ <application>

      <meta-data
        android:name="com.google.test.loops"
        android:value="5" />

      Intent การเปิดตัวนี้มีลูปเป้าหมายเป็นพารามิเตอร์จำนวนเต็ม ในช่อง android:value คุณสามารถระบุจำนวนเต็มตั้งแต่ 1 ถึง 1024 (จำนวนรอบสูงสุดที่อนุญาตสำหรับการทดสอบครั้งเดียว) โปรดทราบว่าระบบจะจัดทําดัชนีของลูปโดยเริ่มจาก 1 ไม่ใช่ 0

    2. ในแอป Test Loop Manager หน้าจอการเลือกจะปรากฏขึ้นเพื่อให้คุณเลือกลูปที่ต้องการเรียกใช้ หากเลือกหลายลูป ระบบจะเปิดแต่ละลูปตามลําดับหลังจากที่ลูปก่อนหน้าทํางานเสร็จ

  • หากคุณกำลังทำการทดสอบด้วยคอนโซล Firebase ให้ป้อนรายการหรือช่วงของจำนวนรอบในช่องสถานการณ์

  • หากกำลังทำการทดสอบด้วย gcloud CLI ให้ระบุรายการหมายเลขลูปโดยใช้แฟล็ก --scenario-numbers เช่น --scenario-numbers=1,3,5 เรียกใช้ลูป 1, 3 และ 5

  • ถ้าคุณกำลังเขียน C++ และต้องการเปลี่ยนลักษณะการทำงานของลูป ให้ส่งค่าต่อไปนี้ไปยังโค้ด C++ ดั้งเดิม

    Kotlin+KTX

    val launchIntent = intent
    val scenario = launchIntent.getIntExtra("scenario", 0)

    Java

    Intent launchIntent = getIntent();
    int scenario = launchIntent.getIntExtra("scenario", 0);

    ตอนนี้คุณสามารถเปลี่ยนลักษณะการทํางานของลูปตามintค่าที่ได้

ติดป้ายกำกับ Game Loop

เมื่อติดป้ายกำกับ Game Loop ด้วยป้ายกำกับสถานการณ์อย่างน้อย 1 รายการ คุณและทีม QA สามารถเปิดชุด Game Loop ที่เกี่ยวข้องได้โดยง่าย (เช่น "all compatibility game loops") และทดสอบในเมทริกซ์เดียว คุณสามารถสร้างป้ายกำกับของคุณเองหรือใช้ป้ายกำกับที่กำหนดไว้ล่วงหน้าซึ่ง Test Lab มีให้ดังนี้

  • com.google.test.loops.player_experience: สำหรับลูปที่ใช้เพื่อจำลองประสบการณ์ของผู้ใช้จริงเมื่อเล่นเกม เป้าหมายของการทดสอบด้วยลูปเหล่านี้คือการค้นหาปัญหาที่ผู้ใช้จริงอาจพบขณะเล่นเกม
  • com.google.test.loops.gpu_compatibility: สำหรับการวนซ้ำที่ใช้ทดสอบปัญหาที่เกี่ยวข้องกับ GPU เป้าหมายของการทดสอบด้วยลูปเหล่านี้คือการเรียกใช้โค้ด GPU ที่อาจทํางานไม่ถูกต้องในเวอร์ชันที่ใช้งานจริง เพื่อแสดงปัญหาเกี่ยวกับฮาร์ดแวร์และไดรเวอร์
  • com.google.test.loops.compatibility: สําหรับลูปที่ใช้ทดสอบปัญหาความเข้ากันได้ที่หลากหลาย รวมถึงปัญหา I/O และ OpenSSL
  • com.google.test.loops.performance: สำหรับลูปที่ใช้ทดสอบประสิทธิภาพของอุปกรณ์ เช่น เกมอาจทำงานด้วยการตั้งค่ากราฟิกที่ซับซ้อนที่สุดเพื่อดูว่าอุปกรณ์ใหม่ทำงานอย่างไร

วิธีเปิดใช้แอปให้เรียกใช้ลูปที่มีป้ายกำกับเดียวกัน

  • หากคุณทำการทดสอบด้วย Test Loop Manager ให้ทำดังนี้

    1. ในไฟล์ Manifest ของแอป ให้เพิ่มบรรทัดข้อมูลเมตาต่อไปนี้ แล้วแทนที่ LABEL_NAME ด้วยป้ายกำกับที่ต้องการ

      <meta-data
       android:name="com.google.test.loops.LABEL_NAME"
       android:value="1,3-5" />

      ในช่อง android:value คุณสามารถระบุช่วงหรือชุดจำนวนเต็มตั้งแต่ 1 ถึง 1024 (จำนวนรอบสูงสุดที่อนุญาตสำหรับการทดสอบครั้งเดียว) ที่แสดงถึงลูปที่ต้องการติดป้ายกำกับ โปรดทราบว่าระบบจะจัดทำดัชนีการวนซ้ำโดยเริ่มจาก 1 ไม่ใช่ 0 เช่น android:value="1,3-5" ใช้กับ LABEL_NAME ในลูป 1, 3, 4 และ 5

    2. ในแอปเครื่องมือจัดการ Test Loop ให้ป้อนป้ายกำกับอย่างน้อย 1 รายการในช่องป้ายกำกับ

  • หากกำลังทดสอบกับคอนโซล Firebase ให้ป้อนป้ายกำกับอย่างน้อย 1 รายการในช่องป้ายกำกับ

  • หากเรียกใช้การทดสอบด้วย gcloud CLI ให้ระบุป้ายกำกับสถานการณ์อย่างน้อย 1 รายการโดยใช้แฟล็ก --scenario-labels (เช่น --scenario-labels=performance,gpu)

การสนับสนุนการมอบใบอนุญาตแอป

Test Lab รองรับแอปที่ใช้บริการการอนุญาตให้ใช้แอปที่ Google Play นำเสนอ หากต้องการตรวจสอบการอนุญาตให้ใช้สิทธิให้เสร็จสมบูรณ์เมื่อทดสอบแอปกับ Test Lab คุณต้องเผยแพร่แอปไปยังช่องเวอร์ชันที่ใช้งานจริงใน Play Store หากต้องการทดสอบแอปในช่องทางอัลฟ่าหรือเบต้าโดยใช้ Test Lab ให้นำการตรวจสอบการอนุญาตให้ใช้สิทธิออกก่อนอัปโหลดแอปไปยัง Test Lab

ปัญหาที่ทราบ

การทดสอบ Game Loop ใน Test Lab มีปัญหาที่ทราบดังต่อไปนี้

  • ข้อขัดข้องบางรายการไม่รองรับ Backtrace เช่น บิลด์รุ่นบางเวอร์ชันอาจระงับเอาต์พุตของกระบวนการ debuggerd โดยใช้ prctl(PR_SET_DUMPABLE, 0) ดูข้อมูลเพิ่มเติมได้ที่ debuggerd
  • ขณะนี้ระบบยังไม่รองรับ API ระดับ 19 เนื่องจากข้อผิดพลาดเกี่ยวกับสิทธิ์ของไฟล์