diff --git a/.github/workflows/android-appcenter.yml b/.github/workflows/android-browserstack.yml similarity index 59% rename from .github/workflows/android-appcenter.yml rename to .github/workflows/android-browserstack.yml index 3000e2b..107e32c 100644 --- a/.github/workflows/android-appcenter.yml +++ b/.github/workflows/android-browserstack.yml @@ -1,17 +1,17 @@ -name: Android AppCenter Tests +name: Android BrowserStack Tests on: workflow_dispatch: push: branches: [ main ] paths: - - '.github/workflows/android-appcenter.yml' + - '.github/workflows/android-browserstack.yml' - 'binding/android/KoalaTestApp/**' - 'resources/audio_samples/**' pull_request: branches: [ main, 'v[0-9]+.[0-9]+'] paths: - - '.github/workflows/android-appcenter.yml' + - '.github/workflows/android-browserstack.yml' - 'binding/android/KoalaTestApp/**' - 'resources/audio_samples/**' @@ -21,24 +21,23 @@ defaults: jobs: build: - name: Run Android Tests on AppCenter + name: Run Android Tests on BrowserStack runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up Node.js LTS - uses: actions/setup-node@v3 + - name: Installing Python + uses: actions/setup-python@v5 with: - node-version: lts/* + python-version: '3.10' + - run: + pip3 install requests - - name: Install AppCenter CLI - run: npm install -g appcenter-cli - - - name: set up JDK 11 + - name: set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' - name: Copy test_resources @@ -63,35 +62,34 @@ jobs: - name: Build androidTest run: ./gradlew assembleAndroidTest - - name: Run tests on AppCenter - run: appcenter test run espresso - --token ${{secrets.APPCENTERAPITOKEN}} - --app "Picovoice/Koala-Android" - --devices "Picovoice/android-min-max" - --app-path koala-test-app/build/outputs/apk/debug/koala-test-app-debug.apk - --test-series "koala-android" - --locale "en_US" - --build-dir koala-test-app/build/outputs/apk/androidTest/debug + - name: Run tests on BrowserStack + run: python3 ../../../script/automation/browserstack.py + --type espresso + --username "${{secrets.BROWSERSTACK_USERNAME}}" + --access_key "${{secrets.BROWSERSTACK_ACCESS_KEY}}" + --project_name "Koala-Android" + --devices "android-min-max" + --app_path "koala-test-app/build/outputs/apk/debug/koala-test-app-debug.apk" + --test_path "koala-test-app/build/outputs/apk/androidTest/debug/koala-test-app-debug-androidTest.apk" build-integ: - name: Run Android Integration Tests on AppCenter + name: Run Android Integration Tests on BrowserStack runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up Node.js LTS - uses: actions/setup-node@v3 + - name: Installing Python + uses: actions/setup-python@v5 with: - node-version: lts/* - - - name: Install AppCenter CLI - run: npm install -g appcenter-cli + python-version: '3.10' + - run: + pip3 install requests - - name: set up JDK 11 + - name: set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' - name: Copy test_resources @@ -119,12 +117,12 @@ jobs: - name: Build androidTest run: ./gradlew assembleReleaseAndroidTest -DtestBuildType=integ - - name: Run tests on AppCenter - run: appcenter test run espresso - --token ${{secrets.APPCENTERAPITOKEN}} - --app "Picovoice/Koala-Android" - --devices "Picovoice/android-min-max" - --app-path koala-test-app/build/outputs/apk/release/koala-test-app-release.apk - --test-series "koala-android" - --locale "en_US" - --build-dir koala-test-app/build/outputs/apk/androidTest/release + - name: Run tests on BrowserStack + run: python3 ../../../script/automation/browserstack.py + --type espresso + --username "${{secrets.BROWSERSTACK_USERNAME}}" + --access_key "${{secrets.BROWSERSTACK_ACCESS_KEY}}" + --project_name "Koala-Android-Integration" + --devices "android-min-max" + --app_path "koala-test-app/build/outputs/apk/release/koala-test-app-release.apk" + --test_path "koala-test-app/build/outputs/apk/androidTest/release/koala-test-app-release-androidTest.apk" diff --git a/.github/workflows/android-demos.yml b/.github/workflows/android-demos.yml index ed1844d..57dabb5 100644 --- a/.github/workflows/android-demos.yml +++ b/.github/workflows/android-demos.yml @@ -25,10 +25,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: set up JDK 11 + - name: set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' - name: Build diff --git a/.github/workflows/android-perf.yml b/.github/workflows/android-perf.yml index ba9bd6e..0132bcf 100644 --- a/.github/workflows/android-perf.yml +++ b/.github/workflows/android-perf.yml @@ -23,33 +23,30 @@ defaults: jobs: build: - name: Run Android Speed Tests on AppCenter + name: Run Android Speed Tests on BrowserStack runs-on: ubuntu-latest strategy: matrix: - device: [single-android, 32bit-android] + device: [ android-perf ] include: - - device: single-android + - device: android-perf performanceThresholdSec: 0.4 - - device: 32bit-android - performanceThresholdSec: 3.0 steps: - uses: actions/checkout@v3 - - name: Set up Node.js LTS - uses: actions/setup-node@v3 + - name: Installing Python + uses: actions/setup-python@v5 with: - node-version: lts/* + python-version: '3.10' + - run: + pip3 install requests - - name: Install AppCenter CLI - run: npm install -g appcenter-cli - - - name: set up JDK 11 + - name: set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' - name: Copy test_resources @@ -83,13 +80,13 @@ jobs: - name: Build androidTest run: ./gradlew assembleAndroidTest -DtestBuildType=perf - - name: Run tests on AppCenter - run: appcenter test run espresso - --token ${{secrets.APPCENTERAPITOKEN}} - --app "Picovoice/Koala-Android" - --devices "Picovoice/${{ matrix.device }}" - --app-path koala-test-app/build/outputs/apk/debug/koala-test-app-debug.apk - --test-series "koala-android" - --locale "en_US" - --build-dir koala-test-app/build/outputs/apk/androidTest/debug + - name: Run tests on BrowserStack + run: python3 ../../../script/automation/browserstack.py + --type espresso + --username "${{secrets.BROWSERSTACK_USERNAME}}" + --access_key "${{secrets.BROWSERSTACK_ACCESS_KEY}}" + --project_name "Koala-Android-Performance" + --devices "${{ matrix.device }}" + --app_path "koala-test-app/build/outputs/apk/debug/koala-test-app-debug.apk" + --test_path "koala-test-app/build/outputs/apk/androidTest/debug/koala-test-app-debug-androidTest.apk" diff --git a/.github/workflows/ios-appcenter.yml b/.github/workflows/ios-appcenter.yml deleted file mode 100644 index 93e014e..0000000 --- a/.github/workflows/ios-appcenter.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: iOS AppCenter Tests - -on: - workflow_dispatch: - push: - branches: [ main ] - paths: - - '.github/workflows/ios-appcenter.yml' - - 'binding/ios/KoalaAppTest/KoalaAppTestUITests/KoalaAppTestUITests.swift' - - 'binding/ios/KoalaAppTest/Podfile.lock' - pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] - paths: - - '.github/workflows/ios-appcenter.yml' - - 'binding/ios/KoalaAppTest/KoalaAppTestUITests/KoalaAppTestUITests.swift' - - 'binding/ios/KoalaAppTest/Podfile.lock' - -defaults: - run: - working-directory: binding/ios/KoalaAppTest - -jobs: - build: - name: Run iOS Tests on AppCenter - runs-on: macos-latest - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Set up Node.js LTS - uses: actions/setup-node@v3 - with: - node-version: lts/* - - - name: Install Cocoapods - run: gem install cocoapods - - - name: Install AppCenter CLI - run: npm install -g appcenter-cli - - - name: Make build dir - run: mkdir ddp - - - name: Run Cocoapods - run: pod install - - - name: Inject AppID - run: sed -i '.bak' 's:{TESTING_ACCESS_KEY_HERE}:${{secrets.PV_VALID_ACCESS_KEY}}:' - KoalaAppTestUITests/KoalaAppTestUITests.swift - - - name: XCode Build - run: xcrun xcodebuild build-for-testing - -configuration Debug - -workspace KoalaAppTest.xcworkspace - -sdk iphoneos - -scheme KoalaAppTest - -derivedDataPath ddp - CODE_SIGNING_ALLOWED=NO - - - name: Run Tests on AppCenter - run: appcenter test run xcuitest - --token ${{secrets.APPCENTERAPITOKEN}} - --app "Picovoice/Koala-iOS" - --devices "Picovoice/ios-min-max" - --test-series "koala-ios" - --locale "en_US" - --build-dir ddp/Build/Products/Debug-iphoneos diff --git a/.github/workflows/ios-browserstack.yml b/.github/workflows/ios-browserstack.yml new file mode 100644 index 0000000..40ff3af --- /dev/null +++ b/.github/workflows/ios-browserstack.yml @@ -0,0 +1,79 @@ +name: iOS BrowserStack Tests + +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - '.github/workflows/ios-browserstack.yml' + - 'binding/ios/KoalaAppTest/**' + - 'resources/audio_samples/**' + pull_request: + branches: [ main, 'v[0-9]+.[0-9]+' ] + paths: + - '.github/workflows/ios-browserstack.yml' + - 'binding/ios/KoalaAppTest/**' + - 'resources/audio_samples/**' + +defaults: + run: + working-directory: binding/ios/KoalaAppTest + +jobs: + build: + name: Run iOS Tests on BrowserStack + runs-on: macos-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Installing Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + - run: + pip3 install requests + + - name: Install Cocoapods + run: gem install cocoapods + + - name: Make build dir + run: mkdir ddp + + - name: Run Cocoapods + run: pod install + + - name: Inject AppID + run: sed -i '.bak' 's:{TESTING_ACCESS_KEY_HERE}:${{secrets.PV_VALID_ACCESS_KEY}}:' + KoalaAppTestUITests/KoalaAppTestUITests.swift + + - name: XCode Build + run: xcrun xcodebuild build-for-testing + -configuration Debug + -workspace KoalaAppTest.xcworkspace + -sdk iphoneos + -scheme KoalaAppTest + -derivedDataPath ddp + CODE_SIGNING_ALLOWED=NO + + - name: Generating ipa + run: cd ddp/Build/Products/Debug-iphoneos/ && + mkdir Payload && + cp -r KoalaAppTest.app Payload && + zip --symlinks -r KoalaAppTest.ipa Payload && + rm -r Payload + + - name: Zipping Tests + run: cd ddp/Build/Products/Debug-iphoneos/ && + zip --symlinks -r KoalaAppTestUITests.zip KoalaAppTestUITests-Runner.app + + - name: Run tests on BrowserStack + run: python3 ../../../script/automation/browserstack.py + --type xcuitest + --username "${{secrets.BROWSERSTACK_USERNAME}}" + --access_key "${{secrets.BROWSERSTACK_ACCESS_KEY}}" + --project_name "Koala-iOS" + --devices "ios-min-max" + --app_path "ddp/Build/Products/Debug-iphoneos/KoalaAppTest.ipa" + --test_path "ddp/Build/Products/Debug-iphoneos/KoalaAppTestUITests.zip" diff --git a/.github/workflows/ios-demos.yml b/.github/workflows/ios-demos.yml index a4e8d37..dccce4f 100644 --- a/.github/workflows/ios-demos.yml +++ b/.github/workflows/ios-demos.yml @@ -33,9 +33,6 @@ jobs: - name: Install Cocoapods run: gem install cocoapods - - name: Install AppCenter CLI - run: npm install -g appcenter-cli - - name: Make build dir run: mkdir ddp diff --git a/.github/workflows/ios-perf.yml b/.github/workflows/ios-perf.yml index 129c745..0c78336 100644 --- a/.github/workflows/ios-perf.yml +++ b/.github/workflows/ios-perf.yml @@ -21,7 +21,7 @@ defaults: jobs: build: - name: Run iOS Tests on AppCenter + name: Run iOS Tests on BrowserStack runs-on: macos-latest strategy: @@ -35,24 +35,23 @@ jobs: - name: Checkout uses: actions/checkout@v3 - - name: Set up Node.js LTS - uses: actions/setup-node@v3 + - name: Installing Python + uses: actions/setup-python@v5 with: - node-version: lts/* + python-version: '3.10' + - run: + pip3 install requests - name: Install Cocoapods run: gem install cocoapods - - name: Install AppCenter CLI - run: npm install -g appcenter-cli - - name: Make build dir run: mkdir ddp - name: Run Cocoapods run: pod install - - name: Inject AppID + - name: Inject AccessKey run: sed -i '.bak' 's:{TESTING_ACCESS_KEY_HERE}:${{secrets.PV_VALID_ACCESS_KEY}}:' PerformanceTest/PerformanceTest.swift @@ -61,7 +60,8 @@ jobs: PerformanceTest/PerformanceTest.swift - name: Inject Performance Threshold - run: sed -i '.bak' 's:{PROC_PERFORMANCE_THRESHOLD_SEC}:${{ matrix.searchPerformanceThresholdSec }}:' + run: sed -i '.bak' + '1,/{PROC_PERFORMANCE_THRESHOLD_SEC}/s/{PROC_PERFORMANCE_THRESHOLD_SEC}/${{ matrix.procPerformanceThresholdSec }}/' PerformanceTest/PerformanceTest.swift - name: XCode Build @@ -73,11 +73,23 @@ jobs: -derivedDataPath ddp CODE_SIGNING_ALLOWED=NO - - name: Run Tests on AppCenter - run: appcenter test run xcuitest - --token ${{secrets.APPCENTERAPITOKEN}} - --app "Picovoice/Koala-iOS" - --devices "Picovoice/${{ matrix.device }}" - --test-series "koala-ios" - --locale "en_US" - --build-dir ddp/Build/Products/Debug-iphoneos + - name: Generating ipa + run: cd ddp/Build/Products/Debug-iphoneos/ && + mkdir Payload && + cp -r KoalaAppTest.app Payload && + zip --symlinks -r KoalaAppTest.ipa Payload && + rm -r Payload + + - name: Zipping Tests + run: cd ddp/Build/Products/Debug-iphoneos/ && + zip --symlinks -r PerformanceTest.zip PerformanceTest-Runner.app + + - name: Run tests on BrowserStack + run: python3 ../../../script/automation/browserstack.py + --type xcuitest + --username "${{secrets.BROWSERSTACK_USERNAME}}" + --access_key "${{secrets.BROWSERSTACK_ACCESS_KEY}}" + --project_name "Koala-iOS-Performance" + --devices "${{ matrix.device }}" + --app_path "ddp/Build/Products/Debug-iphoneos/KoalaAppTest.ipa" + --test_path "ddp/Build/Products/Debug-iphoneos/PerformanceTest.zip" diff --git a/binding/android/KoalaTestApp/build.gradle b/binding/android/KoalaTestApp/build.gradle index 9e877c5..30bd380 100644 --- a/binding/android/KoalaTestApp/build.gradle +++ b/binding/android/KoalaTestApp/build.gradle @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. ext { - defaultTargetSdkVersion = 31 + defaultTargetSdkVersion = 33 } buildscript { @@ -9,7 +9,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.2.2' + classpath 'com.android.tools.build:gradle:8.2.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -23,6 +23,6 @@ allprojects { } } -task clean(type: Delete) { +tasks.register('clean', Delete) { delete rootProject.buildDir } diff --git a/binding/android/KoalaTestApp/gradle.properties b/binding/android/KoalaTestApp/gradle.properties index c09e1e3..683c3de 100644 --- a/binding/android/KoalaTestApp/gradle.properties +++ b/binding/android/KoalaTestApp/gradle.properties @@ -15,3 +15,6 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 # Android operating system, and which are packaged with your app"s APK # https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false diff --git a/binding/android/KoalaTestApp/gradle/wrapper/gradle-wrapper.properties b/binding/android/KoalaTestApp/gradle/wrapper/gradle-wrapper.properties index 3fadc5c..3d63a90 100644 --- a/binding/android/KoalaTestApp/gradle/wrapper/gradle-wrapper.properties +++ b/binding/android/KoalaTestApp/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Jun 29 23:02:09 PDT 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/binding/android/KoalaTestApp/koala-test-app/build.gradle b/binding/android/KoalaTestApp/koala-test-app/build.gradle index f41fde6..827225c 100644 --- a/binding/android/KoalaTestApp/koala-test-app/build.gradle +++ b/binding/android/KoalaTestApp/koala-test-app/build.gradle @@ -28,7 +28,7 @@ if (rootProject.file("local.properties").exists()) { } android { - compileSdkVersion defaultTargetSdkVersion + compileSdk defaultTargetSdkVersion defaultConfig { applicationId "ai.picovoice.koala.testapp" @@ -104,6 +104,7 @@ android { lint { abortOnError false } + namespace 'ai.picovoice.koala.testapp' } dependencies { @@ -119,13 +120,16 @@ dependencies { androidTestImplementation('androidx.test.espresso:espresso-core:3.2.0', { exclude group: 'com.android.support', module: 'support-annotations' }) - androidTestImplementation('com.microsoft.appcenter:espresso-test-extension:1.4') androidTestImplementation('androidx.test.espresso:espresso-intents:3.5.1') } afterEvaluate { tasks."mergeDebugAssets".dependsOn "copyParams" tasks."mergeReleaseAssets".dependsOn "copyParams" + tasks."generateReleaseLintVitalReportModel".dependsOn "copyParams" + tasks."lintVitalAnalyzeRelease".dependsOn "copyParams" tasks."mergeDebugAssets".dependsOn "copyAudio" tasks."mergeReleaseAssets".dependsOn "copyAudio" + tasks."generateReleaseLintVitalReportModel".dependsOn "copyAudio" + tasks."lintVitalAnalyzeRelease".dependsOn "copyAudio" } diff --git a/binding/android/KoalaTestApp/koala-test-app/src/androidTest/java/ai/picovoice/koala/testapp/IntegrationTest.java b/binding/android/KoalaTestApp/koala-test-app/src/androidTest/java/ai/picovoice/koala/testapp/IntegrationTest.java index ba7e18f..8cdba27 100644 --- a/binding/android/KoalaTestApp/koala-test-app/src/androidTest/java/ai/picovoice/koala/testapp/IntegrationTest.java +++ b/binding/android/KoalaTestApp/koala-test-app/src/androidTest/java/ai/picovoice/koala/testapp/IntegrationTest.java @@ -16,9 +16,6 @@ import androidx.test.ext.junit.rules.ActivityScenarioRule; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.microsoft.appcenter.espresso.Factory; -import com.microsoft.appcenter.espresso.ReportHelper; - import org.hamcrest.Matcher; import org.junit.After; import org.junit.Before; @@ -74,9 +71,6 @@ public void perform(UiController uiController, View view) { @RunWith(AndroidJUnit4.class) public class IntegrationTest { - @Rule - public ReportHelper reportHelper = Factory.getReportHelper(); - @Rule public ActivityScenarioRule activityScenarioRule = new ActivityScenarioRule<>(MainActivity.class); @@ -91,11 +85,6 @@ public void intentsTeardown() { Intents.release(); } - @After - public void TearDown() { - reportHelper.label("Stopping App"); - } - @Test public void testKoala() { onView(withId(R.id.testButton)).perform(click()); diff --git a/binding/android/KoalaTestApp/koala-test-app/src/androidTest/java/ai/picovoice/koala/testapp/KoalaTest.java b/binding/android/KoalaTestApp/koala-test-app/src/androidTest/java/ai/picovoice/koala/testapp/KoalaTest.java index b2be5df..18eac6f 100644 --- a/binding/android/KoalaTestApp/koala-test-app/src/androidTest/java/ai/picovoice/koala/testapp/KoalaTest.java +++ b/binding/android/KoalaTestApp/koala-test-app/src/androidTest/java/ai/picovoice/koala/testapp/KoalaTest.java @@ -18,9 +18,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; -import com.microsoft.appcenter.espresso.Factory; -import com.microsoft.appcenter.espresso.ReportHelper; - import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -51,8 +48,6 @@ @RunWith(AndroidJUnit4.class) public class KoalaTest { - @Rule - public ReportHelper reportHelper = Factory.getReportHelper(); Context testContext; Context appContext; AssetManager assetManager; @@ -60,11 +55,6 @@ public class KoalaTest { String accessKey = ""; - @After - public void TearDown() { - reportHelper.label("Stopping App"); - } - @Before public void Setup() throws IOException { testContext = InstrumentationRegistry.getInstrumentation().getContext(); diff --git a/binding/android/KoalaTestApp/koala-test-app/src/androidTest/java/ai/picovoice/koala/testapp/PerformanceTest.java b/binding/android/KoalaTestApp/koala-test-app/src/androidTest/java/ai/picovoice/koala/testapp/PerformanceTest.java index 02767a2..782dc0e 100644 --- a/binding/android/KoalaTestApp/koala-test-app/src/androidTest/java/ai/picovoice/koala/testapp/PerformanceTest.java +++ b/binding/android/KoalaTestApp/koala-test-app/src/androidTest/java/ai/picovoice/koala/testapp/PerformanceTest.java @@ -19,9 +19,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; -import com.microsoft.appcenter.espresso.Factory; -import com.microsoft.appcenter.espresso.ReportHelper; - import org.junit.After; import org.junit.Assume; import org.junit.Before; @@ -44,19 +41,13 @@ @RunWith(AndroidJUnit4.class) public class PerformanceTest { - @Rule - public ReportHelper reportHelper = Factory.getReportHelper(); + Context testContext; Context appContext; AssetManager assetManager; String testResourcesPath; String accessKey; - @After - public void TearDown() { - reportHelper.label("Stopping App"); - } - @Before public void Setup() throws IOException { testContext = InstrumentationRegistry.getInstrumentation().getContext(); diff --git a/binding/android/KoalaTestApp/koala-test-app/src/main/AndroidManifest.xml b/binding/android/KoalaTestApp/koala-test-app/src/main/AndroidManifest.xml index 194bafb..da0648b 100644 --- a/binding/android/KoalaTestApp/koala-test-app/src/main/AndroidManifest.xml +++ b/binding/android/KoalaTestApp/koala-test-app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + diff --git a/resources/.lint/spell-check/dict.txt b/resources/.lint/spell-check/dict.txt index 2665e38..aa23396 100644 --- a/resources/.lint/spell-check/dict.txt +++ b/resources/.lint/spell-check/dict.txt @@ -44,4 +44,5 @@ styleable testapp wargv wchars +xcuitest xcworkspace diff --git a/script/automation/browserstack.py b/script/automation/browserstack.py new file mode 100644 index 0000000..54c0e77 --- /dev/null +++ b/script/automation/browserstack.py @@ -0,0 +1,136 @@ +import argparse +import requests +import time + +APP_URI = 'https://api-cloud.browserstack.com/app-automate/{}/v2/app' +TEST_URI = 'https://api-cloud.browserstack.com/app-automate/{}/v2/test-suite' +BUILD_URI = 'https://api-cloud.browserstack.com/app-automate/{}/v2/build' +STATUS_URI = 'https://api-cloud.browserstack.com/app-automate/{}/v2/builds/{}' + +devices_dict = { + 'android-min-max': [ + 'Samsung Galaxy S8-7.0', + 'Samsung Galaxy M52-11.0', + 'Google Pixel 9-15.0' + ], + 'android-perf': [ + 'Google Pixel 6 Pro-15.0' + ], + 'ios-min-max': [ + 'iPhone SE 2022-15', + 'iPhone 14 Plus-16', + 'iPhone 14-18' + ], + 'ios-perf': [ + 'iPhone 13-18', + ] +} + + +def main(args: argparse.Namespace) -> None: + app_files = { + 'file': open(args.app_path, 'rb') + } + + app_response = requests.post( + APP_URI.format(args.type), + files=app_files, + auth=(args.username, args.access_key) + ) + app_response_json = app_response.json() + + if not app_response.ok: + print('App Upload Failed', app_response_json) + exit(1) + + test_files = { + 'file': open(args.test_path, 'rb') + } + test_response = requests.post( + TEST_URI.format(args.type), + files=test_files, + auth=(args.username, args.access_key) + ) + test_response_json = test_response.json() + + if not test_response.ok: + print('Test Upload Failed', test_response_json) + exit(1) + + build_headers = { + 'Content-Type': 'application/json' + } + build_data = { + 'app': app_response_json['app_url'], + 'testSuite': test_response_json['test_suite_url'], + 'project': args.project_name, + 'devices': devices_dict[args.devices], + 'deviceLogs': True + } + + while True: + build_response = requests.post( + BUILD_URI.format(args.type), + headers=build_headers, + json=build_data, + auth=(args.username, args.access_key) + ) + if (build_response is not None and 'message' in build_response.json() and '[BROWSERSTACK_ALL_PARALLELS_IN_USE]' + in build_response.json()['message']): + print('Parallel threads limit reached. Waiting...', flush=True) + time.sleep(60) + else: + break + + if build_response is None: + print('Build Failed') + exit(1) + + build_response_json = build_response.json() + + if not build_response.ok: + print('Build Failed', build_response.json()) + exit(1) + + if build_response_json['message'] != 'Success': + print('Build Unsuccessful') + exit(1) + + print( + 'View build results at https://app-automate.browserstack.com/dashboard/v2/builds/{}' + .format(build_response_json['build_id'])) + + while True: + time.sleep(60) + status_response = requests.get( + STATUS_URI.format(args.type, build_response_json['build_id']), + auth=(args.username, args.access_key) + ) + status_response_json = status_response.json() + status = status_response_json['status'] + + if not status_response.ok: + print('Status Request Failed', status_response_json) + exit(1) + + if status != 'queued' and status != 'running': + break + + print('Status:', status) + if status != 'passed': + exit(1) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--type', choices=['espresso', 'xcuitest'], required=True) + parser.add_argument('--username', required=True) + parser.add_argument('--access_key', required=True) + + parser.add_argument('--project_name', required=True) + parser.add_argument('--devices', choices=devices_dict.keys(), required=True) + parser.add_argument('--app_path', required=True) + parser.add_argument('--test_path', required=True) + args = parser.parse_args() + + main(args)