การแมปการทดสอบ

นี่คือข้อมูลเบื้องต้นเกี่ยวกับการจับคู่การทดสอบและคำอธิบายเกี่ยวกับวิธีเริ่มต้นกำหนดค่าการทดสอบในโครงการโอเพนซอร์ส Android (AOSP)

เกี่ยวกับการจับคู่การทดสอบ

การจับคู่การทดสอบเป็นแนวทางที่อิงตาม Gerrit ซึ่งช่วยให้นักพัฒนาซอฟต์แวร์สร้างกฎการทดสอบก่อนส่งและหลังส่งได้โดยตรงในแผนผังซอร์สของ Android และปล่อยให้โครงสร้างพื้นฐานการทดสอบเป็นผู้กำหนดสาขาและอุปกรณ์ที่จะทดสอบ คำจำกัดความของการจับคู่การทดสอบคือไฟล์ JSON ที่ชื่อ TEST_MAPPING ซึ่งคุณวางไว้ในไดเรกทอรีต้นทางใดก็ได้

Atest สามารถใช้ไฟล์ TEST_MAPPING เพื่อเรียกใช้การทดสอบก่อนส่งในไดเรกทอรีที่เชื่อมโยง การจับคู่การทดสอบช่วยให้คุณเพิ่มชุดการทดสอบเดียวกันลงในการตรวจสอบก่อนส่งได้โดยมีการเปลี่ยนแปลงน้อยที่สุดภายในแผนผังซอร์สของ Android

ดูตัวอย่างต่อไปนี้

การจับคู่การทดสอบอาศัยชุดทดสอบ Trade Federation (TF) สำหรับการดำเนินการทดสอบและการรายงานผลลัพธ์

กำหนดกลุ่มทดสอบ

การจับคู่การทดสอบจะจัดกลุ่มการทดสอบด้วย กลุ่มทดสอบ ชื่อกลุ่มทดสอบจะเป็นสตริงใดก็ได้ ตัวอย่างเช่น presubmit อาจเป็นชื่อกลุ่มการทดสอบที่จะเรียกใช้เมื่อตรวจสอบการเปลี่ยนแปลง และ postsubmit อาจเป็นการทดสอบที่ใช้ตรวจสอบบิลด์หลังจากผสานการเปลี่ยนแปลงแล้ว

กฎสคริปต์บิลด์แพ็กเกจ

ชุดทดสอบ Trade Federation จะเรียกใช้โมดูลการทดสอบสำหรับบิลด์ที่กำหนดได้ก็ต่อเมื่อโมดูลเหล่านี้มีการตั้งค่า test_suites สำหรับ Soong หรือ LOCAL_COMPATIBILITY_SUITE สำหรับ Make เป็นชุดทดสอบ 1 ใน 2 ชุดทดสอบต่อไปนี้

  • general-tests ใช้สำหรับการทดสอบที่ไม่ขึ้นอยู่กับความสามารถเฉพาะของอุปกรณ์ (เช่น ฮาร์ดแวร์เฉพาะของผู้ให้บริการที่อุปกรณ์ส่วนใหญ่ไม่มี) การทดสอบส่วนใหญ่ควรอยู่ในชุดทดสอบ general-tests แม้ว่าจะเป็นการทดสอบที่เฉพาะเจาะจงกับ ABI หรือบิตเนส หรือฟีเจอร์ฮาร์ดแวร์ เช่น HWASan (มีเป้าหมาย test_suites แยกต่างหากสำหรับแต่ละ ABI) และแม้ว่าการทดสอบจะต้องเรียกใช้ในอุปกรณ์
  • device-tests ใช้สำหรับการทดสอบที่ขึ้นอยู่กับความสามารถเฉพาะของอุปกรณ์ โดยปกติแล้วการทดสอบเหล่านี้จะอยู่ใน vendor/ เฉพาะอุปกรณ์ หมายถึงความสามารถที่เฉพาะเจาะจงกับอุปกรณ์ หนึ่ง เครื่องเท่านั้น ดังนั้นจึงใช้ได้กับการทดสอบ JUnit รวมถึงการทดสอบ GTest (ซึ่งโดยปกติแล้วควรทำเครื่องหมายเป็น general-tests แม้ว่าจะเป็นการทดสอบที่เฉพาะเจาะจงกับ ABI)

ตัวอย่าง

Android.bp: test_suites: ["general-tests"],
Android.mk: LOCAL_COMPATIBILITY_SUITE := general-tests

กำหนดค่าการทดสอบให้เรียกใช้ในชุดโปรแกรมทดสอบ

การทดสอบจะเรียกใช้ภายในชุดโปรแกรมทดสอบได้ก็ต่อเมื่อการทดสอบมีลักษณะดังนี้

  • ต้องไม่มีผู้ให้บริการบิลด์
  • ต้องล้างข้อมูลหลังจากเสร็จสิ้น เช่น ลบไฟล์ชั่วคราวที่สร้างขึ้นระหว่างการทดสอบ
  • ต้องเปลี่ยนการตั้งค่าระบบเป็นค่าเริ่มต้นหรือค่าเดิม
  • ไม่ควรสันนิษฐานว่าอุปกรณ์อยู่ในสถานะใดสถานะหนึ่ง เช่น พร้อมใช้งานรูท การทดสอบส่วนใหญ่ไม่จำเป็นต้องมีสิทธิ์รูทในการเรียกใช้ หากการทดสอบต้องใช้ รูท การทดสอบควรระบุด้วย RootTargetPreparer ใน AndroidTest.xml ดังตัวอย่างต่อไปนี้

    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
    

สร้างไฟล์การจับคู่การทดสอบ

สำหรับไดเรกทอรีที่ต้องมีการครอบคลุมการทดสอบ ให้เพิ่มไฟล์ JSON TEST_MAPPING ที่คล้ายกับ ตัวอย่าง กฎเหล่านี้จะช่วยให้การทดสอบเรียกใช้ในการตรวจสอบก่อนส่งเมื่อมีการแตะไฟล์ในไดเรกทอรีนั้นหรือไดเรกทอรีย่อยใดก็ได้

ทำตามตัวอย่าง

นี่คือตัวอย่างไฟล์ TEST_MAPPING (อยู่ในรูปแบบ JSON แต่รองรับความคิดเห็น)

{
  "presubmit": [
    // JUnit test with options and file patterns.
    {
      "name": "CtsWindowManagerDeviceTestCases",
      "options": [
        {
          "include-annotation": "android.platform.test.annotations.RequiresDevice"
        }
      ],
      "file_patterns": ["(/|^)Window[^/]*\\.java", "(/|^)Activity[^/]*\\.java"]
    },
    // Device-side GTest with options.
    {
      "name" : "hello_world_test",
      "options": [
        {
          "native-test-flag": "\"servicename1 servicename2\""
        },
        {
          "native-test-timeout": "6000"
        }
      ]
    }
    // Host-side GTest.
    {
      "name" : "net_test_avrcp",
      "host" : true
    }
  ],
  "postsubmit": [
    {
      "name": "CtsDeqpTestCases",
      "options": [
        {
          // Use regex in include-filter which is supported in AndroidJUnitTest
          "include-filter": "dEQP-EGL.functional.color_clears.*"
        }
      ]
    }
  ],
  "imports": [
    {
      "path": "frameworks/base/services/core/java/com/android/server/am"
    }
  ]
}

ตั้งค่าแอตทริบิวต์

ใน ตัวอย่าง, presubmit และ postsubmit คือชื่อของกลุ่มทดสอบแต่ละกลุ่ม ดูข้อมูลเพิ่มเติมเกี่ยวกับกลุ่มทดสอบได้ที่กำหนดกลุ่มทดสอบ

คุณสามารถตั้งค่าชื่อโมดูลการทดสอบหรือชื่อการทดสอบการผสานรวม Trade Federation (เส้นทางทรัพยากรไปยังไฟล์ XML การทดสอบ เช่น uiautomator/uiautomator-demo) ในค่าของแอตทริบิวต์ name โปรดทราบว่าช่อง name จะใช้ name ของคลาสหรือ name ของเมธอดการทดสอบไม่ได้ หากต้องการจำกัดการทดสอบที่จะเรียกใช้ ให้ใช้ตัวเลือกต่างๆ เช่น include-filter ดูตัวอย่างการใช้งาน include-filter

การตั้งค่า host ของการทดสอบจะระบุว่าการทดสอบเป็นการทดสอบที่ไม่มีอุปกรณ์และเรียกใช้ในโฮสต์หรือไม่ ค่าเริ่มต้นคือ false ซึ่งหมายความว่าการทดสอบต้องใช้อุปกรณ์ในการเรียกใช้ ประเภทการทดสอบที่รองรับคือ HostGTest สำหรับ ไบนารี GTest และ HostTest สำหรับการทดสอบ JUnit

แอตทริบิวต์ file_patterns ช่วยให้คุณตั้งค่ารายการสตริงนิพจน์ทั่วไปสำหรับการจับคู่เส้นทางแบบสัมพัทธ์ของไฟล์ซอร์สโค้ด (เทียบกับไดเรกทอรีที่มีไฟล์ TEST_MAPPING) ในตัวอย่าง, การทดสอบ CtsWindowManagerDeviceTestCases จะเรียกใช้ในการทดสอบก่อนส่งก็ต่อเมื่อไฟล์ Java ขึ้นต้นด้วย Window หรือ Activity ซึ่งอยู่ในไดเรกทอรีเดียวกับ TEST_MAPPING ไฟล์ หรือไดเรกทอรีย่อยใดก็ได้ ต้องหลีกเลี่ยงการใช้แบ็กสแลช (\) เนื่องจากอยู่ในไฟล์ JSON

นำเข้าไฟล์ TEST_MAPPING

แอตทริบิวต์ imports ช่วยให้คุณรวมการทดสอบในไฟล์ TEST_MAPPING อื่นๆ ได้โดยไม่ต้องคัดลอกเนื้อหา ระบบจะรวมไฟล์ TEST_MAPPING ในไดเรกทอรีหลักของเส้นทางที่นำเข้าด้วย TEST_MAPPING อนุญาตการนำเข้าแบบซ้อน ซึ่งหมายความว่าไฟล์ที่นำเข้าสามารถนำเข้าไฟล์ TEST_MAPPING อื่นๆ ได้ และการจับคู่การทดสอบสามารถผสานการทดสอบที่รวมไว้ได้

TEST_MAPPING รองรับการนำเข้าระดับรูทและระดับกลุ่ม

  • การนำเข้าระดับรูท: ระบุที่ระดับบนสุดของไฟล์ TEST_MAPPING (นอกกลุ่มทดสอบ) การนำเข้าระดับรูทจะนำเข้าไฟล์ TEST_MAPPING เป้าหมายทั้งหมด (และไดเรกทอรีหลัก) ราวกับว่าเขียนไว้ในเส้นทางที่จะนำเข้า คำจำกัดความของกลุ่มทดสอบทั้งหมดในไฟล์ที่นำเข้า (เช่น presubmit, postsubmit) จะผสานเข้ากับกลุ่มทดสอบที่เกี่ยวข้องของไฟล์ที่นำเข้า
  • การนำเข้าระดับกลุ่ม: ระบุไว้ในกลุ่มทดสอบที่เฉพาะเจาะจง (เช่น presubmit หรือ postsubmit) การนำเข้าระดับกลุ่มจะมีขอบเขตเฉพาะกลุ่มทดสอบนั้นอย่างเคร่งครัด ซึ่งหมายความว่าจะมีการนำเข้าเฉพาะการทดสอบที่กำหนดไว้ในกลุ่มที่เฉพาะเจาะจงนั้นภายในไฟล์ TEST_MAPPING เป้าหมาย ระบบจะข้ามกลุ่มทดสอบอื่นๆ ทั้งหมดในไฟล์เป้าหมาย

การนำเข้าระดับกลุ่มช่วยให้ควบคุมการดำเนินการทดสอบได้อย่างละเอียด ตัวอย่างเช่น คุณสามารถนำเข้าการทดสอบสำหรับการทดสอบก่อนส่งโดยเฉพาะได้โดยไม่ต้องดึงการทดสอบหลังส่งขนาดใหญ่จากไดเรกทอรีที่นำเข้า

ตัวอย่างการนำเข้าระดับรูท

{
  "imports": [
    {
      "path": "frameworks/base/services/core"
    }
  ],
  "presubmit": [
    {
      "name": "MyTestModule"
    }
  ]
}

ตัวอย่างการนำเข้าระดับกลุ่ม

{
  "presubmit": [
    {
      "name": "MyTestModule"
    },
    {
      "imports": [
        {
          "path": "frameworks/base/services/core"
        }
      ]
    }
  ],
  "postsubmit": [
    {
      "imports": [
        {
          "path": "frameworks/base/services/accessibility"
        }
      ]
    }
  ]
}

แอตทริบิวต์ options มีตัวเลือกบรรทัดคำสั่ง Tradefed เพิ่มเติม

หากต้องการดูรายการตัวเลือกทั้งหมดที่ใช้ได้สำหรับการทดสอบที่กำหนด ให้เรียกใช้คำสั่งต่อไปนี้

tradefed.sh run commandAndExit [test_module] --help

ดูรายละเอียดเพิ่มเติมเกี่ยวกับวิธีทำงานของตัวเลือกได้ที่ การจัดการตัวเลือกใน Tradefed

การตรวจสอบความถูกต้องของ TEST_MAPPING

เมื่อส่งการเปลี่ยนแปลงที่แก้ไขไฟล์ TEST_MAPPING การตรวจสอบก่อนส่งจะทำงานเพื่อให้แน่ใจว่าถูกต้อง

  • การตรวจสอบความถูกต้องของรูปแบบไฟล์: ช่วยให้มั่นใจว่านิพจน์ทั่วไปทั้งหมดใน file_patterns ตรงกับไฟล์อย่างน้อย 1 ไฟล์ในที่เก็บ รูปแบบที่ล้าสมัยซึ่งไม่ตรงกับไฟล์ใดๆ จะทำให้การตรวจสอบไม่สำเร็จ
  • การตรวจสอบความถูกต้องในเวลาบิลด์: เลื่อนระดับคำเตือนการตรวจสอบความถูกต้องในเวลาบิลด์ที่บิลด์รวบรวมไว้เป็นข้อผิดพลาดที่บล็อกในการทดสอบก่อนส่งสำหรับสาขาหลัก คำเตือนที่พบบ่อย ได้แก่
    • โมดูลที่ไม่มีอยู่: การอ้างอิงชื่อโมดูลการทดสอบที่ไม่มีอยู่ในฐานของโค้ด เช่น เมื่อชื่อมีข้อผิดพลาดในการพิมพ์
    • การนำเข้าที่ไม่ถูกต้อง: เส้นทางการอ้างอิงใน imports ที่ไม่มีอยู่หรือไม่มีไฟล์ TEST_MAPPING
    • ปัญหาเกี่ยวกับสคีมา: การใช้คีย์ที่ไม่รองรับหรือโครงสร้างที่ผิดรูปแบบในการกำหนดค่า JSON

เรียกใช้การทดสอบด้วย Atest

วิธีดำเนินการตามกฎการทดสอบก่อนส่งในเครื่อง

  1. ไปที่ไดเรกทอรีที่มีไฟล์ TEST_MAPPING
  2. เรียกใช้คำสั่งต่อไปนี้

    atest
    

ระบบจะเรียกใช้การทดสอบก่อนส่งทั้งหมดที่กำหนดค่าไว้ในไฟล์ TEST_MAPPING ของไดเรกทอรีปัจจุบันและไดเรกทอรีหลัก Atest จะค้นหาและเรียกใช้การทดสอบ 2 รายการสำหรับการทดสอบก่อนส่ง (A และ B)

นี่เป็นวิธีที่ตรงไปตรงมาที่สุดในการเรียกใช้การทดสอบก่อนส่งในไฟล์ TEST_MAPPING ในไดเรกทอรีการทำงานปัจจุบัน (CWD) และไดเรกทอรีหลัก Atest จะค้นหาและใช้ไฟล์ TEST_MAPPING ใน CWD และไดเรกทอรีหลักทั้งหมด

จัดโครงสร้างซอร์สโค้ด

ตัวอย่างนี้แสดงวิธีกำหนดค่าไฟล์ TEST_MAPPING ในแผนผังซอร์ส

src
├── project_1
│   └── TEST_MAPPING
├── project_2
│   └── TEST_MAPPING
└── TEST_MAPPING

เนื้อหาของ src/TEST_MAPPING

{
  "presubmit": [
    {
      "name": "A"
    }
  ]
}

เนื้อหาของ src/project_1/TEST_MAPPING

{
  "presubmit": [
    {
      "name": "B"
    }
  ],
  "postsubmit": [
    {
      "name": "C"
    }
  ],
  "other_group": [
    {
      "name": "X"
    }
  ]}

เนื้อหาของ src/project_2/TEST_MAPPING

{
  "presubmit": [
    {
      "name": "D"
    }
  ],
  "import": [
    {
      "path": "src/project_1"
    }
  ]}

ระบุไดเรกทอรีเป้าหมาย

คุณสามารถระบุไดเรกทอรีเป้าหมายเพื่อเรียกใช้การทดสอบในไฟล์ TEST_MAPPING ในไดเรกทอรีนั้นได้ คำสั่งต่อไปนี้จะเรียกใช้การทดสอบ 2 รายการ (A, B)

atest --test-mapping src/project_1

เรียกใช้กฎการทดสอบหลังส่ง

นอกจากนี้ คุณยังใช้คำสั่งนี้เพื่อเรียกใช้กฎการทดสอบหลังส่งที่กำหนดไว้ใน TEST_MAPPING ใน src_path (ค่าเริ่มต้นคือ CWD) และไดเรกทอรีหลักได้ด้วย

atest [--test-mapping] [src_path]:postsubmit

เรียกใช้เฉพาะการทดสอบที่ไม่ต้องใช้อุปกรณ์

คุณสามารถใช้ตัวเลือก --host สำหรับ Atest เพื่อเรียกใช้เฉพาะการทดสอบที่กำหนดค่ากับโฮสต์ที่ไม่ต้องใช้อุปกรณ์ หากไม่มีตัวเลือกนี้ Atest จะเรียกใช้การทดสอบทั้ง 2 รายการ ได้แก่ การทดสอบที่ต้องใช้อุปกรณ์และการทดสอบที่เรียกใช้ในโฮสต์ที่ไม่ต้องใช้อุปกรณ์ ระบบจะเรียกใช้การทดสอบในชุดทดสอบ 2 ชุดแยกกัน

atest [--test-mapping] --host

ระบุกลุ่มทดสอบ

คุณสามารถระบุกลุ่มทดสอบในคำสั่ง Atest ได้ คำสั่งต่อไปนี้จะเรียกใช้การทดสอบ postsubmit ทั้งหมดที่เกี่ยวข้องกับไฟล์ในไดเรกทอรี src/project_1 ซึ่งมีการทดสอบเพียงรายการเดียว (C)

หรือคุณจะใช้ :all เพื่อเรียกใช้การทดสอบทั้งหมดโดยไม่คำนึงถึงกลุ่มก็ได้ คำสั่งต่อไปนี้จะเรียกใช้การทดสอบ 4 รายการ (A, B, C, X)

atest --test-mapping src/project_1:all

รวมไดเรกทอรีย่อย

โดยค่าเริ่มต้น การเรียกใช้การทดสอบใน TEST_MAPPING ด้วย Atest จะเรียกใช้เฉพาะการทดสอบก่อนส่งที่กำหนดค่าไว้ในไฟล์ TEST_MAPPING ใน CWD (หรือไดเรกทอรีที่ระบุ) และไดเรกทอรีหลัก หากต้องการเรียกใช้การทดสอบในไฟล์ TEST_MAPPING ทั้งหมดในไดเรกทอรีย่อย ให้ใช้ตัวเลือก --include-subdir เพื่อบังคับให้ Atest รวมการทดสอบเหล่านั้นด้วย

atest --include-subdir

หากไม่มีตัวเลือก --include-subdir Atest จะเรียกใช้เฉพาะการทดสอบ A หากมีตัวเลือก --include-subdir Atest จะเรียกใช้การทดสอบ 2 รายการ (A, B)

รองรับความคิดเห็นระดับบรรทัด

คุณสามารถเพิ่มความคิดเห็นรูปแบบ // ระดับบรรทัดเพื่อเพิ่มรายละเอียดไฟล์ TEST_MAPPING ด้วยคำอธิบายของการตั้งค่าที่ตามมา ATest และ Trade Federation จะประมวลผลล่วงหน้า TEST_MAPPING เป็นรูปแบบ JSON ที่ถูกต้องโดยไม่มีความคิดเห็น ระบบรองรับเฉพาะความคิดเห็นรูปแบบ // ระดับบรรทัดเพื่อให้ไฟล์ JSON สะอาด

ตัวอย่าง

{
  // For presubmit test group.
  "presubmit": [
    {
      // Run test on module A.
      "name": "A"
    }
  ]
}