我写了一个在apk文件上运行测试的机器人测试。 在这种情况下,我在之前的android poroject中创建了apk文件,因为apk仍处于调试模式。 测试点击并在应用程序中插入数据。
在模拟器中运行时我收到错误“注入另一个应用程序需要INJECT_EVENTS权限”。
我尝试了每次在互联网上发布的洗礼,但无济于事。
以下列出了我尝试的各种措施:
在root上设置模拟器。
在测试开始时让测试睡几秒钟。
添加到清单:
<uses-permission android:name="android.permission.INJECT_EVENTS"/>
aslo将此添加到清单:
android:anyDensity="true"
添加setUp函数:
setActivityInitialTouchMode(true);
aslo在setUp函数中添加:
KeyguardManager km =
(KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
if (km.inKeyguardRestrictedInputMode())
{
KeyguardManager.KeyguardLock lock = km.newKeyguardLock("some_tag");
lock.disableKeyguard();
SystemClock.sleep(2000);
}
将应用程序从data / appfolder移动到system aoo文件夹。
代码解锁屏幕:
mSolo.unlockScreen();
aslo解锁:
adb shell input keyevent 82
我正在添加代码。 代码包含三个类,以及清单:
班级主要:
package genericTest.test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import android.annotation.SuppressLint;
import android.app.KeyguardManager;
import android.content.Context;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.test.SingleLaunchActivityTestCase;
import android.util.Log;
import android.view.Display;
import android.view.View;
import com.robotium.solo.Solo;
@SuppressWarnings("rawtypes")
public class Main extends ActivityInstrumentationTestCase2 {
//public class Main extends SingleLaunchActivityTestCase {
//SingleLaunchActivityTestCase
private FunctonsForViews mFunctonsForViews;
private Random mRand;
private Solo mSolo;
//private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "com.goldtouch.ynet.ui.activities.SplashActivity";
private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "com.bignerdranch.android.criminalintent.CrimeListActivity";
//in Manifest: <!--android:targetPackage="com.bignerdranch.android.criminalintent"-->
//private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "com.mojang.minecraftpe.MainActivity";
//in Manifest: <!--android:targetPackage="com.mojang.minecraftpe"-->
private final int LIMIT_TIME = 300000;
private final int DELAY = 200;
private final int SCREEN_SIZE = 200;
private final int ERROR_COUNT_LIMIT = 10;
private final int CLICK_ON_LOOP_LIMIT = 20;
private final int WHAITING_FOR_VIEWS_LIMIT = 20;
private static Class launcherActivityClass;
private static int error_count = 0;
static {
try {
launcherActivityClass = Class
.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
@SuppressLint("NewApi")
@SuppressWarnings("unchecked")
public Main() throws ClassNotFoundException {
super(launcherActivityClass);
}
protected void setUp() throws Exception {
setActivityInitialTouchMode(true);
mSolo = new Solo(getInstrumentation(), getActivity());
Context context = getActivity();
int temp = 0;
KeyguardManager km =
(KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
if (km.inKeyguardRestrictedInputMode())
{
KeyguardManager.KeyguardLock lock = km.newKeyguardLock("some_tag");
lock.disableKeyguard();
SystemClock.sleep(2000);
}
setActivityInitialTouchMode(true);
}
/*
* runs the test for the app.
*/
public void testMethod()
{
mFunctonsForViews = new FunctonsForViews(mSolo);
mSolo.sleep(10000);
mRand = new Random();
/*
* the test will take place in the loop, and will be limit in time.
* in every iteration it will get the vies in activity's, and run a test on a random view.
*/
for(int i=0 ;i < LIMIT_TIME ; i += DELAY)
{
mSolo.unlockScreen();
ArrayList Views = mSolo.getViews();
int arraySize = Views.size();
if (arraySize == 0)// now View in activity.
{
whenNoViewsInScreen(Views, arraySize);
}
if (arraySize != 0)
{
int ViewIndexInArray = mRand.nextInt(arraySize + 1);
if (ViewIndexInArray == arraySize)
{
mSolo.scrollDown();
}
else
{
View randomView = (View)(Views.get(ViewIndexInArray));
runTestOnOneView(randomView);
}
}
}
}
/*
* performing clicks onScreen()
*/
public void myClickOnScreen()
{
try {
mSolo.unlockScreen();
mSolo.clickOnScreen(mRand.nextInt(SCREEN_SIZE), mRand.nextInt(SCREEN_SIZE));
//mSolo.clickLongOnScreen(mRand.nextInt(SCREEN_SIZE), mRand.nextInt(SCREEN_SIZE));
} catch (Exception e) {
e.printStackTrace();
Log.e("in exception of clickOnScreen function.", "error_count=" + error_count);
if(error_count > ERROR_COUNT_LIMIT)
{
//goingBack();
error_count = 0;
}
//e.printStackTrace();
} catch (Error e2) {
e2.printStackTrace();
Log.e("in error of clickOnScreen function.", "error_count=" + error_count);
if(error_count > ERROR_COUNT_LIMIT)
{
//goingBack();
error_count = 0;
}
//e2.printStackTrace();
}
}
/*
* there is no Views available.
* we will try pressing on screen or the goBack function.
*/
public void whenNoViewsInScreen(ArrayList Views, int arraySize)
{
for (int j = 0; j < WHAITING_FOR_VIEWS_LIMIT; j++)
{
for (int k= 0; k < CLICK_ON_LOOP_LIMIT; k++)
{
myClickOnScreen();
}
Views = mSolo.getViews();
arraySize = Views.size();
if (arraySize != 0)
{
return;
}
mSolo.sleep(DELAY);
Views = mSolo.getViews();
arraySize = Views.size();
if (arraySize != 0)
{
return;
}
}
goingBack();
mSolo.sleep(DELAY);
return;
}
public void runTestOnOneView(View randomView)
{
String rawViewName = randomView.getClass().getName();
String viewName = parseRawViewName(rawViewName);
Log.i("ViewName", viewName);
//temp
/*if (viewName.contains("ActionBarContainer"))
{
return;
}*/
MyRunnable myRunnable = mFunctonsForViews.getMethodMap().get(viewName);
try{
if (myRunnable != null)
{
Log.e("myRunnable != null", viewName);
myRunnable.run((View)randomView);
}
else // view not in map.
{
boolean inMap = false;
Iterator it = mFunctonsForViews.getMethodMap().entrySet().iterator();
/*
* iterating in case the View is a version of one of View in map
* example:
* View is "CustomEditText", and map contains o view "EditText".
*/
while (it.hasNext())
{
Map.Entry pairs = (Map.Entry)it.next();
if ( viewName.contains((String)pairs.getKey()) )
{
inMap = true;
// next two lines changed
myRunnable = (MyRunnable)(pairs.getValue());
myRunnable.run((View)randomView);
break;
}
}
if (inMap == false)
{
mSolo.clickOnView((View)randomView);
}
error_count = 0;
}
}catch(Exception exception)
{
exception.printStackTrace();
Log.e("Exception click on view", viewName);
for (int i=0 ; i < CLICK_ON_LOOP_LIMIT; i++)
{
myClickOnScreen();
error_count ++;
if(error_count > ERROR_COUNT_LIMIT)
{
goingBack();
error_count = 0;
}
}
}catch(Error error)
{
error.printStackTrace();
Log.e("Error click on view ", viewName+ " " + error.toString());
for (int i=0 ; i < CLICK_ON_LOOP_LIMIT; i++)
{
myClickOnScreen();
error_count ++;
if(error_count > ERROR_COUNT_LIMIT)
{
goingBack();
error_count = 0;
}
}
}
mSolo.sleep(DELAY);
}
/*
* performs a goBack command surrounded with catch/try
*/
public void goingBack()
{
try {
mSolo.goBack();
} catch (Exception e) {
//Log.e("Exeption! ", "Can;t go back" );
e.printStackTrace();
} catch (Error e) {
//Log.e("Error! ", "Can;t go back" );
e.printStackTrace();
}
}
/*
* extract the name of View from raw View name.
* example:
* raw View name: android.widget.TextView
* raw View name:TextView
*/
public String parseRawViewName(String rawViewName)
{
if (rawViewName.contains(" "))
{
String [] array = rawViewName.split(" ");
rawViewName = array [0];
}
if (rawViewName.contains(".") || rawViewName.contains("$"))
{
String [] array = rawViewName.split("\\.|$");
Log.i("array length:", ""+ array.length);
rawViewName = array [array.length-1];
}
return rawViewName;
}
public void tearDown() throws Exception {
mSolo.finishOpenedActivities();
//super.tearDown();
}
}
类FunctonsForViews:
package genericTest.test;
import java.lang.reflect.*;
import java.util.*;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
import android.view.View;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.TimePicker;
import com.robotium.solo.Solo;
/*
* contains the functions and parameters running for every View.
*/
public class FunctonsForViews {
private Map<String, MyRunnable> mMethodMap;
private Solo mSolo;
private Random mRand = new Random();
private final int LIST_TEST_FUNCTIONS = 4;
private final String TAG = "FunctonsForViews";
private final String [] editTextMailInput =
{"example@gmail.com", "secondExample@gmail.com", "erongFormat","123"};
private final String [] editTextPasswordInput =
{"0987654321", "0987654321a", "12","iioo", "ui9"};
private final String [] editTextNameInput =
{"yoav", "567", "ran","iioott", "iioottrr", "iioottrraaqqhh", "iioottrraaqqhh23"};
private final String [] editTextTelephoneInput =
{"078123456", "078123456a", "dan","4675", "123"};
//getter
public Map<String, MyRunnable> getMethodMap()
{
return mMethodMap;
}
/*
* initials the HashMap mMethodMap, and insert the fitting function for handling every View in activity
*/
public FunctonsForViews(Solo solo)
{
mSolo = solo ;
mMethodMap = new HashMap<String, MyRunnable>();
try {
mMethodMap.put("EditText", new MyRunnable() {
public void run(View view) { MyEnterText(view); }
});
/*
mMethodMap.put("CustomEditText", new MyRunnable() {
public void run(View view) { MyEnterText(view); }
});*/
mMethodMap.put("ProgressBar", new MyRunnable() {
public void run(View view) { MySetProgressBar(view); }
});
mMethodMap.put("TimePicker", new MyRunnable() {
public void run(View view) { MySetTimePicker(view); }
});
mMethodMap.put("DatePicker", new MyRunnable() {
public void run(View view) { MySetDatePicker(view); }
});
mMethodMap.put("ListView", new MyRunnable() {
public void run(View view) { MyListTest(view); }
});
/*
mMethodMap.put("e", new MyRunnable() {
public void run(View view) { doNuthing(view); }
});
*/
} catch (Exception e) {
Log.i(TAG, "Cant put in map");
e.printStackTrace();
}
}
/*
* sets random values in the TimePicker View
*/
public void MySetTimePicker(View view)
{
int hour = mRand.nextInt(24);
int minute = mRand.nextInt(60);
mSolo.setTimePicker((android.widget.TimePicker)view, hour, minute);
}
/*
* sets random values in the DatePicker View
*/
public void MySetDatePicker(View view)
{
int year = mRand.nextInt((2020 - 1900) ) + 1900;
int month = mRand.nextInt(12);
int dayOfMonth = mRand.nextInt((31 - 1) ) + 1;
mSolo.setDatePicker((android.widget.DatePicker)view, year, month, dayOfMonth);
}
/*
* sets random values in the ProgressBar View
*/
public void MySetProgressBar(View view)
{
ProgressBar progressBar = (ProgressBar)view;
mSolo.setProgressBar(progressBar, mRand.nextInt(progressBar.getMax()));
}
/*
* calls a random ViewList Solo function
*/
public void MyListTest(View view)
{
int function = mRand.nextInt(LIST_TEST_FUNCTIONS );
switch (function)
{
case 0:
if (((((ListView)view).getLastVisiblePosition()
- ((ListView)view).getFirstVisiblePosition()) + 1) >0)
{
mSolo.clickInList(mRand.nextInt(((ListView)view).getLastVisiblePosition()
- ((ListView)view).getFirstVisiblePosition()) + 1);
}
break;
case 1:
if (((((ListView)view).getLastVisiblePosition()
- ((ListView)view).getFirstVisiblePosition()) + 1) >0)
{
//mSolo.clickLongInList(mRand.nextInt(((ListView)view).getLastVisiblePosition()
//- ((ListView)view).getFirstVisiblePosition()) + 1);
mSolo.clickInList(mRand.nextInt(((ListView)view).getLastVisiblePosition()
- ((ListView)view).getFirstVisiblePosition()) + 1);
}
break;
case 2:
mSolo.scrollListToBottom((ListView)view) ;
break;
default:
mSolo.scrollListToTop((ListView)view) ;
break;
}
}
/*
* sets the text of a EditText View
*/
public void MyEnterText(View view)
{
mSolo.clearEditText((android.widget.EditText)view);
mSolo.enterText((android.widget.EditText)view, getStringForEditTextInput(view));
}
/*
* return a string to be use to set in EditText View.
* the specific string will be choose randomly.
*/
public String getStringForEditTextInput(View view)
{
ArrayList Views = mSolo.getViews();
String EditTextInput = null;
int index = Views.indexOf(view);
for (int i = index - 1; i> index - 4; i--)
{
if (Views.get(i).getClass().getName() == "TextView" )
{
String textViewText = ((TextView)Views.get(i)).getText().toString().toLowerCase();
if(textViewText.contains("mail"))
{
EditTextInput = editTextMailInput[mRand.nextInt(editTextMailInput.length) ];
}
else if(textViewText.contains("password"))
{
EditTextInput = editTextPasswordInput[mRand.nextInt(editTextPasswordInput.length) ];
}
else if(textViewText.contains("telephone"))
{
EditTextInput = editTextTelephoneInput[mRand.nextInt(editTextTelephoneInput.length) ];
}
return EditTextInput;
}
}
EditTextInput = editTextNameInput[mRand.nextInt(editTextNameInput.length) ];
return EditTextInput;
}
}
接口MyRunnable:
package genericTest.test;
import android.view.View;
/*
* used for storing function HashMap
*/
public interface MyRunnable {
public void run(View view);
}
清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="genericTest.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.INJECT_EVENTS"/>
android:anyDensity=”true"
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.bignerdranch.android.criminalintent"/>
/>
<supports-screens
android:resizeable="true"
android:smallScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:normalScreens="true"
android:anyDensity="true"/>
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<uses-library android:name="android.test.runner" />
</application>
</manifest>