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

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

คุณสามารถใช้การทดสอบที่มี Loop เดียวหรือหลาย Loop ทั้งนี้ขึ้นอยู่กับเครื่องมือสร้างเกม ลูปคือการทดสอบแอปเล่นเกมของคุณทั้งบางส่วนหรือทั้งหมด Game 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. เปิดแอปทดสอบแอป Loop ในโทรศัพท์หรือแท็บเล็ต แอปจะแสดงรายการแอปในอุปกรณ์ที่ทำงานกับลูปเกมได้ หากไม่เห็นแอปเล่นเกมที่นี่ ให้ตรวจสอบว่าตัวกรอง Intent ตรงกับตัวกรองที่อธิบายไว้ในขั้นตอนแรกของส่วนก่อนเริ่มต้น
  3. เลือกแอปเล่นเกม แล้วเลือกจำนวนรอบที่ต้องการเรียกใช้ หมายเหตุ: ในขั้นตอนนี้ คุณสามารถเลือกเรียกใช้ชุดย่อยของลูปแทนที่จะเรียกใช้เพียงลูปเดียว ดูข้อมูลเพิ่มเติมเกี่ยวกับการเรียกใช้ลูปหลายรายการพร้อมกันได้ที่ฟีเจอร์ที่ไม่บังคับ
  4. คลิกเรียกใช้การทดสอบ การทดสอบจะเริ่มทํางานทันที

ทำงานใน Test Lab

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

ใช้คอนโซล Firebase

  1. ในคอนโซล Firebase ให้คลิก Test Lab จากแผงด้านซ้าย
  2. คลิกเรียกใช้การทดสอบครั้งแรก (หรือเรียกใช้การทดสอบหากโปรเจ็กต์เคยเรียกใช้การทดสอบแล้ว)
  3. เลือกรอบเกมเป็นประเภทการทดสอบ แล้วคลิกต่อไป
  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 ให้ระบุรายการจำนวนรอบโดยใช้ Flag --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

เมื่อติดป้ายกำกับลูปเกมด้วยป้ายกำกับสถานการณ์อย่างน้อย 1 รายการ คุณและทีม QA จะเปิดชุดลูปเกมที่เกี่ยวข้องได้ง่ายๆ (เช่น "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: ลูป For ใช้ทดสอบประสิทธิภาพของอุปกรณ์ เช่น เกมอาจทำงานด้วยการตั้งค่ากราฟิกที่ซับซ้อนที่สุดเพื่อดูลักษณะการทำงานของอุปกรณ์ใหม่

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

  • หากคุณทำการทดสอบด้วย 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 รายการโดยใช้ Flag --scenario-labels (เช่น --scenario-labels=performance,gpu)

การรองรับการอนุญาตให้ใช้สิทธิแอป

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

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

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

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