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

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

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

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

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

ก่อนจะเริ่ม

ในการดำเนินการทดสอบ คุณต้องกำหนดค่าแอปของคุณสำหรับการทดสอบ Game Loop ก่อน

  1. ในรายการแอปของคุณ ให้เพิ่มตัวกรองความตั้งใจใหม่ให้กับ กิจกรรม ของคุณ:

    <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 สามารถเปิดเกมของคุณได้โดยการเรียกเกมด้วยความตั้งใจเฉพาะ

  2. ในรหัสของคุณ (เราแนะนำในการประกาศเมธอด onCreate ) ให้เพิ่มสิ่งต่อไปนี้:

    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
    }

    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
    }

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

  3. แนะนำ: เมื่อสิ้นสุดการทดสอบ ให้เพิ่ม:

    Java

    yourActivity.finish();

    Kotlin+KTX

    yourActivity.finish()

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

สร้างและเรียกใช้การทดสอบ Game Loop

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

ทำงานบนอุปกรณ์ท้องถิ่น

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

ในการรันการทดสอบบนอุปกรณ์ในพื้นที่โดยใช้ Test Loop Manager:

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

เรียกใช้ในห้องปฏิบัติการทดสอบ

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

ใช้คอนโซล Firebase

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

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

Java

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

Kotlin+KTX

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

หากคุณต้องการเขียนไฟล์จากด้าน C++ ของแอปเกม คุณสามารถส่งผ่าน file descriptor แทนเส้นทางของไฟล์:

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);

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);

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

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

คุณสามารถใช้ไฟล์ข้อมูลเอาต์พุต (จัดรูปแบบตามตัวอย่างด้านล่าง) เพื่อแสดงผลการทดสอบ Game Loop ในส่วน 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
}

หลายเกมลูป

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

ในการทำให้แอปของคุณทำงานหลายลูปพร้อมกัน:

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

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

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

      จุดประสงค์ในการเรียกใช้นี้มีลูปเป้าหมายเป็นพารามิเตอร์จำนวนเต็ม ในฟิลด์ 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++ ดั้งเดิมของคุณ:

    Java

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

    Kotlin+KTX

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

    ตอนนี้คุณสามารถเปลี่ยนพฤติกรรมของลูปของคุณตามค่า int ที่เป็นผลลัพธ์

ติดฉลากเกมลูป

เมื่อคุณติดป้ายกำกับลูปเกมของคุณด้วยป้ายกำกับสถานการณ์หนึ่งรายการขึ้นไป คุณและทีม QA ของคุณสามารถเปิดชุดลูปเกมที่เกี่ยวข้องได้อย่างง่ายดาย (เช่น "ลูปเกมที่เข้ากันได้ทั้งหมด") และทดสอบพวกมันในเมทริกซ์เดียว คุณสามารถสร้างป้ายกำกับของคุณเองหรือใช้ป้ายกำกับที่กำหนดไว้ล่วงหน้าที่ 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 ของแอปของคุณ ให้เพิ่มบรรทัด meta-data ต่อไปนี้และแทนที่ 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 Manager ให้ป้อนป้ายกำกับอย่างน้อยหนึ่งป้ายในช่อง ป้ายกำกับ

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

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

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

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

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

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

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