Last active
June 28, 2016 11:41
-
-
Save roubachof/47b974d576d722dc0c01 to your computer and use it in GitHub Desktop.
Continuous Integration with Xamarin: launch emulator, copy apk, launch activity, retrieve test results as xml.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Notes: | |
# | |
# - 10/06/16 | |
# - the script attempts to connect to the first active Android emulator | |
# found in the list returned by the "adb devices" command, and launches it, if this list is empty. | |
# In this case, the AVD launched is the first .ini file found in the directory. | |
# | |
# paramètres (exemple): | |
# .\launch-emulator.ps1 | |
# -tcpListenerPath .\Stago.Mhp.Instr.Pocm.UnitTests.Droid.Server.exe | |
# -tcpListenerIp 127.0.0.1 | |
# -tcpListenerPort 13000 | |
# -packageName Stago.Mhp.Instr.Pocm.UnitTests.Droid | |
# -activityName stago.mhp.instr.pocm.unitTests.droid.mainActivity | |
# [option] -avdName Nexus-S-API22-ARM | |
# [option] -outXmlReportPath ..\..\artifacts\DroidTestResults.xml | |
# [option] -logServerTimeoutInSeconds 1200 | |
# [option] -apkName xxxx-Signed.pak | |
# powershell.exe -noprofile -executionpolicy bypass -file .\launch-emulator.ps1 -tcpListenerPath .\Stago.Mhp.Instr.Pocm.UnitTests.Droid.Server.exe -tcpListenerIp 127.0.0.1 -tcpListenerPort 13000 -packageName Stago.Mhp.Instr.Pocm.UnitTests.Droid -activityName stago.mhp.instr.pocm.unitTests.droid.mainActivity -outXmlReportPath ..\..\artifacts\DroidTestResults.xml -logServerTimeoutInSeconds 1200 | |
[CmdletBinding()] | |
Param( | |
[Parameter(Mandatory=$True)] | |
[string]$tcpListenerPath, | |
[Parameter(Mandatory=$True)] | |
[string]$tcpListenerIp, | |
[Parameter(Mandatory=$True)] | |
[int]$tcpListenerPort, | |
[Parameter(Mandatory=$True)] | |
[string]$packageName, | |
[Parameter(Mandatory=$True)] | |
[string]$activityName, | |
[string]$avdName, | |
[string]$apkName, | |
[string]$outXmlReportPath, | |
[int]$logServerTimeoutInSeconds | |
) | |
try | |
{ | |
#region --- try | |
Write-Host "Version=1.0.503" | |
Write-Host "" | |
# | |
# IMPORTANT: cleanup des process 'adb', 'emulator', ... | |
# | |
Write-Host "Get-Process emulator*, adb*(0)" | |
Get-Process emulator*, adb* | |
Write-Host "-------------------------------" | |
Get-Process emulator*, adb* | Stop-Process | |
Write-Host "Get-Process emulator*, adb*(1)" | |
Get-Process emulator*, adb* | |
Write-Host "-------------------------------" | |
#region --- Prepare environment | |
# Add needed pathes | |
Write-Host "Adding the needed paths to the process environment path" | |
$VerifiedPathsToAdd = $Null | |
$PathToAdd = @( | |
"C:\Users\AgentTeamcity\AppData\Local\Android\android-sdk\platform-tools", | |
"C:\Users\AgentTeamcity\AppData\Local\Android\android-sdk\tools") | |
Foreach ($Path in $PathToAdd) | |
{ | |
if ($env:Path -like "*$Path*") | |
{ | |
Write-Host "$Path already exists in Path statement" | |
} | |
else | |
{ | |
$VerifiedPathsToAdd += ";$Path" | |
Write-Host "`$Path will be added to the environment path" | |
} | |
} | |
if($VerifiedPathsToAdd -ne $null) | |
{ | |
Write-Host "Adding $VerifiedPathsToAdd to Path statement now..." | |
[Environment]::SetEnvironmentVariable("Path",$env:Path + $VerifiedPathsToAdd,"Process") # replace 'Process' with [EnvironmentVariableTarget]::Machine, if you want to make this persistent | |
} | |
Write-Host "--------------------------------------------------------------------" | |
#endregion | |
#region --- Find or starts an emulator | |
# Find the emulator name is one is already running | |
Write-Host "adb devices" | |
adb devices | |
Write-Host "-------------------------------" | |
$aDevice = adb devices | |
foreach ($device in $aDevice) | |
{ | |
$position0 = $device.IndexOf("emulator") | |
if ($position0 -lt 0) | |
{ | |
continue | |
} | |
$emulator = $device.Substring($position0) | |
$position1 = $emulator.IndexOf(0x09) | |
if ($position1 -gt 0) | |
{ | |
$emulator = $emulator.Substring(0, $position1); | |
} | |
break | |
} | |
Write-Host "emulator='"$emulator"'" | |
# A running emulator wasn't found lookup in .ini file | |
if (!$emulator) | |
{ | |
#region --- Choose the AVD from .ini file | |
$avdDir = "C:\Users\AgentTeamcity\.android\avd" | |
Write-Host "Value of the avdName parameter="$avdName | |
Write-Host "----------------------------------------" | |
if (!$avdName) | |
{ | |
Write-Host "Looking for the first .ini file in the avdDir="$avdDir" directory" | |
Write-Host "--------------------------------------------------------------------" | |
$List = get-childitem $avdDir | where {$_.extension -eq ".ini"} | |
if (!$List) | |
{ | |
throw "EXIT: NO .ini file was found in the directory avdDir=" + $avdDir | |
} | |
foreach ($item in $List) | |
{ | |
$avdName = $item.BaseName | |
break | |
} | |
} | |
if (!$avdName) | |
{ | |
throw "EXIT: No AVD was found" | |
} | |
Write-Host "Effective value of the avdName="$avdName | |
Write-Host "----------------------------------------" | |
#endregion | |
#region --- Starts the emulator | |
Try | |
{ | |
Write-Host "Start-Process(-) -PassThru -FilePath emulator.exe -ArgumentList -no-boot-anim -no-window -avd="$avdName | |
$process_emulator = Start-Process -PassThru -FilePath emulator.exe -ArgumentList "-no-boot-anim -no-window -avd $avdName" | |
Write-Host "Start-Process(+) process_emulator="$process_emulator | |
} | |
Catch | |
{ | |
$ErrorMessage = $_.Exception.Message | |
$FailedItem = $_.Exception.ItemName | |
Write-Host "Start-Process(EXCEPTION) ErrorMessage="$ErrorMessage | |
} | |
if (!$process_emulator) | |
{ | |
throw "EXIT: no emulator could be launched." | |
} | |
#endregion | |
Write-Host "adb wait-for-device" | |
adb wait-for-device | |
Write-Host "--------------------------------------" | |
#region --- wait for end of boot | |
Write-Host "Waiting for the end of the boot sequence" | |
$timeout = 400 | |
for ($attempts = 0; $attempts -lt $timeout; $attempts++) | |
{ | |
$result = adb shell getprop sys.boot_completed | |
Write-Host "adb shell getprop sys.boot_completed -> " $result | |
if ($result -match "invalid|error|fail") | |
{ | |
throw "EXIT: failed to communicate with the emulator: $result" | |
} | |
Sleep 1 | |
if ($result -like "1*") | |
{ | |
"Boot sequence ended" | |
break; | |
} | |
} | |
Write-Host "--------------------------------" | |
if ($attempts -ge $timeout) | |
{ | |
throw "Timeout reached while waiting for the end of the boot sequence ($attempts attempts with a 1 second delay)" | |
} | |
#endregion | |
#region --- Get emulator name | |
Write-Host "adb devices" | |
adb devices | |
Write-Host "-------------------------------" | |
$aDevice = adb devices | |
foreach ($device in $aDevice) | |
{ | |
$position0 = $device.IndexOf("emulator") | |
if ($position0 -lt 0) | |
{ | |
continue | |
} | |
$emulator = $device.Substring($position0) | |
$position1 = $emulator.IndexOf(0x09) | |
if ($position1 -gt 0) | |
{ | |
$emulator = $emulator.Substring(0, $position1); | |
} | |
break | |
} | |
Write-Host "emulator=<<"$emulator">>" | |
#endregion | |
#endregion | |
} | |
#endregion | |
#region --- Launch log server | |
# $tcpListenerPath_name <- $tcpListenerPath, 'nettoyage' | |
$tcpListenerPath_name=$tcpListenerPath.ToUpper() | |
while ($true) | |
{ | |
if ($tcpListenerPath_name.StartsWith(".")) | |
{ | |
$tcpListenerPath_name = $tcpListenerPath_name.Substring(1) | |
continue | |
} | |
if ($tcpListenerPath_name.StartsWith("\")) | |
{ | |
$tcpListenerPath_name = $tcpListenerPath_name.Substring(1) | |
continue | |
} | |
break | |
} | |
if ($tcpListenerPath_name.EndsWith(".EXE")) | |
{ | |
$tcpListenerPath_name = $tcpListenerPath_name.Substring(0, $tcpListenerPath_name.Length - 4) | |
} | |
Write-Host "tcpListenerPath_name="$tcpListenerPath_name | |
# kill old server log process | |
$aProcess = Get-Process | |
foreach ($process in $aProcess) | |
{ | |
$processName = $process.Name.ToUpper() | |
if ($processName.Equals($tcpListenerPath_name)) | |
{ | |
Write-Host "process.Kill()="$process | |
$process.Kill() | |
} | |
} | |
Write-Host "-------------------------------" | |
Try | |
{ | |
Write-Host "Start-Process(-) -PassThru -FilePath tcpListenerPath="$tcpListenerPath | |
$process_tcpListenerPath = Start-Process -PassThru -FilePath $tcpListenerPath -ArgumentList "-hostname=$tcpListenerIp -port=$tcpListenerPort -output=$outXmlReportPath" | |
Write-Host "Start-Process(+) process_tcpListenerPath="$process_tcpListenerPath | |
} | |
Catch | |
{ | |
$ErrorMessage = $_.Exception.Message | |
$FailedItem = $_.Exception.ItemName | |
Write-Host "Start-Process(EXCEPTION) ErrorMessage="$ErrorMessage | |
} | |
if (!$process_tcpListenerPath) | |
{ | |
throw "EXIT: process_tcpListenerPath='" + $process_tcpListenerPath + "' could not be launched" | |
} | |
#endregion | |
#region --- Starting the APK | |
Write-Host "apkName(-)="$apkName | |
if (-Not $apkName) | |
{ | |
$apkName = "$packageName-Signed.apk" | |
} | |
Write-Host "apkName(+)="$apkName | |
Write-Host "-------------------------" | |
Write-Host "Unlocking the emulator screen" | |
Write-Host "adb -s $emulator shell input keyevent 82" | |
adb -s $emulator shell input keyevent 82 | |
Write-Host "-------------------------" | |
Write-Host "Trying to uninstall the package previous version" | |
Write-Host "adb -s $emulator uninstall $packageName" | |
adb -s $emulator uninstall $packageName | |
Write-Host "-------------------------" | |
Write-Host "Installing the APK" | |
Write-Host "adb -s $emulator install -r $apkName" | |
$result = adb -s $emulator install -r "$apkName" | |
if ($result -match "invalid|error|fail") | |
{ | |
throw "APK installation failed: $result" | |
} | |
Write-Host "-------------------------" | |
Write-Host "Removing the existing xml results" | |
Write-Host "adb -s $emulator shell run-as $packageName rm -fr files/NUnitTestsOutput" | |
adb -s $emulator shell run-as $packageName rm -fr files/NUnitTestsOutput | |
Write-Host "-------------------------" | |
Write-Host "Launching the test Activity" | |
"adb -s $emulator shell am start $packageName/$activityName" | |
Sleep 5 | |
$result = adb -s $emulator shell am start "$packageName/$activityName" | |
if ($result -match "invalid|error|fail") | |
{ | |
throw "Error while launching main activity: $result" | |
} | |
Write-Host "-------------------------" | |
$logServerTimeoutInSeconds = if ($logServerTimeoutInSeconds -eq 0) { 5 * 60 } else { $logServerTimeoutInSeconds } | |
Write-Host "Waiting for process $logServerProcess with timeout of $logServerTimeoutInSeconds seconds" | |
if (-Not $process_tcpListenerPath -Or -Not $process_tcpListenerPath.WaitForExit($logServerTimeoutInSeconds * 1000)) | |
{ | |
throw "The log server hasn't received any log in $logServerTimeoutInSeconds seconds: a timeout is detected" | |
} | |
Write-Host "-------------------------" | |
#endregion | |
#endregion | |
} | |
finally | |
{ | |
# | |
# IMPORTANT: cleanup processes 'adb', 'emulator', ... | |
# | |
Write-Host "Get-Process emulator*, adb*(0)" | |
Get-Process emulator*, adb* | |
Write-Host "-------------------------------" | |
Get-Process emulator*, adb* | Stop-Process | |
Write-Host "Get-Process emulator*, adb*(1)" | |
Get-Process emulator*, adb* | |
Write-Host "-------------------------------" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment