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ẽ được khởi động lại bằng mã đo lường được chèn và bắt đầu thực thi. Một ngoại lệ là gói mục tiêu ở đây không được là chính khung ứng dụng Android, chẳng hạn như gói android, vì việc này dẫn đến tình huống nghịch lý là cần phải khởi động lại khung Android, là yếu tố hỗ trợ các chức năng của hệ thống, bao gồm cả chính hoạt động đo lường.

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

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

  • Cần có các hoạt động gói để 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.

Loại kiểm thử đo lường này đôi khi được gọi là tự đo lường. Sau đâ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 tại gói ứng dụng kiểm thử của riêng nó. Hướng dẫn này sử dụng làm ví dụ:

Bạn nên duyệt qua mã trước để có ấn tượng rõ ràng 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 đã thiết lập về các vị trí cần kiểm tra trong mã và các vị trí cần 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ẻ tệp với các nhóm khác nhưng có thư mục con riêng chứa mã nguồn thành phần.

Giả sử vị trí gốc của nguồn thành phần là tại <component source root>, thì hầu hết các thành phần đều có thư mục srctests bên dưới, và một số các 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 thử nghiệm "AndroidTest.xml".

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

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 trong tests do nhu cầu phải đóng gói nhiều bộ thử nghiệm vào từng tệp APK. và trong trường hợp này, bạn cần tạo một thư mục con mới trong tests.

Bất kể cấu trúc nào, bạn cũng sẽ điền sẵn 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 ở phần sau của tài liệu này.

Tệp kê khai

Giống như với dự án ứng dụng, mỗi mô-đun kiểm thử đo lường yêu cầu tệp kê khai có tên là AndroidManifest.xml. Để tự động đưa tệp này vào bằng tệp makefile 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ử.

Nếu bạn chưa hiểu rõ về tệp AndroidManifest.xml, hãy tham khảo Tổng quan về tệp kê khai ứng dụng

Dưới đâ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 cụ thể trong 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ị duy nhất mà khung ứng dụng Android sử dụng để xác định ứng dụng (hoặc trong ngữ cảnh này: ứng dụng thử nghiệm 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 đó.

Ngoài ra, thuộc tính package này giống với thuộc tính ComponentName#getPackageName() cũng như cách bạn sẽ sử dụng để tương tác với pm phụ sử dụng adb shell.

Lưu ý rằng mặc dù tên gói thường theo cùng một kiểu là tên gói Java, nhưng thực sự nó không có nhiều tác dụng. 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ó tên gói bất kỳ, mặc dù mặt khác, bạn có thể chọn đơn giản và đặt 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"

Thao tác 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 quyền cùng một mã nhận dạng người dùng (tức là nhận dạng trong thời gian chạy) làm nền tảng cốt lõi. Lưu ý rằng phụ thuộc vào tệp APK được ký bằng cùng một chứng chỉ với nền tảng cốt lõi (xem LOCAL_CERTIFICATE trong phần trước), tuy nhiên, chúng khác nhau các khái niệm:

  • 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 danh tính người dùng system của phương thức 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à tách gói khỏ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 đó, cần có thêm các mục nhập đường dẫn lớp 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 targetPackage ở đây được khai báo giống với Thuộc tính package được khai báo trong thẻ manifest của tệp này. Như đã đề cập trong thông tin cơ bản về kiểm thử, danh mục kiểm thử đo lường này thường dành cho việc thử nghiệm API khung, vì vậy, nó không có ý nghĩa lắm đối với để chúng có một gói ứng dụng được nhắm mục tiêu cụ thể, khác sau đó chính nó.

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 để chuyển hướng hệ thống xây dựng với siêu dữ liệu mô-đun, phần phụ thuộc thời gian biên dịch và đóng gói hướng dẫn. 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 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 cấu hình kiểm thử cho phần khai thác kiểm thử của Android, Liên đoàn Thương mại.

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à để cung cấp lớp kiểm thử. Xem ví dụ tại /platform_testing/tests/example/Instrumentation/AndroidTest.xml.

Để thuận tiện cho bạn, tôi xin cung cấp thông tin tổng quan nhanh:

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

Thao tác này sẽ yêu cầu Trade Federation cài đặt HelloWorldTests.apk vào mục tiêu bằng cách sử dụng target_preparer cụ thể. Có nhiều người chuẩn bị mục tiêu dành cho các nhà phát triển trong Liên đoàn Thương mại và có thể sử dụng các mã này để đảm bảo thiết bị được thiết lập đúng cách trước khi 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>

Thao tác này chỉ định lớp kiểm thử Liên kết Thương mại sẽ sử dụng để thực thi phép kiểm thử và truyền trong gói trên thiết bị cần được thực thi và 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 Kiểm thử cấu hình mô-đun.

Các tính năng của 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 và thay đổi về cửa sổ mẫu chứa một số lớp rất cơ bản việc sử dụng các tính năng của Google. 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 thường hữu ích.

@RunWith(JUnit4.class)
public class HelloWorldTest {

Một điểm khác biệt đáng kể trong JUnit4 là các bài kiểm thử không còn bắt buộc phải kế thừa từ một lớp kiểm thử cơ sở chung; thay vào đó, bạn viết các bài 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ố quy tắc thiết lập và quy tắc ràng buộc nhất định của kiểm thử. Ngang bằng trong ví dụ này, chúng ta sẽ hướng dẫn chạy lớp nà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() {
    ...

Các chú giải @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 thử nghiệm và chia nhỏ sau thử nghiệm. Tương tự, @BeforeClass và Chú giải @AfterClass được JUnit4 sử dụng trên các phương thức để thực hiện việc thiết lập trước khi thực thi tất cả các bài kiểm thử trong một lớp kiểm thử rồi chia nhỏ sau đó. Xin lưu ý rằng các phương thức thiết lập và huỷ thiết lập trong phạm vi lớp phải là tĩnh. Đối với phương pháp kiểm thử, không giống như trong phiên bản trước của JUnit, họ không cần bắt đầu tên phương thức nữa bằng test. Thay vào đó, bạn phải chú thích mỗi đối tượng này bằng @Test. Như thường lệ, phương pháp 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ó trong ví dụ cơ bản về Hello world (Xin chào thế giới), nhưng điều này khá phổ biến đối với Bài kiểm thử Android để yêu cầu quyền truy cập vào thực thể Instrumentation: đây là API chính giao diện cung cấp quyền truy cập vào ngữ cảnh ứng dụng, vòng đời hoạt động kiểm thử liên quan 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 phải lấy thực thể Instrumentation thông qua InstrumentationTestCase#getInstrumentation() nữa. Thay vào đó, trình chạy kiểm thử mới sẽ quản lý thực thể này thông qua InstrumentationRegistry, nơi lưu trữ chế độ thiết lập môi trường và ngữ cảnh do khung đo lường tạo.

Để 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()

Tạo bản 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 tùy chỉnh nặng hơn, hãy làm theo hướng dẫn đo lường.