mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-05-14 20:48:00 +00:00
[React Native CI] Record more info to debug E2E test (#13329)
Record more info from the React Native CI E2E test. In particular, log the view hierarchy when exiting the test and dump logs from Android emulator to the build output.
This commit is contained in:
parent
9189ebb415
commit
2fa18ea77e
6 changed files with 155 additions and 56 deletions
|
|
@ -189,6 +189,7 @@ dependencies {
|
|||
implementation "com.facebook.react:react-native:+" // From node_modules
|
||||
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
|
||||
implementation 'androidx.test.ext:junit:1.1.3'
|
||||
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
|
||||
exclude group:'com.facebook.fbjni'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.example.reactnativeonnxruntimemodule;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
|
@ -7,9 +8,10 @@ import androidx.test.espresso.NoMatchingViewException;
|
|||
import androidx.test.espresso.UiController;
|
||||
import androidx.test.espresso.ViewAction;
|
||||
import androidx.test.espresso.ViewInteraction;
|
||||
import androidx.test.espresso.util.TreeIterables;
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.rule.ActivityTestRule;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.Assert;
|
||||
|
|
@ -20,37 +22,44 @@ import org.junit.runner.RunWith;
|
|||
import static androidx.test.espresso.Espresso.onView;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
public class OnnxruntimeModuleExampleUITests {
|
||||
public static final String TAG = OnnxruntimeModuleExampleUITests.class.getSimpleName();
|
||||
|
||||
@Rule
|
||||
public ActivityTestRule<MainActivity> activityTestRule = new ActivityTestRule<>(MainActivity.class);
|
||||
public ActivityScenarioRule<MainActivity> activityScenarioRule = new ActivityScenarioRule<>(MainActivity.class);
|
||||
|
||||
@Test
|
||||
public void testExample() {
|
||||
// Wait for a view displayed
|
||||
int waitTime = 0;
|
||||
final int sleepTime = 1000;
|
||||
do {
|
||||
try {
|
||||
ViewInteraction view = onView(allOf(withContentDescription("output"), isDisplayed()));
|
||||
if (getText(view) != null) {
|
||||
break;
|
||||
}
|
||||
} catch (NoMatchingViewException ne) {
|
||||
try {
|
||||
// Wait for a view displayed
|
||||
int waitTime = 0;
|
||||
final int sleepTime = 1000;
|
||||
do {
|
||||
try {
|
||||
Thread.sleep(sleepTime);
|
||||
} catch (InterruptedException ie) {
|
||||
ViewInteraction view = onView(allOf(withContentDescription("output"), isDisplayed()));
|
||||
if (getText(view) != null) {
|
||||
break;
|
||||
}
|
||||
} catch (NoMatchingViewException ne) {
|
||||
try {
|
||||
Thread.sleep(sleepTime);
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
waitTime += sleepTime;
|
||||
}
|
||||
waitTime += sleepTime;
|
||||
}
|
||||
} while (waitTime < 180000);
|
||||
} while (waitTime < 180000);
|
||||
|
||||
ViewInteraction view = onView(allOf(withContentDescription("output"), isDisplayed()));
|
||||
Assert.assertEquals(getText(view), "Result: 3");
|
||||
ViewInteraction view = onView(allOf(withContentDescription("output"), isDisplayed()));
|
||||
Assert.assertEquals("Result: 3", getText(view));
|
||||
} finally {
|
||||
dumpRootViewHierarchy();
|
||||
}
|
||||
}
|
||||
|
||||
private String getText(ViewInteraction matcher) {
|
||||
|
|
@ -76,4 +85,35 @@ public class OnnxruntimeModuleExampleUITests {
|
|||
|
||||
return text[0];
|
||||
}
|
||||
|
||||
private static void dumpRootViewHierarchy() {
|
||||
ViewInteraction rootViewInteraction = onView(isRoot());
|
||||
rootViewInteraction.perform(new ViewAction() {
|
||||
@Override
|
||||
public Matcher<View> getConstraints() {
|
||||
return isRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "dump view hierarchy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(UiController uiController, View view) {
|
||||
if (view == null) {
|
||||
Log.w(TAG, "view is null, unable to dump view hierarchy");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, "view hierarchy:");
|
||||
for (TreeIterables.ViewAndDistance viewAndDistance : TreeIterables.depthFirstViewTraversalWithDistance(view)) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < viewAndDistance.getDistanceFromRoot(); i++) builder.append(" ");
|
||||
builder.append(viewAndDistance.getView().toString());
|
||||
Log.d(TAG, builder.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,11 +96,9 @@ export default class App extends React.PureComponent<{}, State> {
|
|||
<Text>{'\n'}</Text>
|
||||
{imagePath && (
|
||||
<Image
|
||||
source={
|
||||
{
|
||||
uri:
|
||||
imagePath
|
||||
}}
|
||||
source={{
|
||||
uri: imagePath,
|
||||
}}
|
||||
style={{
|
||||
height: 200,
|
||||
width: 200,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
# dumps the Android logs from the given step(s)
|
||||
|
||||
parameters:
|
||||
- name: steps
|
||||
type: stepList
|
||||
|
||||
steps:
|
||||
- task: CmdLine@2
|
||||
inputs:
|
||||
script: |
|
||||
python3 tools/python/run_adb.py logcat --clear
|
||||
displayName: "Clear Android logs"
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- ${{ parameters.steps }}
|
||||
|
||||
- task: CmdLine@2
|
||||
inputs:
|
||||
script: |
|
||||
python3 tools/python/run_adb.py logcat -d
|
||||
displayName: "Dump Android logs"
|
||||
condition: succeededOrFailed()
|
||||
|
|
@ -66,7 +66,6 @@ jobs:
|
|||
|
||||
- script: |
|
||||
python3 -m pip install -q flatbuffers
|
||||
workingDirectory: '$(Build.BinariesDirectory)'
|
||||
displayName: Install python modules
|
||||
|
||||
- script: |
|
||||
|
|
@ -144,21 +143,23 @@ jobs:
|
|||
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e/ios'
|
||||
displayName: Start iOS Simulator
|
||||
|
||||
- task: Gradle@3
|
||||
inputs:
|
||||
gradleWrapperFile: '$(Build.SourcesDirectory)/js/react_native/android/gradlew'
|
||||
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/android'
|
||||
options: '--stacktrace'
|
||||
tasks: 'connectedDebugAndroidTest'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
testRunTitle: 'React Native Android Instrumented Test results'
|
||||
javaHomeOption: 'path'
|
||||
jdkDirectory: '$(JAVA_HOME_11_X64)'
|
||||
sonarQubeRunAnalysis: false
|
||||
spotBugsAnalysis: false
|
||||
displayName: Run React Native Android Instrumented Tests
|
||||
continueOnError: false
|
||||
- template: android-dump-logs-from-steps.yml
|
||||
parameters:
|
||||
steps:
|
||||
- task: Gradle@3
|
||||
inputs:
|
||||
gradleWrapperFile: '$(Build.SourcesDirectory)/js/react_native/android/gradlew'
|
||||
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/android'
|
||||
options: '--stacktrace'
|
||||
tasks: 'connectedDebugAndroidTest'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
testRunTitle: 'React Native Android Instrumented Test results'
|
||||
javaHomeOption: 'path'
|
||||
jdkDirectory: '$(JAVA_HOME_11_X64)'
|
||||
sonarQubeRunAnalysis: false
|
||||
spotBugsAnalysis: false
|
||||
displayName: Run React Native Android Instrumented Tests
|
||||
|
||||
- script: |
|
||||
pod install
|
||||
|
|
@ -229,21 +230,23 @@ jobs:
|
|||
targetFolder: $(Build.SourcesDirectory)/js/react_native/e2e/android/app/libs
|
||||
displayName: Copy Android package to Android e2e test directory
|
||||
|
||||
- task: Gradle@3
|
||||
inputs:
|
||||
gradleWrapperFile: '$(Build.SourcesDirectory)/js/react_native/e2e/android/gradlew'
|
||||
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e/android'
|
||||
options: '--stacktrace'
|
||||
tasks: ':app:connectedDebugAndroidTest'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
testRunTitle: 'React Native Android e2e Test results'
|
||||
javaHomeOption: 'path'
|
||||
jdkDirectory: '$(JAVA_HOME_11_X64)'
|
||||
sonarQubeRunAnalysis: false
|
||||
spotBugsAnalysis: false
|
||||
displayName: Run React Native Android e2e Tests
|
||||
continueOnError: false
|
||||
- template: android-dump-logs-from-steps.yml
|
||||
parameters:
|
||||
steps:
|
||||
- task: Gradle@3
|
||||
inputs:
|
||||
gradleWrapperFile: '$(Build.SourcesDirectory)/js/react_native/e2e/android/gradlew'
|
||||
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e/android'
|
||||
options: '--stacktrace'
|
||||
tasks: ':app:connectedDebugAndroidTest'
|
||||
publishJUnitResults: true
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
testRunTitle: 'React Native Android e2e Test results'
|
||||
javaHomeOption: 'path'
|
||||
jdkDirectory: '$(JAVA_HOME_11_X64)'
|
||||
sonarQubeRunAnalysis: false
|
||||
spotBugsAnalysis: false
|
||||
displayName: Run React Native Android e2e Tests
|
||||
|
||||
- script: |
|
||||
export FORCE_BUNDLING=1
|
||||
|
|
|
|||
35
tools/python/run_adb.py
Executable file
35
tools/python/run_adb.py
Executable file
|
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import typing
|
||||
|
||||
from util import run
|
||||
from util.android import get_sdk_tool_paths
|
||||
|
||||
|
||||
def run_adb(android_sdk_root: str, args: typing.List[str]):
|
||||
sdk_tool_paths = get_sdk_tool_paths(android_sdk_root)
|
||||
run(sdk_tool_paths.adb, *args)
|
||||
|
||||
|
||||
def main():
|
||||
logging.getLogger().setLevel(logging.WARNING)
|
||||
|
||||
adb_args = sys.argv[1:]
|
||||
|
||||
android_sdk_root = os.environ.get("ANDROID_HOME") or os.environ.get("ANDROID_SDK_ROOT")
|
||||
if android_sdk_root is None:
|
||||
raise RuntimeError(
|
||||
"Please provide the Android SDK root with environment variable 'ANDROID_HOME' or "
|
||||
"environment variable 'ANDROID_SDK_ROOT'."
|
||||
)
|
||||
|
||||
run_adb(android_sdk_root, adb_args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Reference in a new issue