Làm cách nào để bạn kiểm tra một ứng dụng Android trên nhiều Hoạt động?


80

Chúng tôi đang xây dựng một ứng dụng Android phức tạp bao gồm nhiều màn hình và quy trình làm việc trải rộng trên nhiều Hoạt động. Quy trình làm việc của chúng tôi tương tự như những gì bạn có thể thấy trên máy ATM của Ngân hàng, chẳng hạn, có một Activityđăng nhập trong đó chuyển sang menu chính Activitycó thể chuyển sang các hoạt động khác dựa trên lựa chọn của người dùng.

Vì chúng tôi có rất nhiều quy trình công việc, nên chúng tôi cần tạo các thử nghiệm tự động trải dài nhiều hoạt động để chúng tôi có thể kiểm tra quy trình làm việc từ đầu đến cuối. Ví dụ: sử dụng ví dụ ATM, chúng tôi muốn nhập mã PIN hợp lệ, xác minh sẽ đưa chúng tôi đến menu chính, chọn rút tiền mặt, xác minh rằng chúng tôi đang ở trên màn hình rút tiền, v.v., v.v. và cuối cùng tìm thấy chính mình trở lại menu chính hoặc "đăng xuất".

Chúng tôi đã đùa giỡn với các API thử nghiệm đi kèm với Android (ví dụ ActivityInstrumentationTestCase2) và cả Positron , nhưng dường như không có khả năng thử nghiệm vượt quá giới hạn của một ứng dụng duy nhất Activityvà trong khi chúng tôi có thể tìm thấy một số tiện ích trong các công cụ này cho một số thử nghiệm đơn vị, họ đã thắng 'không đáp ứng nhu cầu của chúng tôi về các tình huống thử nghiệm cắt qua nhiều Hoạt động.

Chúng tôi sẵn sàng sử dụng khung công tác xUnit, tập lệnh, trình ghi / phát lại GUI, v.v. và sẽ đánh giá cao mọi lời khuyên.


2
Tính đến Android 4.1, bây giờ có một khuôn khổ kiểm tra mới từ Android mà cho phép thử nghiệm trên các hoạt động và thực sự là toàn bộ hệ thống: developer.android.com/tools/testing/testing_ui.html
Christopher Orr

1
Robotium cũng sẽ phù hợp với nhu cầu này và chỉ trong một vài dòng.
Dori

Câu trả lời:


65

Tôi cảm thấy hơi khó xử khi trả lời câu hỏi về tiền thưởng của chính mình, nhưng đây là ...

Tôi đã tìm kiếm nhiều và thấp về điều này và không thể tin rằng không có câu trả lời được công bố ở bất cứ đâu. Tôi đã đến rất gần. Tôi chắc chắn có thể chạy các thử nghiệm kéo dài các hoạt động ngay bây giờ, nhưng việc triển khai của tôi dường như có một số vấn đề về thời gian mà các thử nghiệm không phải lúc nào cũng vượt qua một cách đáng tin cậy. Đây là ví dụ duy nhất mà tôi biết về việc kiểm tra thành công nhiều hoạt động. Hy vọng rằng việc trích xuất và ẩn danh của tôi không gây ra lỗi. Đây là một thử nghiệm đơn giản trong đó tôi nhập tên người dùng và mật khẩu vào một hoạt động đăng nhập, sau đó quan sát thấy một thông báo chào mừng thích hợp được hiển thị trên một hoạt động "chào mừng" khác:

package com.mycompany;

import android.app.*;
import android.content.*;
import android.test.*;
import android.test.suitebuilder.annotation.*;
import android.util.*;
import android.view.*;
import android.widget.*;

import static org.hamcrest.core.Is.*;
import static org.hamcrest.core.IsNull.*;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.*;
import static com.mycompany.R.id.*;

public class LoginTests extends InstrumentationTestCase {

   @MediumTest
   public void testAValidUserCanLogIn() {

      Instrumentation instrumentation = getInstrumentation();

      // Register we are interested in the authentication activiry...
      Instrumentation.ActivityMonitor monitor = instrumentation.addMonitor(AuthenticateActivity.class.getName(), null, false);

      // Start the authentication activity as the first activity...
      Intent intent = new Intent(Intent.ACTION_MAIN);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      intent.setClassName(instrumentation.getTargetContext(), AuthenticateActivity.class.getName());
      instrumentation.startActivitySync(intent);

      // Wait for it to start...
      Activity currentActivity = getInstrumentation().waitForMonitorWithTimeout(monitor, 5);
      assertThat(currentActivity, is(notNullValue()));

      // Type into the username field...
      View currentView = currentActivity.findViewById(username_field);
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(EditText.class));
      TouchUtils.clickView(this, currentView);
      instrumentation.sendStringSync("MyUsername");

      // Type into the password field...
      currentView = currentActivity.findViewById(password_field);
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(EditText.class));
      TouchUtils.clickView(this, currentView);
      instrumentation.sendStringSync("MyPassword");

      // Register we are interested in the welcome activity...
      // this has to be done before we do something that will send us to that
      // activity...
      instrumentation.removeMonitor(monitor);
      monitor = instrumentation.addMonitor(WelcomeActivity.class.getName(), null, false);

      // Click the login button...
      currentView = currentActivity.findViewById(login_button;
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(Button.class));
      TouchUtils.clickView(this, currentView);

      // Wait for the welcome page to start...
      currentActivity = getInstrumentation().waitForMonitorWithTimeout(monitor, 5);
      assertThat(currentActivity, is(notNullValue()));

      // Make sure we are logged in...
      currentView = currentActivity.findViewById(welcome_message);
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(TextView.class));
      assertThat(((TextView)currentView).getText().toString(), is("Welcome, MyUsername!"));
   }
}

Mã này rõ ràng là không thể đọc được. Tôi đã thực sự giải nén nó vào một thư viện đơn giản với một API giống như tiếng Anh nên tôi chỉ có thể nói những điều như sau:

type("myUsername").intoThe(username_field);
click(login_button);

Tôi đã kiểm tra độ sâu của khoảng 4 hoạt động và hài lòng rằng cách tiếp cận hoạt động mặc dù như tôi đã nói, đôi khi có một vấn đề về thời gian mà tôi chưa hoàn toàn tìm ra. Tôi vẫn muốn nghe về bất kỳ cách kiểm tra nào khác trong các hoạt động.


3
Bạn có thể thử thêm chú thích FlakyTest để tự động lặp lại kiểm tra khi các vấn đề về thời gian khiến nó không thành công. Thực sự không phải là một giải pháp mà là một giải pháp khả thi trong một số tình huống.
Carl Manaster

Cảm ơn vì đã viết cái này lên! Tôi đang tìm kiếm thứ gì đó có chức năng của ActivityMonitors để thử nghiệm. Tôi chỉ không thể tìm thấy chúng.
Peter Ajtai

Theo như tôi biết, không có gì bạn đã làm ở trên không thể được thực hiện bằngActivityInstrumentationTestCase2
ericn

bất kỳ ý tưởng nào, với điều kiện nào, 'getInticmentation (). waitForIdleSync ();' sẽ nhận được vào vòng lặp vô hạn? Trong bảng mạch xử lý đang chạy android 4.4.2_r2, tôi đang gặp phải sự cố này khi thực hiện Kiểm tra CTS.
ArunJTS

Tôi nghĩ rằng con trai tôi @ pajato1 đã tìm thấy và khắc phục sự cố thời gian của bạn. Bản sửa lỗi của anh ấy đã giải quyết được vấn đề của tôi. Đây là những gì anh ấy nói: "Tôi chỉ nhận thấy trong javadoc rằng Instrumentation.startActivitySync () đang chặn cho đến khi Hoạt động mới sẵn sàng và sau đó trả lại nó, vì vậy có vẻ như Màn hình không cần thiết. Việc xóa nó đã chứng minh điều này là chính xác. lý thuyết là Monitor đã khiến Activity được tạo bởi startActivitySync () được khởi động lại trong một số trường hợp do điều kiện cuộc đua. Tôi đã dành một chút thời gian để đọc mã nguồn android, nhưng không có gì bật ra với tôi là nguyên nhân của tình trạng cuộc đua. "
pajato0

22

Hãy xem Robotium
'một khung kiểm tra mã nguồn mở được tạo ra để làm cho kiểm tra hộp đen tự động của các ứng dụng Android nhanh hơn và dễ dàng hơn đáng kể so với những gì có thể với các bài kiểm tra thiết bị Android ngay lập tức.'

Trang chủ: http://www.robotium.org/
Nguồn: http://github.com/jayway/robotium

Xin lưu ý rằng dự án Robotium được duy trì bởi công ty tôi làm việc


chào, Có công cụ ghi cho việc này không? Tôi đã kiểm tra nhiều trang web và tìm thấy testdroid ghi lại các tập lệnh và chạy nó. Thật không may, nó không phải là một phần mềm miễn phí, bạn có biết bất kỳ phần mềm miễn phí nào thực hiện quá trình ghi âm không?
thndrkiss

@thndrkiss: Tôi không biết bất kỳ công cụ nào như vậy. Nếu bạn đặt câu hỏi trên diễn đàn Robotium, bạn có khả năng nhận được câu trả lời tốt hơn.
Jonas Söderström

2
Robotium là một cứu tinh. Nó sẽ làm cho bài kiểm tra của bạn cực kỳ dễ viết (về cơ bản bạn đang nói chuyện với nó bằng tiếng Anh đơn giản: nhấp vào nút này, nhấn nút quay lại, v.v.) Bạn có thể kiểm tra bất cứ thứ gì nhưng bạn không bắt buộc phải biết những chi tiết nhỏ. Nó có ít nhất hai lợi ích chính: bạn có thể kiểm tra các ứng dụng mà bạn không có mã nguồn và nó dựa vào giao diện người dùng làm cho nó rất mạnh mẽ (bạn thay đổi bộ điều khiển / mô hình nhiều hơn so với chế độ xem của bạn ...)
tiktak

8

Bạn luôn có thể sử dụng Robotium. Nó hỗ trợ kiểm tra hộp đen giống như Selenium nhưng dành cho Android. Bạn sẽ tìm thấy nó tại Robotium.org


1
Lần trước, tôi đã kiểm tra Không thể sử dụng Robotium trên các Hoạt động. Điều đó đã được sửa chữa bây giờ? stackoverflow.com/questions/3840034/…
user77115

3
Nó luôn hoạt động trên các Hoạt động miễn là chúng thuộc cùng một quy trình.
Renas

4

Tôi ngạc nhiên là không ai đề cập đến một số công cụ kiểm tra chức năng tự động hàng đầu . So với Robotium, chúng không yêu cầu viết mã Java.

MonkeyTalk : một công cụ mã nguồn mở được hỗ trợ bởi công ty Gorilla Logic. Ưu điểm: cung cấp khả năng ghi âm cũng như ngôn ngữ kịch bản cấp cao hơn dễ dàng hơn cho người dùng không chuyên về kỹ thuật và đa nền tảng (bao gồm iOS). Với những lợi ích đó theo yêu cầu, chúng tôi nhận thấy đây là giải pháp tốt nhất. Nó cũng cho phép tùy chỉnh ngoài những gì có thể được thực hiện trong ngôn ngữ kịch bản của họ bằng cách sử dụng Javascript.

Calabash-Android : một công cụ mã nguồn mở cho các tính năng kiểu Dưa chuột. Ưu điểm: viết các tính năng bằng ngôn ngữ Gherkin là Ngôn ngữ dành riêng cho miền có thể đọc được, cho phép bạn mô tả hành vi của phần mềm mà không nêu chi tiết cách hành vi đó được thực hiện. Hỗ trợ tương tự nhưng không chính xác có sẵn cho iOS trong dưa chuột-ios . Khả năng ghi không tốt vì chúng tạo ra đầu ra nhị phân.

Một số tài liệu tham khảo khác:

  • Dưới đây là một số so sánh bổ sung giữa Robotium, Monkeytalk và Calabash. Nó đề cập đến TestDroid như một khả năng khác.
  • Blog này đề cập ở trên cùng với NativeDriver và Bot-bot.

3

Tôi đã tạo công cụ ghi và phát lại cho Android và cung cấp nó trên GitHub . Nó dễ dàng cấu hình và sử dụng, không cần lập trình, chạy trên các thiết bị thực (không cần phải root) và tự động lưu ảnh chụp màn hình khi nó chạy các bài kiểm tra.


Điều này có vẻ đầy hứa hẹn. Đối với những người không nhìn thấy điểm: điều này dường như là một giải pháp khá tốt để cử chỉ kiểm tra (khai thác, kéo và những thứ khác)
tiktak

3

Trước hết, hãy sử dụng 'ActivityInticmentationTestCase2', không phải 'InstrumentationTestCase', làm lớp cơ sở của bạn. Tôi sử dụng Robotium và thường xuyên kiểm tra trên nhiều Hoạt động. Tôi thấy rằng tôi phải chỉ định hoạt động đăng nhập là kiểu chung (và đối số lớp cho hàm tạo).

Phương thức khởi tạo 'ActivityInticmentationTestCase2' bỏ qua đối số gói và không yêu cầu nó. Hàm tạo nhận gói không được dùng nữa.

Từ Javadocs: "ActivityInticmentationTestCase2 (String pkg, Class activityClass) Hàm tạo này không được dùng nữa. Thay vào đó, hãy sử dụng ActivityInticmentationTestCase2 (Class)"

Sử dụng lớp cơ sở được đề xuất cho phép khung công tác xử lý một số bản soạn sẵn nhất định, như bắt đầu hoạt động của bạn. Điều đó được thực hiện bằng lệnh gọi tới 'getActivity ()', nếu cần.


3

Tìm thấy điều này hữu ích với một vài sửa đổi. Đầu tiên getInstrumentation().waitForIdleSync()sẽ chữa khỏi lỗi mà SingleShot nói đến và cũng InstrumentationTestCasecó một lauchActivitychức năng có thể thay thế các dòng hoạt động bắt đầu.


2

bạn có thể làm như vậy để tránh thời gian chờ flake không đồng bộ:

final Button btnLogin = (Button) getActivity().findViewById(R.id.button);
Instrumentation instrumentation = getInstrumentation();

// Register we are interested in the authentication activity...
Instrumentation.ActivityMonitor aMonitor = 
        instrumentation.addMonitor(mynextActivity.class.getName(), null, false);

getInstrumentation().runOnMainSync(new Runnable() {
         public void run() {
             btnLogin.performClick();
         }
     });

getInstrumentation().waitForIdleSync();

//check if we got at least one hit on the new activity
assertTrue(getInstrumentation().checkMonitorHit(aMonitor, 1)); 

1

Tôi đang làm khá nhiều thứ tương tự và có lẽ tôi sẽ đi với một biến thể cho câu trả lời được chấp nhận cho câu hỏi này, nhưng tôi đã gặp Calculuon ( gitHub ) trong quá trình tìm kiếm giải pháp.


0

Cá nhân tôi chưa sử dụng nó, nhưng ApplicationTestCase có vẻ như nó có thể là thứ bạn đang tìm kiếm.


Thật không may, không có ví dụ nào chỉ ra rằng đúng như vậy.
SingleShot

Yea, có vẻ như bạn đã đúng ... đã bị lừa bởi tên. Tôi không thể hiểu được điều này. Cách tốt nhất mà tôi có cho đến nay là sử dụng ActivityUnitTestCase của positron để xác minh rằng hoạt động tiếp theo được bắt đầu, nhưng điều đó không giúp bạn xây dựng các câu chuyện mạch lạc. Ngoài ra, InstrumentationTestCase.launchActivity có thể cho phép bạn bắt đầu một số hoạt động tùy ý, nhưng tôi vẫn đang cố gắng tìm ra những thứ trong Instrumentation.
Eric

0

Phương pháp tiếp cận được chấp nhận có hoạt động với các Hoạt động khác nhau từ các Ứng dụng khác nhau, được ký bởi các chứng chỉ khác nhau không? Nếu không, Robotium là cách tốt nhất để kiểm tra các hoạt động trong cùng một ứng dụng.


0

Có một cách khác để thực hiện nhiều hoạt động bằng cách sử dụng Lớp Hoạt động Kinh tế .. Đó là một kịch bản tự động hóa bình thường ... Trước tiên, hãy lấy tiêu điểm của đối tượng từng muốn và sau đó gửi một khóa đơn giản như mã mẫu đó

button.requestFocus();
sendKeys(KeyEvent.KEYCODE_ENTER);

Chỉ có điều là hiểu mọi lệnh gọi API sẽ giúp chúng ta.


0

Câu trả lời này dựa trên câu trả lời được chấp nhận nhưng được sửa đổi để giải quyết vấn đề thời gian mà đối với tôi đã trở nên nhất quán sau khi thêm khoảng nửa tá bài kiểm tra. @ pajato1 nhận được tín dụng cho việc giải quyết vấn đề thời gian, như được trích dẫn trong các nhận xét câu trả lời được chấp nhận.

/**
 * Creates a test Activity for a given fully qualified test class name.
 *
 * @param fullyQualifiedClassName The fully qualified name of test activity class.
 *
 * @return The test activity object or null if it could not be located.
 */
protected AbstractTestActivity getTestActivity(final String fullyQualifiedClassName) {
    AbstractTestActivity result = null;

    // Register our interest in the given activity and start it.
    Log.d(TAG, String.format("Running test (%s) with main class: %s.", getName(), fullyQualifiedClassName));
    instrumentation = getInstrumentation();

    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setClassName(instrumentation.getTargetContext(), fullyQualifiedClassName);
    // Wait for the activity to finish starting
    Activity activity = instrumentation.startActivitySync(intent);

    // Perform basic sanity checks.
    assertTrue("The activity is null!  Aborting.", activity != null);
    String format = "The test activity is of the wrong type (%s).";
    assertTrue(String.format(format, activity.getClass().getName()), activity.getClass().getName().equals(fullyQualifiedClassName));
    result = (AbstractTestActivity) activity;

    return result;
}

0

Hãy thử kiểm tra công cụ Monkey

Bước 1:

mở thiết bị đầu cuối studio android (Công cụ-> mở thiết bị đầu cuối)

Bước 2:

Để sử dụng Monkey, hãy mở dấu nhắc lệnh và chỉ cần điều hướng đến thư mục sau.

 export PATH=$PATH:/home/adt-bundle-linux-x86-20140702/sdk/platform-tools

Bước 3:

thêm lệnh khỉ này vào thiết bị đầu cuối và nhấn enter ..

thấy điều kỳ diệu trong trình giả lập của bạn.

adb shell monkey -p com.example.yourpackage -v 500

500- nó là số lượng tần suất hoặc số lượng sự kiện được gửi để kiểm tra.

bạn có thể thay đổi số lượng này ..

Tham khảo thêm,

http://www.tutorialspoint.com/android/android_testing.htm

http://androidtesting.blogspot.in/2012/04/android-testing-with-monkey-tool.html


Người phản đối phải cho biết lý do phản đối ... đây là mã làm việc .. và cả phương pháp thử nghiệm chính thức nữa. Nếu bất kỳ sai lầm tôi đã sẵn sàng để sửa câu trả lời của tôi ..
Ranjith Kumar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.