Let’s start with some batch basics. If you are already familiar with them skip this section.
- @echo off – Should be added at the top of your batch script to prevent printing all commands.
- echo Some text – Output: “Some text”
- echo. – Empty line
- set /a index=0 – Set numeric variable
- echo Index is %index% – Output: “Index is 0”
- Rem It is a comment
- :: It is a comment too
- echo Some text>> test.txt – Write “Some text” to test.txt file.
Functions
To declare a function we use ” : ” and the name of a function. And to mark the end of a function we add: EXIT /B 0
:PrintMyName
echo Alexey Korolev
EXIT /B 0
As you guessed this function will print my name. You will ask how we can call functions: CALL : PrintMyName
Functions with arguments
The parameters in the function are marked as %~1, %~2, %~3
If we want to call the function bellow: CALL : PrintHeader “Param1”
:PrintHeader
echo ==================================================
echo %~1
echo ==================================================
EXIT /B 0
Separating functions from the main code
@echo off
echo Main code it here
CALL : PrintHeader "Param1"
:: This line should be added before your funcitons
EXIT /B %ERRORLEVEL%
:PrintHeader
echo ==== %~1 ====
EXIT /B 0
For Loops
There is a lot of them, but we will cover only the ones we need.
Get the output of some command line by line
for /f %%i in ('adb shell pm list packages') do (
echo %%i
)
The code below will print all the packages are existing on your device. And the following code will show us how we check if some package existent/installed on a device:
for /f %%i in ('adb shell pm list packages ^| findstr com.example.app') do (
set isExist=%%i
)
if defined isExist (echo Installed) else (echo Not installed)
List iteration with for
set "someList=FirestElement SecondElement ThirdElement"
for %%x in (%someList%) do (
echo %%x
)
For loop with index
- Delayed Expansion will cause variables within a batch file to be expanded at execution time rather than at parse time, this option is turned on with the SETLOCAL EnableDelayedExpansion command.
- When the delayed expansion is in effect, variables can be immediately read using !variable_name! you can still read and use %variable_name% but that will continue to show the initial value
SETLOCAL EnableDelayedExpansion
set /a index=0
for %%x in (%someList%) do (
echo !index! - %%x
set /a index=!index! + 1
)
ENDLOCAL
Run tests from multiple modules
First, we will declare variables with project location, APKs locations and more.
@echo off
:: Project folder
set DIR=%USERPROFILE%/AndroidStudioProjects/project_folder
:: Locations of APK files used for tests
set APK1=%DIR%/module_name/build/outputs/apk/androidTest/debug/module_name-debug-androidTest.apk
set APK2=%DIR%/module_name_2/build/outputs/apk/androidTest/debug/module_name_2-debug-androidTest.apk
:: Location on device where we will push APKs before installing
set TMP1=/data/local/tmp/app.example.com.module_name
set TMP2=/data/local/tmp/app.example.com.module_name_2
:: Test package name
set PCKG1=app.example.com.module_name.test
set PCKG2=app.example.com.module_name_2.test
:: Packages prefixes, used when we call for tests
set PREFIX=com.example.app.
set PREFIX2=com.example.app2.
:: Path for JUnit Runners
set androidJUnitRunnerPath1=app.example.com.module_name.test/android.support.test.runner.AndroidJUnitRunner
set androidJUnitRunnerPath2=app.example.com.module_name2.test/androidx.test.runner.AndroidJUnitRunner
Git pull
echo Pull project from GIT...
git pull
Header printing function
:: ============== FUNCTIONS ===================
EXIT /B %ERRORLEVEL%
:PrintHeader
echo. & echo ==================================================
echo %~1
echo ================================================== & echo.
EXIT /B 0
Gradle task function
:GradleTasks
CALL :PrintHeader "Gradle tasks - clean task"
cd..
call gradlew clean
cls & CALL :PrintHeader "Gradle tasks - assembleDebug task"
call gradlew assembleDebug
cls & CALL :PrintHeader "Gradle tasks - assembleDebugAndroidTest task"
call gradlew assembleDebugAndroidTest
cd scripts
cls
EXIT /B 0
Set a list with tests names
echo Pull project from GIT...
git pull
:: gradlew clean + assembleDebug + assembleDebugAndroidTest
CALL :GradleTasks
SETLOCAL EnableDelayedExpansion
set "testArr=FirstTest SecondTest ThirdTest"
ENDLOCAL
A function that prepares APK for test
As a first argument, we need to pass a package name of the test module. As a second argument, we pass APK location and finally as a third argument we pass a location where APK would be saved on the device. The fourth argument is just a title for the log. The fifth is a variable that allows us to know if the function succeeded.
:PrepareApkForTests
CALL :PrintHeader "Running %~4 tests"
echo Check if APK exist in project folder...
if exist %~2 (echo APK exist) else (
echo APK not exist. Break.
EXIT /B 0
)
echo. & echo Uploading the apk into the device...
adb push %~2 %~3
echo. & echo Uninstalling current project if exist...
adb shell pm uninstall %~1
echo. & echo Installing the apk...
adb shell pm install -t -r %~3
set %~5=1
EXIT /B 0
A method running the tests
Ad a first argument we pass a PREFIX, as a second argument we pass android JUnit Runner Path. And the third argument is a list of tests.
:RunTests
echo. & echo Run all tests on the device... & echo.
:: Back button click - Exit from screen saver
adb shell input keyevent 4
set /a i=0
for %%x in (%*) do (
if !i! gtr 1 (
echo Execute: %~1%%x...
set /a index=0
for /f "tokens=*" %%k in ('adb shell am instrument -w -r -e debug false -e class %~1%%x %~2') do (
::echo !index! - %%k
set result[!index!]=%%k
set /a index=!index! + 1
(echo %%k | findstr /i /c:"OK" >nul) && (set isTestPassed=true)
)
if defined isTestPassed (echo Test OK) else (
echo Test failed
set /a index=!index! - 1
for /L %%f in (0,1,!index!) do (
::echo !result[%%f]!
echo !result[%%f]!>> logs.txt
)
)
)
set /a i=!i! + 1
)
EXIT /B 0
Final code
@echo off
:: ============== VARIABLES===================
:: Variables are here
:: ============== MAIN CODE===================
echo Pull project from GIT...
git pull
:: gradlew clean + assembleDebug + assembleDebugAndroidTest
CALL :GradleTasks
SETLOCAL EnableDelayedExpansion
set "testArr=FirstTest SecondTest ThirdTest"
CALL :PrepareApkForTests %PCKG1% %APK1% %TMP1% "Test 1" ok
if defined ok (CALL :RunTests %PREFIX% %androidJUnitRunnerPath1% %testArr%)
ENDLOCAL
SETLOCAL EnableDelayedExpansion
set "testArr=FirstTest SecondTest ThirdTest"
CALL :PrepareApkForTests %PCKG2% %APK2% %TMP2% "Test 2" ok
if defined ok (CALL :RunTests %PREFIX2% %androidJUnitRunnerPath2% %testArr%)
ENDLOCAL
:: ============== FUNCTIONS ===================
EXIT /B %ERRORLEVEL%
:PrintHeader
echo. & echo ==================================================
echo %~1
echo ================================================== & echo.
EXIT /B 0
:PrepareApkForTests
CALL :PrintHeader "Running %~4 tests"
echo Check if APK exist in project folder...
if exist %~2 (echo APK exist) else (
echo APK not exist. Break.
EXIT /B 0
)
echo. & echo Uploading the apk into the device...
adb push %~2 %~3
echo. & echo Uninstalling current project if exist...
adb shell pm uninstall %~1
echo. & echo Installing the apk...
adb shell pm install -t -r %~3
set %~5=1
EXIT /B 0
:RunTests
echo. & echo Run all tests on the device... & echo.
:: Back button click - Exit from screen saver
adb shell input keyevent 4
set /a i=0
for %%x in (%*) do (
if !i! gtr 1 (
echo Execute: %~1%%x...
set /a index=0
for /f "tokens=*" %%k in ('adb shell am instrument -w -r -e debug false -e class %~1%%x %~2') do (
::echo !index! - %%k
set result[!index!]=%%k
set /a index=!index! + 1
(echo %%k | findstr /i /c:"OK" >nul) && (set isTestPassed=true)
)
if defined isTestPassed (echo Test OK) else (
echo Test failed
set /a index=!index! - 1
for /L %%f in (0,1,!index!) do (
::echo !result[%%f]!
echo !result[%%f]!>> logs.txt
)
)
)
set /a i=!i! + 1
)
EXIT /B 0
*** & amp ; => &