Skip to content

Instantly share code, notes, and snippets.

@mrk-han
Created January 9, 2020 22:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrk-han/fcc75e73eb73efc15eb518441a998703 to your computer and use it in GitHub Desktop.
Save mrk-han/fcc75e73eb73efc15eb518441a998703 to your computer and use it in GitHub Desktop.
Appium Pre-Run Script
#!/usr/bin/env bash
########################################################################
# Goal: Run this script and start automating!
# 1) Pull all changes for Appium/iOS/Android repo
# 2) Build iOS App then Copy to Appium Repo
# 3) Build Android App then Copy to Appium Repo
# 4) Allow user to choose emulator, launch emulator, install app
########################################################################
CURRENT_DIRECTORY="$(pwd)"
PARENT_DIRECTORY="$(cd ../ && pwd)"
IOS_DIR="$PARENT_DIRECTORY/iOS-repo-with-app-to-build"
ANDROID_DIR="$PARENT_DIRECTORY/android-repo-with-app-to-build"
ANDROID_APP="$CURRENT_DIRECTORY/apps/Android.apk" # For installing to emulator. (Appium automatically does this for iOS, so not needed)
APPIUM_GIT_OUTPUT=$(git pull 2>&1)
IOS_GIT_OUTPUT=$(cd "$IOS_DIR" && git pull 2>&1)
ANDROID_GIT_OUTPUT=$(cd "$ANDROID_DIR" && git pull 2>&1)
BOOT_ANIMATION=""
FAIL_COUNTER=0
SECONDS_UNTIL_TIMEOUT=60
LINE="$(printf %"$(tput cols)"s | tr " " "-")" # https://stackoverflow.com/a/42763333/9470346
ONLY_EMULATOR=false
SHOULD_BUILD_FAST=false
SHOULD_LAUNCH_EMULATOR=false
ONLY_EMULATOR=false
AVD_ARGS=" -wipe-data -no-snapshot" # You need a SPACE before the first argument. Find more args to use here: https://developer.android.com/studio/run/emulator-commandline
for arg in "$@"; do
if [ "$arg" == "--fast" ] || [ "$arg" == "-f" ]; then
SHOULD_BUILD_FAST=true
fi
if [ "$arg" == "--emulator" ] || [ "$arg" == "-e" ]; then
SHOULD_LAUNCH_EMULATOR=true
fi
if [ "$arg" == "--device" ] || [ "$arg" == "-d" ]; then
ONLY_EMULATOR=true
fi
if [ "$arg" == "-fe" ] || [ "$arg" == "-ef" ]; then
SHOULD_BUILD_FAST=true
SHOULD_LAUNCH_EMULATOR=true
fi
if [ "$arg" == "--help" ] || [ "$arg" == "-h" ]; then
echo -e "\n${LINE}"
echo "Welcome to the help menu for build.sh"
echo "${LINE}"
echo -e "\n-f or --fast will pull changes and build the Appium, iOS and Android repos"
echo -e "Usage: build.sh -f OR build.sh --fast"
echo -e "\n${LINE}"
echo -e "\n-e or --emulator will also prompt you for an emulator at the end of script if ran with --fast command"
echo -e "Usage: build.sh -e OR build.sh --emulator"
echo -e "\n${LINE}"
echo -e "\nUse -ef, -fe, or --fast --emulator to use the arguments together"
echo -e "Usage: build.sh -fe OR build.sh -ef"
echo -e "\n${LINE}"
echo -e "\nUse -d, or --device to skip everything except for the request to launch an emulator"
echo -e "This will make it easy to copy the built APK onto a new emulator to test"
echo -e "Usage: build.sh -d OR build.sh --device"
exit 1
fi
done
function pullAppiumRepo() {
branch=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p') # https://stackoverflow.com/a/2111099/9470346
echo -e "\n${LINE}"
echo -e "\nPulling Latest Appium Changes... Current Branch: ${branch}"
echo -e "\n${LINE}"
if [[ ${APPIUM_GIT_OUTPUT} =~ "fatal" ]]; then
echo -e "\n${APPIUM_GIT_OUTPUT}"
echo -e "\n Make sure you are on the VPN or check your internet connection."
echo -e "\n Exiting Script..."
exit 1
else
echo "${APPIUM_GIT_OUTPUT}"
fi
}
function requestToPullAppiumRepo() {
read -rp "${LINE}
Pull Latest Appium Changes? 1=YES , 2=NO
${LINE}
-> " answerAppium
if [[ ${answerAppium} -eq 1 ]]; then
pullAppiumRepo
fi
}
function cdIntoIosRepoAndPrintBranchInformation() {
cd "$IOS_DIR" || exit
branch=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p') # https://stackoverflow.com/a/2111099/9470346
echo -e "\n${LINE}"
echo -e "\nPulling Latest IOS Changes... Current Branch: ${branch}"
echo -e "\n${LINE}"
}
function requestToHardResetIos() {
read -rp "
Before pulling changes, do you want to erase all uncommitted files in $IOS_DIR? 1=YES , 2=NO
${LINE}
-> " answerIosHardReset
if [[ ${answerIosHardReset} -eq 1 ]]; then
echo "${LINE}"
echo "git reset --hard HEAD"
echo "${LINE}"
git reset --hard HEAD
fi
}
function pullIosChanges() {
if [[ ${IOS_GIT_OUTPUT} =~ "fatal" ]]; then
echo -e "\n${IOS_GIT_OUTPUT}"
echo -e "\n Make sure you are on the VPN or check your internet connection."
echo -e "\n Exiting Script..."
exit 1
else
echo "${IOS_GIT_OUTPUT}"
fi
}
function buildThenCopyIosApp() {
make clean
make build
echo -e "\nRemoving old *.app from apps/IOS/ folder."
rm -r "${CURRENT_DIRECTORY}"/apps/IOS/*.app
./copy_app.sh "$CURRENT_DIRECTORY"
}
function requestToBuildIos() {
read -rp "${LINE}
Build iOS? 1=YES , 2=NO
${LINE}
-> " answerIos
if [[ ${answerIos} -eq 1 ]]; then
cdIntoIosRepoAndPrintBranchInformation
requestToHardResetIos
pullIosChanges
buildThenCopyIosApp
fi
}
function cdIntoAndroidRepoAndPrintBranchInformation() {
cd "$ANDROID_DIR" || exit
branch=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p') # https://stackoverflow.com/a/2111099/9470346
echo -e "\n${LINE}"
echo -e "\nPulling Latest Android Changes... Current Branch: ${branch}"
echo -e "\n${LINE}"
}
function requestToHardResetAndroid() {
read -rp "${LINE}
Before pulling changes, do you want to erase all uncommitted files in $ANDROID_DIR? 1=YES , 2=NO
${LINE}
-> " answerAndroidHardReset
if [[ ${answerAndroidHardReset} -eq 1 ]]; then
echo "${LINE}"
echo "git reset --hard HEAD"
echo "${LINE}"
git reset --hard HEAD
fi
}
function pullAndroidChanges() {
if [[ ${ANDROID_GIT_OUTPUT} =~ "fatal" ]]; then
echo -e "\n${ANDROID_GIT_OUTPUT}"
echo -e "\n Make sure you are on the VPN or check your internet connection."
echo -e "\n Exiting Script..."
exit 1
else
echo "${ANDROID_GIT_OUTPUT}"
fi
}
function buildThenCopyAndroidApk() {
echo -e "\nRunning ./gradlew clean assembleQaAutomation"
#./gradlew clean assembleQaAutomation || exit
if ./gradlew clean assembleQaAutomation; then
echo -e "\nGradle task succeeded" >&2
echo "${LINE}"
else
echo -e "\nGradle task failed! Exiting script..." >&2
exit 1
fi
echo -e "\nRemoving old *.apk from apps/ folder."
echo "${LINE}"
rm "${CURRENT_DIRECTORY}"/apps/*.apk
# Copy Apk to Intellij from Android Studio
echo -e "\nCopying APK from Android Studio to IntelliJ..."
cp ./app/build/outputs/apk/qa/automation/*.apk "$ANDROID_APP"
}
function waitForEmulatorToStart() {
until [[ "$BOOT_ANIMATION" =~ "stopped" ]]; do
BOOT_ANIMATION=$(adb -e shell getprop init.svc.bootanim 2>&1 &) # Checks state of emulator while in the boot animation
if [[ "$BOOT_ANIMATION" =~ "device not found" || "$BOOT_ANIMATION" =~ "device offline" || "$BOOT_ANIMATION" =~ "running" ]]; then
((FAIL_COUNTER += 1))
echo -e "\nWaiting for emulator to start.. $FAIL_COUNTER"
echo "Boot Animation State: $BOOT_ANIMATION"
if [[ ${FAIL_COUNTER} -gt ${SECONDS_UNTIL_TIMEOUT} ]]; then
echo -e "\nTimeout of $SECONDS_UNTIL_TIMEOUT seconds reached; failed to start emulator"
exit 1
fi
fi
sleep 1
done
echo -e "\n${LINE}"
echo -e "\nEmulator is ready!"
}
function waitForBootAnimationThenInstall() {
# After the boot animation stops, and while the emulator is starting up there can be an error, so we attempt to install until there isn't this error.
ADB_INSTALL_OUTPUT=$(adb install -r "${ANDROID_APP}" 2>&1)
regex="Can't find service"
until ! [[ "${ADB_INSTALL_OUTPUT}" =~ $regex ]]; do
echo ""
ADB_INSTALL_OUTPUT=$(adb install -r "${ANDROID_APP}" 2>&1)
echo -e "\nRetrying..."
echo -e "\n${ADB_INSTALL_OUTPUT}"
sleep 2
done
}
function selectAndLaunchEmulator() {
# Check if the emulator command exists on path first
if ! type emulator >/dev/null; then # >/dev/null hides stdout message.
echo "emulator command not found, make sure \"export PATH=\$PATH:\$ANDROID_HOME/emulator\" is in your Bash Profile and the Android SDK Tools are installed"
exit 1
fi
if ! type mapfile >/dev/null; then
echo "${LINE}"
echo "mapfile command not found, this is usually because your bash version is outdated. please run: \"brew install bash\""
echo "${LINE}"
exit 1
fi
# Gather emulators that exist on this computer
# DEVICES=( $(emulator -list-avds 2>&1) ) # 2>&1 reroutes stderr message to same output value as stdout(&1)
mapfile -t DEVICES < <(emulator -list-avds 2>&1)
# Display list of emulators
echo -e "\nAvailable Emulators
----------------------------------------"
N=1
for DEVICE in "${DEVICES[@]}"; do # Create DEVICES Array and use [@] to allow us to iterate through it
echo "$N) $DEVICE" # Iterate through Emulators and display their name next to a number which will be how the user selects the emulator
((N = N + 1))
done
# Request user input to decide which emulator to start
read -rp "
Choose an emulator by entering a number: " emulatorNumber
# If the input is valid, launch our emulator
if [[ ${emulatorNumber} -lt ${N} ]] && [[ ${emulatorNumber} -gt 0 ]]; then
DEVICE=${DEVICES[$emulatorNumber - 1]}
# shellcheck disable=SC2086
(emulator @${DEVICE}${AVD_ARGS} >/dev/null 2>&1 &)
else
echo "Invalid Entry. Please enter the number next to the Emulator name. You entered: $emulatorNumber"
fi
}
function launchEmulatorAndInstallApk() {
selectAndLaunchEmulator
waitForEmulatorToStart
waitForBootAnimationThenInstall
}
function printHelpfulInfoEmulator() {
echo "${LINE}"
echo -e "\nInstalled $ANDROID_APP to $DEVICE with arguments:$AVD_ARGS"
echo "${LINE}"
echo -e "\nRemember to:"
echo -e "\n Start an appium server: (appium -a 127.0.0.1 -p 4723 from command line, or use appium desktop)"
echo -e "\n Start a local wiremock server (./gradlew run from command line, or run the Standalone class from Intellij in Wiremock Repo)"
echo -e "\n Adjust your config.yaml and set your schemes"
echo -e "\nAnd then you'll be ready to automate! (Appium will start your simulator automatically when you run a test)"
echo "${LINE}"
}
function printHelpfulInfoNoEmulator() {
echo "${LINE}"
echo -e "\nRemember to:"
echo -e "\n Start an emulator (Appium will start your simulator automatically when you run a test)"
echo -e "\n Start an appium server: (appium -a 127.0.0.1 -p 4723 or use appium desktop)"
echo -e "\n Start a local wiremock server (./gradlew run from command line, or run the Standalone class from Intellij in Wiremock Repo)"
echo -e "\n Adjust your config.yaml and set your schemes"
echo -e "\nAnd then you'll be ready to automate!"
echo "${LINE}"
}
function requestToLaunchEmulator() {
read -rp "${LINE}
Would you like to launch an emulator? 1=YES , 2=NO
${LINE}
-> " answerLaunchEmulator
if [[ ${answerLaunchEmulator} -eq 1 ]]; then
launchEmulatorAndInstallApk
printHelpfulInfoEmulator
else
printHelpfulInfoNoEmulator
fi
}
function requestToBuildAndroid() {
read -rp "${LINE}
Build Android? 1=YES , 2=NO
${LINE}
-> " answerAndroidBuild
if [[ ${answerAndroidBuild} -eq 1 ]]; then
cdIntoAndroidRepoAndPrintBranchInformation
requestToHardResetAndroid
pullAndroidChanges
buildThenCopyAndroidApk
requestToLaunchEmulator
fi
}
function main() {
if [[ "$ONLY_EMULATOR" == "true" ]]; then
echo "Argument -d or --device found! Only requesting to start device... "
requestToLaunchEmulator
echo "Argument -d or --device found! Do not pass this in if you want to run the normal build script. EXITING... "
exit 1
fi
if [[ "$SHOULD_BUILD_FAST" == "true" ]]; then
pullAppiumRepo
cdIntoIosRepoAndPrintBranchInformation
pullIosChanges
buildThenCopyIosApp
cdIntoAndroidRepoAndPrintBranchInformation
pullAndroidChanges
buildThenCopyAndroidApk
if [[ "$SHOULD_LAUNCH_EMULATOR" == "true" ]]; then
requestToLaunchEmulator
fi
else
requestToPullAppiumRepo
requestToBuildIos
requestToBuildAndroid
fi
}
###########################
### ENTRY POINT
###########################
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment