Add functional test for bt anomaly detector

This cl:
Set up the environment for functional test
1. Update Android.mk by adding instrumentation and libs
2. Update AndroidManifest.xml by adding runner

Add functional test for bt anomaly, with the following workflow
1. reset battery stats
2. pretend unplug and screen off
3. Start AnomalyTester app, set values and click start button
4. Wait its running
5. Check anomaly preference in battery main page
6. reset all parameters

Bug: 63815938
Test: runtest -x BluetoothAnomalyTest
Change-Id: Ief02a314d21f6c32d70729047a1d4bdce9ad9920
This commit is contained in:
jackqdyulei
2017-08-17 14:26:01 -07:00
parent 0cc62f860c
commit e4298941b4
4 changed files with 217 additions and 1 deletions

View File

@@ -2,6 +2,15 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
LOCAL_CERTIFICATE := platform
LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
mockito-target \
ub-uiautomator \
truth-prebuilt \
LOCAL_SRC_FILES := $(call all-subdir-java-files)
@@ -9,7 +18,7 @@ LOCAL_PROGUARD_ENABLED := disabled
LOCAL_PACKAGE_NAME := AnomalyTester
LOCAL_CERTIFICATE := platform
LOCAL_INSTRUMENTATION_FOR := Settings
LOCAL_USE_AAPT2 := true

View File

@@ -22,11 +22,13 @@
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<application
android:allowBackup="false"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@android:style/Theme.Material.Light.DarkActionBar">
<uses-library android:name="android.test.runner" />
<activity
android:name=".AnomalyActivity"
android:exported="true">
@@ -41,4 +43,10 @@
android:exported="false"/>
</application>
<instrumentation
android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.settings"
android:label="Settings Test Cases">
</instrumentation>
</manifest>

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.settings.anomaly.tests;
import static com.google.common.truth.Truth.assertWithMessage;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.Until;
import android.text.format.DateUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Functional test for bluetooth unoptimized scanning anomaly detector
*
* @see com.android.settings.fuelgauge.anomaly.checker.BluetoothScanAnomalyDetector
*/
@RunWith(AndroidJUnit4.class)
public class BluetoothAnomalyTest {
private static final String BATTERY_INTENT = "android.intent.action.POWER_USAGE_SUMMARY";
private static final String RES_BT_EDITTEXT =
"com.android.settings.anomaly.tester:id/bluetooth_run_time";
private static final String RES_BT_BUTTON =
"com.android.settings.anomaly.tester:id/bluetooth_button";
private static final long TIME_OUT = 3000;
private UiDevice mDevice;
@Before
public void setUp() {
final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
final Context context = instrumentation.getContext();
mDevice = UiDevice.getInstance(instrumentation);
// setup environment
TestUtils.setUp(instrumentation);
// start anomaly-tester app
TestUtils.startAnomalyApp(context, mDevice);
}
@After
public void tearDown() {
TestUtils.tearDown(InstrumentationRegistry.getInstrumentation());
}
@Test
public void testBluetoothAnomaly_longScanningTime_reportAnomaly() throws InterruptedException {
// Set running time
final long durationMs = DateUtils.SECOND_IN_MILLIS * 15;
TestUtils.setEditTextWithValue(mDevice, RES_BT_EDITTEXT, durationMs);
// Click start button
TestUtils.clickButton(mDevice, RES_BT_BUTTON);
// Wait for its running
mDevice.pressHome();
TestUtils.wait(mDevice, durationMs);
// Check it in battery main page
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.startActivitySync(new Intent(BATTERY_INTENT));
assertWithMessage("Doesn't have bluetooth anomaly").that(
mDevice.wait(Until.findObject(By.text("AnomalyTester draining battery")),
TIME_OUT)).isNotNull();
}
@Test
public void testBluetoothAnomaly_shortScanningTime_notReport() throws InterruptedException {
// Set running time
final long durationMs = DateUtils.SECOND_IN_MILLIS;
TestUtils.setEditTextWithValue(mDevice, RES_BT_EDITTEXT, durationMs);
// Click start button
TestUtils.clickButton(mDevice, RES_BT_BUTTON);
// Wait for its running
mDevice.pressHome();
TestUtils.wait(mDevice, durationMs);
// Check it in battery main page
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.startActivitySync(new Intent(BATTERY_INTENT));
assertWithMessage("Shouldn't have bluetooth anomaly").that(
mDevice.wait(Until.findObject(By.text("AnomalyTester draining battery")),
TIME_OUT)).isNull();
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.settings.anomaly.tests;
import static com.google.common.truth.Truth.assertWithMessage;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.content.Context;
import android.content.Intent;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
public class TestUtils {
private static final String PACKAGE_NAME = "com.android.settings.anomaly.tester";
private static final long TIME_OUT = 3000;
/**
* This method set up the environment for anomaly test
*
* @param instrumentation to execute command
*/
public static void setUp(Instrumentation instrumentation) {
final UiAutomation uiAutomation = instrumentation.getUiAutomation();
// pretend unplug and screen off, also reset the battery stats
uiAutomation.executeShellCommand("dumpsys battery unplug");
uiAutomation.executeShellCommand("dumpsys batterystats enable pretend-screen-off");
uiAutomation.executeShellCommand("dumpsys batterystats --reset");
}
/**
* This method cleans up all the commands in {@link #setUp(Instrumentation)}
*
* @param instrumentation to execute command
*/
public static void tearDown(Instrumentation instrumentation) {
final UiAutomation uiAutomation = instrumentation.getUiAutomation();
// reset unplug and screen-off
uiAutomation.executeShellCommand("dumpsys battery reset");
uiAutomation.executeShellCommand("dumpsys batterystats disable pretend-screen-off");
}
public static void startAnomalyApp(Context context, UiDevice uiDevice) {
final Intent intent = context.getPackageManager().getLaunchIntentForPackage(PACKAGE_NAME);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
uiDevice.wait(Until.hasObject(By.pkg(PACKAGE_NAME).depth(0)), TIME_OUT);
}
/**
* Find {@link android.widget.EditText} with {@code res} and set its {@code value}
*/
public static void setEditTextWithValue(UiDevice uiDevice, String res, long value) {
final UiObject2 editText = uiDevice.findObject(By.res(res));
assertWithMessage("Cannot find editText with res: " + res).that(editText).isNotNull();
editText.setText(String.valueOf(value));
}
/**
* Find {@link android.widget.Button} with {@code res} and click it
*/
public static void clickButton(UiDevice uiDevice, String res) {
final UiObject2 button = uiDevice.findObject(By.res(res));
assertWithMessage("Cannot find button with res: " + res).that(button).isNotNull();
button.click();
}
/**
* Make {@link UiDevice} wait for {@code timeMs}
*
* @see Thread#sleep(long)
*/
public static void wait(UiDevice uiDevice, long timeMs) throws InterruptedException {
uiDevice.waitForIdle();
Thread.sleep(timeMs);
}
}