Ví dụ về kiểm thử tự đo lường

Khi một kiểm thử đo lường bắt đầu, gói mục tiêu của kiểm thử đó sẽ khởi động lại với mã đo lường được chèn và khởi chạy để thực thi. Một trường hợp ngoại lệ là gói mục tiêu ở đây không thể là chính khung ứng dụng Android, chẳng hạn như gói android, vì việc này sẽ dẫn đến tình huống nghịch lý là khung Android sẽ cần khởi động lại, đây là thứ hỗ trợ các chức năng của hệ thống, bao gồm cả chính khả năng đo lường.

Điều này có nghĩa là một kiểm thử đo lường không thể tự chèn vào khung Android, hay còn gọi là máy chủ hệ thống, để thực thi. Để kiểm thử khung Android , mã kiểm thử chỉ có thể gọi các bề mặt API công khai hoặc những bề mặt được hiển thị bằng Ngôn ngữ định nghĩa giao diện Android AIDL có trong cây nguồn nền tảng. Đối với danh mục kiểm thử này, việc nhắm mục tiêu vào bất kỳ gói cụ thể nào đều không có ý nghĩa. Do đó, theo thông lệ, các khả năng đo lường như vậy sẽ được khai báo để nhắm mục tiêu vào gói ứng dụng kiểm thử riêng, như được xác định trong thẻ <manifest> riêng của AndroidManifest.xml.

Tuỳ thuộc vào các yêu cầu, gói ứng dụng kiểm thử trong danh mục này cũng có thể:

  • Gói các hoạt động cần thiết để kiểm thử.
  • Chia sẻ mã nhận dạng người dùng với hệ thống.
  • Được ký bằng khoá nền tảng.
  • Được biên dịch dựa trên nguồn khung thay vì SDK công khai.

Danh mục kiểm thử đo lường này đôi khi được gọi là tự đo lường. Dưới đây là một số ví dụ về kiểm thử tự đo lường trong nguồn nền tảng:

Ví dụ được đề cập ở đây là viết một kiểm thử đo lường mới với gói mục tiêu được đặt ở gói ứng dụng kiểm thử riêng. Hướng dẫn này sử dụng kiểm thử sau đây làm ví dụ:

Bạn nên duyệt qua mã trước để có ấn tượng sơ bộ trước khi tiếp tục.

Quyết định vị trí nguồn

Thông thường, nhóm của bạn sẽ đã có một mẫu vị trí đã thiết lập để kiểm tra mã và vị trí để thêm kiểm thử. Hầu hết các nhóm đều sở hữu một kho lưu trữ git duy nhất hoặc chia sẻ một kho lưu trữ với các nhóm khác nhưng có một thư mục con riêng chứa mã nguồn thành phần.

Giả sử vị trí gốc cho nguồn thành phần của bạn là tại <component source root>, hầu hết các thành phần đều có thư mục srctests bên dưới, cũng như một số tệp bổ sung như Android.mk (hoặc được chia thành các tệp .mk bổ sung), tệp kê khai AndroidManifest.xml, và tệp cấu hình kiểm thử 'AndroidTest.xml'.

Vì bạn đang thêm một kiểm thử hoàn toàn mới, nên có thể bạn sẽ cần tạo thư mục tests bên cạnh src thành phần và điền nội dung vào đó.

Trong một số trường hợp, nhóm của bạn có thể có thêm cấu trúc thư mục bên dưới tests do cần đóng gói các bộ kiểm thử khác nhau vào các tệp apk riêng lẻ. Và trong trường hợp này, bạn sẽ cần tạo một thư mục con mới bên dưới tests.

Bất kể cấu trúc nào, bạn sẽ kết thúc việc điền tệp vào thư mục tests hoặc thư mục con mới tạo bằng các tệp tương tự như trong thư mục instrumentation trong thay đổi gerrit mẫu. Thông tin chi tiết về từng tệp sẽ được giải thích sau trong tài liệu này.

Tệp kê khai

Giống như dự án ứng dụng, mỗi mô-đun kiểm thử đo lường đều yêu cầu một tệp kê khai có tên là AndroidManifest.xml. Để tự động đưa tệp này vào bằng cách sử dụng tệp makefile cốt lõi BUILD_PACKAGE, hãy cung cấp tệp này bên cạnh tệp Android.mk cho mô-đun kiểm thử của bạn.

Nếu bạn chưa quen với tệp AndroidManifest.xml, hãy tham khảo phần Tổng quan về tệp kê khai ứng dụng

Sau đây là tệp AndroidManifest.xml mẫu:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  android:sharedUserId="android.uid.system"
  package="android.test.example.helloworld" >

    <application>
       <uses-library android:name="android.test.runner"/>
    </application>

    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                     android:targetPackage="android.test.example.helloworld"
                     android:label="Hello World Test"/>

</manifest>

Một số nhận xét chọn lọc về tệp kê khai:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.test.example.helloworld" >

Thuộc tính package là tên gói ứng dụng: đây là giá trị nhận dạng duy nhất mà khung ứng dụng Android sử dụng để xác định một ứng dụng (hoặc trong bối cảnh này: ứng dụng kiểm thử của bạn). Mỗi người dùng trong hệ thống chỉ có thể cài đặt một ứng dụng có tên gói đó.

Hơn nữa, thuộc tính package này giống với những gì ComponentName#getPackageName() trả về, cũng như giống với những gì bạn sẽ sử dụng để tương tác với nhiều lệnh con pm sub sử dụng adb shell.

Xin lưu ý rằng mặc dù tên gói thường có cùng kiểu với tên gói Java, nhưng thực ra tên gói này có rất ít điểm chung với tên gói Java. Nói cách khác, gói ứng dụng (hoặc kiểm thử) của bạn có thể chứa các lớp có bất kỳ tên gói nào, mặc dù mặt khác, bạn có thể chọn sự đơn giản và có tên gói Java cấp cao nhất trong ứng dụng hoặc kiểm thử giống với tên gói ứng dụng.

android:sharedUserId="android.uid.system"

Điều này khai báo rằng tại thời điểm cài đặt, tệp APK này sẽ được cấp cùng một mã nhận dạng người dùng, tức là giá trị nhận dạng thời gian chạy, như nền tảng cốt lõi. Xin lưu ý rằng điều này phụ thuộc vào việc tệp apk được ký bằng cùng một chứng chỉ như nền tảng cốt lõi (xem LOCAL_CERTIFICATE trong phần trước), nhưng chúng là các khái niệm khác nhau:

  • một số quyền hoặc API được bảo vệ bằng chữ ký, yêu cầu cùng một chứng chỉ ký
  • một số quyền hoặc API yêu cầu giá trị nhận dạng người dùng system của trình gọi, yêu cầu gói gọi chia sẻ mã nhận dạng người dùng với system, nếu đó là một gói riêng biệt với chính nền tảng cốt lõi
<uses-library android:name="android.test.runner" />

Điều này là bắt buộc đối với tất cả các kiểm thử đo lường vì các lớp liên quan được đóng gói trong một tệp thư viện JAR khung riêng biệt, do đó, yêu cầu các mục classpath bổ sung khi gói kiểm thử được khung ứng dụng gọi.

android:targetPackage="android.test.example.helloworld"

Bạn có thể nhận thấy rằng targetPackage ở đây được khai báo giống như thuộc tính package được khai báo trong thẻ manifest của tệp này. Như đã đề cập trong kiến thức cơ bản về kiểm thử, danh mục kiểm thử đo lường này thường dành cho các API khung kiểm thử, vì vậy, việc chúng có một gói ứng dụng được nhắm mục tiêu cụ thể, ngoài chính chúng, là không có ý nghĩa.

Tệp cấu hình đơn giản

Mỗi mô-đun kiểm thử mới phải có một tệp cấu hình để hướng hệ thống xây dựng bằng siêu dữ liệu mô-đun, các phần phụ thuộc thời gian biên dịch và hướng dẫn đóng gói ứng dụng. Trong hầu hết các trường hợp, tuỳ chọn tệp Blueprint dựa trên Soong là đủ. Để biết thông tin chi tiết, hãy xem phần Cấu hình kiểm thử đơn giản.

Tệp cấu hình phức tạp

Đối với những trường hợp phức tạp hơn này, bạn cũng cần viết tệp cấu hình kiểm thử cho bộ kiểm thử của Android, Trade Federation.

Cấu hình kiểm thử có thể chỉ định các tuỳ chọn thiết lập thiết bị đặc biệt và các đối số mặc định để cung cấp cho lớp kiểm thử. Hãy xem ví dụ tại /platform_testing/tests/example/instrumentation/AndroidTest.xml.

Ảnh chụp nhanh được đưa vào đây để thuận tiện:

<configuration description="Runs sample instrumentation test.">
  <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
  <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
    <option name="test-file-name" value="HelloWorldTests.apk"/>
  </target_preparer>
  <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
  <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
  <option name="test-suite-tag" value="apct"/>
  <option name="test-tag" value="SampleInstrumentationTest"/>

  <test class="com.android.tradefed.testtype.AndroidJUnitTest">
    <option name="package" value="android.test.example.helloworld"/>
    <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
  </test>
</configuration>

Một số nhận xét chọn lọc về tệp cấu hình kiểm thử:

<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
  <option name="test-file-name" value="HelloWorldTests.apk"/>
</target_preparer>

Điều này cho Trade Federation biết cách cài đặt HelloWorldTests.apk lên thiết bị mục tiêu bằng cách sử dụng target_preparer được chỉ định. Có nhiều trình chuẩn bị mục tiêu dành cho nhà phát triển trong Trade Federation và những trình này có thể được dùng để đảm bảo thiết bị được thiết lập đúng cách trước khi phiên chạy thử nghiệm.

<test class="com.android.tradefed.testtype.AndroidJUnitTest">
  <option name="package" value="android.test.example.helloworld"/>
  <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>

Điều này chỉ định lớp kiểm thử Trade Federation để sử dụng nhằm thực thi kiểm thử và chuyển gói trên thiết bị sẽ được thực thi và khung trình chạy kiểm thử, trong trường hợp này là JUnit.

Để biết thêm thông tin, hãy xem Cấu hình mô-đun kiểm thử.

Tính năng JUnit4

Việc sử dụng thư viện android-support-test làm trình chạy kiểm thử cho phép áp dụng các lớp kiểm thử kiểu JUnit4 mới và thay đổi gerrit mẫu chứa một số cách sử dụng rất cơ bản các tính năng của thư viện này. Hãy xem ví dụ tại /platform_testing/tests/example/instrumentation/src/android/test/example/helloworld/HelloWorldTest.java.

Mặc dù các mẫu kiểm thử thường dành riêng cho các nhóm thành phần, nhưng có một số mẫu sử dụng hữu ích chung.

@RunWith(JUnit4.class)
public class HelloWorldTest {

Một điểm khác biệt đáng kể trong JUnit4 là các kiểm thử không còn cần kế thừa từ một lớp kiểm thử cơ sở chung; thay vào đó, bạn viết các kiểm thử trong các lớp Java thuần tuý và sử dụng chú thích để cho biết một số thiết lập và ràng buộc kiểm thử. Trong ví dụ này, chúng tôi đang hướng dẫn rằng lớp này sẽ được chạy dưới dạng kiểm thử JUnit4.

    @BeforeClass
    public static void beforeClass() {
    ...
    @AfterClass
    public static void afterClass() {
    ...
    @Before
    public void before() {
    ...
    @After
    public void after() {
    ...
    @Test
    @SmallTest
    public void testHelloWorld() {
    ...

Chú thích @Before@After được JUnit4 sử dụng trên các phương thức để thực hiện thiết lập trước kiểm thử và huỷ sau kiểm thử. Tương tự, chú thích @BeforeClass@AfterClass được JUnit4 sử dụng trên các phương thức để thực hiện thiết lập trước khi thực thi tất cả các kiểm thử trong một lớp kiểm thử và huỷ sau đó. Xin lưu ý rằng các phương thức thiết lập và huỷ ở phạm vi lớp phải là tĩnh. Đối với các phương thức kiểm thử, không giống như trong phiên bản JUnit trước, chúng không còn cần bắt đầu tên phương thức bằng test, thay vào đó, mỗi phương thức phải được chú thích bằng @Test. Như thường lệ, các phương thức kiểm thử phải là công khai, không khai báo giá trị trả về, không nhận tham số và có thể gửi ngoại lệ.

Quyền truy cập vào lớp đo lường

Mặc dù không được đề cập trong ví dụ cơ bản về xin chào mọi người, nhưng khá phổ biến đối với một kiểm thử Android khi yêu cầu quyền truy cập vào thực thể Instrumentation: đây là giao diện API cốt lõi cung cấp quyền truy cập vào ngữ cảnh ứng dụng, các API kiểm thử liên quan đến vòng đời của activity và nhiều API khác.

Vì các kiểm thử JUnit4 không còn yêu cầu lớp cơ sở chung, nên bạn không còn cần lấy thực thể Instrumentation thông qua InstrumentationTestCase#getInstrumentation(), thay vào đó, trình chạy kiểm thử mới quản lý thực thể này thông qua InstrumentationRegistry nơi lưu trữ thiết lập theo ngữ cảnh và môi trường do khung đo lường tạo được lưu trữ.

Để truy cập vào thực thể của lớp Instrumentation, bạn chỉ cần gọi phương thức tĩnh getInstrumentation() trên lớp InstrumentationRegistry:

Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation()

Xây dựng và kiểm thử cục bộ

Đối với các trường hợp sử dụng phổ biến nhất, hãy sử dụng Atest.

Đối với các trường hợp phức tạp hơn yêu cầu tuỳ chỉnh nhiều hơn, hãy làm theo các hướng dẫn đo lường.