From f827f7b79a1f8a5c575d1e4270da61095b08a5cc Mon Sep 17 00:00:00 2001 From: Konstantin Raev Date: Wed, 2 Mar 2016 06:55:09 -0800 Subject: [PATCH] instrumentation tests are executed with BUCK Summary:Added ability to run instrumentation tests with BUCK. This change uses BUCK to build and run instrumentation tests facebook style. The gains are that we can execute the same tests internally at FB and in OSS. Also running tests not via graddle:connect command is 1.5 minutes faster. I'll keep keep an eye on stability Gradle and BUCK builds for a while. Closes https://github.com/facebook/react-native/pull/6176 Differential Revision: D2999878 Pulled By: bestander fb-gh-sync-id: d715ba231769e57100685a1256f2e530c589921c shipit-source-id: d715ba231769e57100685a1256f2e530c589921c --- ReactAndroid/build.gradle | 2 +- .../src/androidTest/AndroidManifest.xml | 6 +- ReactAndroid/src/androidTest/BUCK_temp | 66 ------------------- ReactAndroid/src/androidTest/assets/BUCK | 5 ++ .../buck-runner/AndroidManifest.xml | 24 +++++++ ReactAndroid/src/androidTest/buck-runner/BUCK | 23 +++++++ ReactAndroid/src/androidTest/buildBundle.sh | 4 -- circle.yml | 24 ++++--- scripts/run-android-instrumentation-tests.sh | 52 +++++++++++++++ 9 files changed, 123 insertions(+), 83 deletions(-) delete mode 100644 ReactAndroid/src/androidTest/BUCK_temp create mode 100644 ReactAndroid/src/androidTest/assets/BUCK create mode 100644 ReactAndroid/src/androidTest/buck-runner/AndroidManifest.xml create mode 100644 ReactAndroid/src/androidTest/buck-runner/BUCK delete mode 100755 ReactAndroid/src/androidTest/buildBundle.sh create mode 100755 scripts/run-android-instrumentation-tests.sh diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index e6fc06a58..8f26d7997 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -224,7 +224,7 @@ android { } buildConfigField 'boolean', 'IS_INTERNAL_BUILD', 'false' - testApplicationId "com.facebook.react.tests" + testApplicationId "com.facebook.react.tests.gradle" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } diff --git a/ReactAndroid/src/androidTest/AndroidManifest.xml b/ReactAndroid/src/androidTest/AndroidManifest.xml index 4275a7ea6..f23091978 100644 --- a/ReactAndroid/src/androidTest/AndroidManifest.xml +++ b/ReactAndroid/src/androidTest/AndroidManifest.xml @@ -1,6 +1,6 @@ @@ -12,8 +12,8 @@ diff --git a/ReactAndroid/src/androidTest/BUCK_temp b/ReactAndroid/src/androidTest/BUCK_temp deleted file mode 100644 index d33209ced..000000000 --- a/ReactAndroid/src/androidTest/BUCK_temp +++ /dev/null @@ -1,66 +0,0 @@ -include_defs('//ReactAndroid/DEFS') - - -CATALYST_PRIMERY_DEX_PATTERNS = [ - '/CatalystAppShell^', - '/CatalystApplicationImpl^', - '^com/facebook/buck/android/support/exopackage/', - '/FbInstrumentationTestRunner^', - '/PrimaryDexFactories^', - '/Screenshot^', - '/DexmakerMockMaker^', - '/AndroidJUnitRunner^', - '/InstrumentationRunListener^', - '/ExposedInstrumentationApi^', - '/TestApplication^', - '/ApplicationWithInjector^', - '/RunListener^', -] - -JS_BUNDLE_DEPS = [ - #':intern-schema', -# '//java/com/facebook/graphql:schema', -# '//java/com/facebook/graphql/graphql-data:locate_node' -] - - -# instrumentation tests that will run for tests located in GitHub open sourced folder -android_binary ( - name = 'react_oss', - manifest = 'AndroidManifest.xml', - keystore = '//keystores:debug', - use_split_dex = True, - linear_alloc_hard_limit = 10 * 1024 * 1024, - primary_dex_patterns = CATALYST_PRIMERY_DEX_PATTERNS, - deps = [ -# ':integration_test_oss_bundle_js', - react_native_integration_tests_target('java/com/facebook/react/tests:tests'), - # '//java/com/facebook/catalyst/js/react-native-github/ReactAndroid/src/main/res:shell', - ], -) - -# Building this rule will produce a file named messenger_test.apk -android_instrumentation_apk( - name = 'react_oss_test_apk', - manifest = 'AndroidManifest.xml', - apk = ':react_oss', - deps = [ -# react_native_integration_tests_target('java/com/facebook/react/tests:tests'), - # react_native_integration_tests_target('java/com/facebook/react/tests:tests'), - # '//java/com/facebook/catalyst:integration_test_oss_bundle_js#dev', - ], -) - - - -android_instrumentation_test( - name = 'react_oss_test', - apk = ':react_oss_test_apk', -) - -sh_binary( - name = 'integration_test_oss_bundle_js', - main = 'buildBundle.sh', -# deps = [':InstallReactNativeNodeModules'], - visibility = ['PUBLIC'], -) diff --git a/ReactAndroid/src/androidTest/assets/BUCK b/ReactAndroid/src/androidTest/assets/BUCK new file mode 100644 index 000000000..4648c5ef9 --- /dev/null +++ b/ReactAndroid/src/androidTest/assets/BUCK @@ -0,0 +1,5 @@ +android_resource( + name = 'assets', + assets = '.', + visibility = ['PUBLIC'], +) diff --git a/ReactAndroid/src/androidTest/buck-runner/AndroidManifest.xml b/ReactAndroid/src/androidTest/buck-runner/AndroidManifest.xml new file mode 100644 index 000000000..8220d4fb4 --- /dev/null +++ b/ReactAndroid/src/androidTest/buck-runner/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/ReactAndroid/src/androidTest/buck-runner/BUCK b/ReactAndroid/src/androidTest/buck-runner/BUCK new file mode 100644 index 000000000..337e846c1 --- /dev/null +++ b/ReactAndroid/src/androidTest/buck-runner/BUCK @@ -0,0 +1,23 @@ +include_defs('//ReactAndroid/DEFS') + +# We are running instrumentation tests in simple mode: app code and instrumentation are in the same APK +# Currently you need to run these commands to execute tests: +# +# node local-cli/cli.js bundle --platform android --dev true --entry-file ReactAndroid/src/androidTest/assets/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js +# gradle :ReactAndroid:packageReactNdkLibsForBuck +# buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests +# ./scripts/run-android-instrumentation-tests.sh com.facebook.react.tests +android_binary( + name = 'instrumentation-tests', + manifest = 'AndroidManifest.xml', + keystore = '//keystores:debug', + deps = [ + react_native_integration_tests_target('java/com/facebook/react/tests:tests'), + react_native_integration_tests_target('assets:assets'), + react_native_target('jni/prebuilt:reactnative-libs'), + react_native_target('jni/prebuilt:android-jsc'), + react_native_dep('libraries/soloader/java/com/facebook/soloader:soloader'), + react_native_target('java/com/facebook/react/devsupport:devsupport'), + ], +) + diff --git a/ReactAndroid/src/androidTest/buildBundle.sh b/ReactAndroid/src/androidTest/buildBundle.sh deleted file mode 100755 index 6a61faa90..000000000 --- a/ReactAndroid/src/androidTest/buildBundle.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -# TODO put output to temp folder? -node ./local-cli/cli.js bundle --entry-file ReactAndroid/src/androidTest/assets/TestBundle.js --dev --platform android --bundle-output ReactAndroid/src/androidTest/assets/ReactAndroidTestBundle.js diff --git a/circle.yml b/circle.yml index 7500233d0..f16f69e1e 100644 --- a/circle.yml +++ b/circle.yml @@ -38,25 +38,29 @@ test: # starting emulator in advance because it takes very long to boot - $ANDROID_HOME/tools/emulator -avd testAVD -no-skin -no-audio -no-window: background: true - # assemble done separately because it requires quite a lot of memory and also gives time for emulator to load - - ./gradlew :ReactAndroid:assembleDebug -PdisablePreDex -Pjobs=1: - timeout: 360 - source scripts/circle-ci-android-setup.sh && waitForAVD override: - # buck tests - - buck/bin/buck test ReactAndroid/src/test/... --config build.threads=1 + # build app - buck/bin/buck build ReactAndroid/src/main/java/com/facebook/react - buck/bin/buck build ReactAndroid/src/main/java/com/facebook/react/shell - # temp, we can't run instrumentation tests yet - - buck/bin/buck build ReactAndroid/src/androidTest/java/com/facebook/react/tests # unit tests - - ./gradlew :ReactAndroid:testDebugUnitTest -PdisablePreDex + - buck/bin/buck test ReactAndroid/src/test/... --config build.threads=1 + # instrumentation tests + # compile native libs with Gradle script + - ./gradlew :ReactAndroid:packageReactNdkLibsForBuck -PdisablePreDex -Pjobs=1: + timeout: 360 # build JS bundle for instrumentation tests - node local-cli/cli.js bundle --platform android --dev true --entry-file ReactAndroid/src/androidTest/assets/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js - # run tests on the emulator + # build test APK + - buck/bin/buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=1 + # run installed apk with tests + - ./scripts/run-android-instrumentation-tests.sh com.facebook.react.tests + + # Deprecated: run tests with Gradle, we keep them for a while to compare performance + - ./gradlew :ReactAndroid:testDebugUnitTest -PdisablePreDex - ./gradlew :ReactAndroid:connectedAndroidTest -PdisablePreDex --stacktrace --info: timeout: 360 @@ -67,6 +71,8 @@ test: - mkdir -p $CIRCLE_TEST_REPORTS/junit/ - find . -type f -regex ".*/build/test-results/debug/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \; - find . -type f -regex ".*/outputs/androidTest-results/connected/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \; + # TODO circle does not understand Buck's report, maybe need to transform xml slightly + #- find . -type f -regex ".*/buck-out/gen/ReactAndroid/src/test/.*/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \; deployment: website: diff --git a/scripts/run-android-instrumentation-tests.sh b/scripts/run-android-instrumentation-tests.sh new file mode 100755 index 000000000..fb2960847 --- /dev/null +++ b/scripts/run-android-instrumentation-tests.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +export PATH="$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools:$PATH" + +# clear the logs +adb logcat -c + +# run tests and check output +python - $1 << END +import re +import subprocess as sp +import sys +import threading +import time + +done = False +test_app = sys.argv[1] + +def update(): + # prevent CircleCI from killing the process for inactivity + while not done: + time.sleep(5) + print "Running in background. Waiting for 'adb' command reponse..." + +t = threading.Thread(target=update) +t.dameon = True +t.start() + +def run(): + sp.Popen(['adb', 'wait-for-device']).communicate() + p = sp.Popen('adb shell am instrument -w %s/android.support.test.runner.AndroidJUnitRunner' % test_app, + shell=True, stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE) + return p.communicate() + +success = re.compile(r'OK \(\d+ tests\)') +stdout, stderr = run() + +done = True +print stderr +print stdout + +if success.search(stderr + stdout): + sys.exit(0) +else: + # dump the logs + sp.Popen(['adb', 'logcat', '-d']).communicate() + sys.exit(1) # make sure we fail if the test failed +END + +RETVAL=$? + +exit $RETVAL