Run parallel test appium with physical devices - android

I've seen a bit everywhere the Selenium Grid solution to run parallel test but I don't know if this works with physical devices or only virtual and what I need is to test on multiple physical devices.
So I tried to do it "my way" for the moment what I have done is creating a selenium server & driver for each of my physical devices and run my tests but the main issue I encounter is that the test are not really parallel ...
Step 1 Server one open & driver one is created
Step 2 Server two open & driver two is created
Step 3 test1 start on driver one until it finish
Step 4 test1 start on driver two until it finish
Step 5 test2 start on driver one
....
Is there a way to make it really parallel ?
Here is my code :
Create server
public static AppiumServer startServer (String deviceName){
String port="";
String boostrapPort="";
switch (deviceName){
case ONEPLUS_ONE :
port = ONEPLUS_ONE_PORT;
boostrapPort = ONEPLUS_ONE_BOOTSTRAP_PORT;
break;
.....
}
ServerArguments serverArguments = new ServerArguments();
serverArguments.setArgument("--address", "127.0.0.1");
serverArguments.setArgument("--port", port);
serverArguments.setArgument("--bootstrap-port", boostrapPort);
AppiumServer appiumServer = new AppiumServer(serverArguments);
appiumServer.startServer();
return appiumServer;
}
Create driver :
#BeforeTest(alwaysRun = true)
public void setUp(){
AppiumServer samsung_S6_server = AppiumServerFactory.startServer(AppiumServerFactory.SAMSUNG_S6);
if(samsung_S6_server.isServerRunning()) {
AndroidDriver samsung_S6 = AndroidDriverFactory.getAndroidDriver(appPackage, appActivity, AppiumServerFactory.SAMSUNG_S6_PORT, AppiumServerFactory.SAMSUNG_S6);
serverList.add(samsung_S6_server);
driverList.add(samsung_S6);
} else {
System.out.println("Server running issue");
}
AppiumServer oneplus_one_server = AppiumServerFactory.startServer(AppiumServerFactory.ONEPLUS_ONE);
if(oneplus_one_server.isServerRunning()) {
AndroidDriver oneplus_one = AndroidDriverFactory.getAndroidDriver(appPackage, appActivity, AppiumServerFactory.ONEPLUS_ONE_PORT, AppiumServerFactory.ONEPLUS_ONE);
serverList.add(oneplus_one_server);
driverList.add(oneplus_one);
} else {
System.out.println("Server running issue");
}
The tests :
#Test
public void openArticle (){
for(AndroidDriver driver : driverList){
WebElement el = driver.findElements(By.id("..."));
el.click();
}
}
.....

Related

Using Appium to reboot android device results in Illegal argument exception

I am using Appium to test the App in the Android mobile phone with Android 12 version. There i have a case where i want to restart the mobile phone.
My setup is where my c# code lies in windows which in turn connected with Macbook throuh WLAN and macbook controls the Android phone through Appium. That is the reason why I cannot execute adb commands directly on the Android mobile phone.
For that i am using the Executescript function from Appium as following
driver.ExecuteScript("mobile:shell", new AdbCommand("reboot"));
But this command throws an illegal argument exception as follows
Exception thrown: 'System.ArgumentException' in WebDriver.dll
An exception of type 'System.ArgumentException' occurred in WebDriver.dll but was not handled in user code
Argument is of an illegal type{"command":"reboot","args":[]}
Relaxed security is ON and adb commands should work in this case.
Any help appreciated regarding this problem.
Regarding Adb Class which does nothing but provides a provision to enter arguments in json format in C# and this has been copied from an example from automatetheplanet.com
public class AdbCommand
{
public AdbCommand(string command)
{
Command = command;
Args = new List();
}
public AdbCommand(string command, params string[] args)
{
Command = command;
Args = new List(args);
}
[JsonProperty("command")]
public string Command { get; set; }
[JsonProperty("args")]
public List Args { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}

BLE Pairing gets stuck after Unpairing with nRF Connect App

I encountered a strange problem when trying to unpair and pair again with my smartphone. Currently I write a C# application on UWP (Windows 10) for BLE connection with a remote device. I use my smartphone with nRF Connect App as the peripheral.
After being paired for a while (and being inactive), when unpairing and pairing again, the application gets stuck when trying to pair again.
I broke everything down to the most basal application I could create. This is a Console App that scans the existing devices and then unpairs and pairs with the selected device:
using BLE_Test;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static async Task Main(string[] args)
{
Dictionary<ulong, string> uuidDict = BleModule.Scan().Result;
Console.WriteLine("Devices found:");
int i = 0;
foreach (var uuid in uuidDict.Keys)
Console.WriteLine(string.Format("ID: {0}, UUID: {1}, Local Name: {2}", i++, uuid, uuidDict[uuid]));
Console.WriteLine("Select ID!");
int id = int.Parse(Console.ReadLine());
ulong selectedUuid = (uuidDict.ElementAt(id)).Key;
await BleModule.Unpair(selectedUuid);
await BleModule.Pair(selectedUuid);
Console.ReadLine();
}
}
}
It calls an UWP DLL called "BLE_Test" with the class "BleModule":
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Enumeration;
namespace BLE_Test
{
public class BleModule
{
public static async Task<Dictionary<ulong, string>> Scan()
{
var uuidDict = new Dictionary<ulong, string>();
BluetoothLEAdvertisementWatcher watcher = new BluetoothLEAdvertisementWatcher();
watcher.Received += (BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
=> AddAdvertisement(eventArgs, uuidDict);
watcher.Start();
await Task.Delay(10000);
watcher.Stop();
return uuidDict;
}
private static void AddAdvertisement(BluetoothLEAdvertisementReceivedEventArgs eventArgs, Dictionary<ulong, string> uuidDict)
{
if (uuidDict.ContainsKey(eventArgs.BluetoothAddress) == false)
uuidDict.Add(eventArgs.BluetoothAddress, eventArgs.Advertisement.LocalName);
}
public static async Task Pair(ulong uuid)
{
Console.WriteLine("Pairing...");
var bluetoothLEDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(uuid);
if (bluetoothLEDevice == null)
{
Console.WriteLine("UUID not found!");
return;
}
DeviceInformationCustomPairing customPairing = bluetoothLEDevice.DeviceInformation.Pairing.Custom;
customPairing.PairingRequested += (DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args) => args.Accept(); // We auto-accept numeric comparison result for the sake of simplicity
DevicePairingResult result = await customPairing.PairAsync(DevicePairingKinds.ConfirmPinMatch);
Console.WriteLine("Pairing Result: " + result.Status.ToString());
}
public static async Task Unpair(ulong uuid)
{
Console.WriteLine("Unpairing...");
var bluetoothLEDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(uuid);
if (bluetoothLEDevice == null)
{
Console.WriteLine("UUID not found!");
return;
}
DeviceUnpairingResult result = await bluetoothLEDevice.DeviceInformation.Pairing.UnpairAsync();
Console.WriteLine("Unpairing Result: " + result.Status.ToString());
}
}
}
If I start the program for the first time, the pairing works fine (the unpairing will be ignored as the devices are not paired yet). If I start it immediately again afterwards, it also works fine. Unpairing and pairing will both take place. But if I wait a while (typically 5-10 minutes) while not doing anything, when I start the program again, it will unpair, but then it will wait indefinitely for PairAsync() to return. No coupling request will show on the nRF Connect App, and no PairingRequested event will appear.
Aborting the stuck program and restarting it won't help. In this case, even though the smartphone is found by the BluetoothLEAdvertisementWatcher, BluetoothLEDevice.FromBluetoothAddressAsync(uuid) will return null and the device can't be paired anymore. This can only be resolved by restarting the computer or switching off and on the advertisement in the nRF Connect App, as in this case a new random BLE Address is created for the device.
I have taken a snapshot of the BLE events using Btetlparse and Wireshark. It seems that there is a problem with a malformed package:
However, I don't really understand what is going wrong. Is this a problem of the nRF Connect App? Or the UWP commands? Or did I do something wrong? I tried two different smartphones (a Samsung Galaxy and an Oppo), so I doubt that it is a problem of the smartphone. I also added a DeviceWatcher, but this didn't change anything. Can anyone help me here?

Unity XR.Settings.LoadDeviceByName() not loading device

I have tried to use XRSettings.LoadDeviceByName() but it never work. I have already check if the parameter device name is same as the current device name but nothing changes. Also, I have added the None in the sdk list
The XRSettings.loadedDeviceName is cardboard when initiating.
IEnumerator testThis() {
if (string.Compare(XRSettings.loadedDeviceName, "", true) != 0) {
XRSettings.LoadDeviceByName("none");
some_text.text = XRSettings.loadedDeviceName;
yield return new WaitForSeconds(1);
XRSettings.enabled = true;
some_text.text = "Device name " + XRSettings.loadedDeviceName;
}
}
IEnumerator temp() {
some_text.text = "Device name " + XRSettings.loadedDeviceName;
yield return new WaitForSeconds(10);
StartCoroutine(testThis());
}
No matter how I detect, the device name is still cardboard.
https://docs.unity3d.com/ScriptReference/XR.XRSettings.LoadDeviceByName.html
What I have done:
Make None as one of the Virtual Reality SDKs
Use XR-Plugin Management
2.1 Disable Virtual Reality Supported
2.2 Convert camera to XR-Rig
2.3 Use the code about turning VR off in XR-Plugin Management
2.4 Remarks: all the procedure in step 2 is work in iOS build but fail in android build.
2.5 https://docs.unity3d.com/Packages/com.unity.xr.management#4.0/manual/index.html
Tried XRSettings.LoadDeviceByName("none"); XRSettings.LoadDeviceByName(""); XRSettings.LoadDeviceByName("None");
Make sure that ''none'' is first in your VR SDK's, Then Cardboard.
I see a problem with your compare, there is no value
if (string.Compare(XRSettings.loadedDeviceName, "", true) != 0) {
If I understand correctly what you want to do, this code down here will receive a device name and will trigger the LoadDevice couroutine with this name.
public void VerifyDeviceName(string newDeviceName)
{
if (newDeviceName == "none")
{
Debug.Log("Will load none device");
StartCoroutine(LoadDevice(newDeviceName));
}
if (newDeviceName == "cardboard")
{
Debug.Log("Will load cardboard device");
StartCoroutine(LoadDevice(newDeviceName));
}
else
{
Debug.Log("Can't find device with name " + newDeviceName);
}
}
IEnumerator LoadDevice(string newDeviceName)
{
XRSettings.LoadDeviceByName(newDeviceName);
yield return new WaitForSeconds(10);
XRSettings.enabled = true;
Debug.Log("Loaded " + newDeviceName);
}
Note; This will obviously not work in editor you wil get a message saying you cannot trigger on/off vr in editor mode.
I just got through this by brute forcing it. The secret is not to Load device by name. If your trying to load "none" you should just initialize and deinitialize your XR loader.
Disable "Initialize XR on Startup" in Project Settings -> XR Plugin Management
In the code use these two methods
IEnumerator StartXR(){
yield return XRGeneralSettings.Instance.Manager.InitializeLoader();
if(XRGeneralSettings.Instance.Manager.activeLoader == null){
Debug.Log("initialization FAILED");
}
else{
XRGeneralSettings.Instance.Manager.activeLoader.Start();
}
}
void StopXR(){
XRGeneralSettings.Instance.Manager.activeLoader.Stop();
XRGeneralSettings.Instance.Manager.activeLoader.Deinitialize();
}
(Sorry I am terrable at code snippits! I'm new to answering)
Then call these as you need them. It should turn on and turn off XR in your project

Android build problem when I clear app data?

I made a mini mobile game on Unity3d. It has many scenes (each level in the game is a scene). the levels start from scene number 1 but there is a scene number 0 which contains an empty that has a script attached to it "Level0".
public class Level0 : MonoBehaviour
{
public int levelIndex;
public IEnumerator delayCoroutine()
{
yield return new WaitForSeconds(1f);
SceneManager.LoadSceneAsync(levelIndex);
}
void Awake()
{
levelIndex = SaveLoadManager.loadCurrentLevelIndex();
StartCoroutine(delayCoroutine());
}
}
the role of this script is to call a static function from "SaveLoadManager" which returns the next level index (scene index in the build settings).
public static int loadCurrentLevelIndex()
{
if (File.Exists(Application.persistentDataPath + "/data.txt"))
{
BinaryFormatter bf = new BinaryFormatter();
FileStream stream = new FileStream(Application.persistentDataPath + "/data.txt", FileMode.Open);
PlayerDataSerializable data = bf.Deserialize(stream) as PlayerDataSerializable;
stream.Close();
return data.realCurrentLevel;
}
else
{
return 1;
}
}
so the method gets the level index from the data file but if the file is not found it just returns "1".
Now the problem is that when I build the game to my OPPO A73 with Android 10 and enter the app settings and choose"clear data" and reopen the game, then it crashes at level0. however when I do the same thing with Nokia 3 (Android 9) or Xiaomi Redmi Note 10 (Android 11) the game works fine and loads the first level as expected.
I monitored the errors via Logcat in Android Studio but I didn't get any error from Unity.
Is the problem with my OPPO device? because I got this error in Logcat:
E/DispScene: [/data/oppo/multimedia/oppo_display_perf_list.xml]:open
config fail
Or with Android 10?

Install Android APK on emulator using appium Node server

I have an appium server created in NODE.JS. I am working out to make the appium test to run an emulator and install the apk. Not able to find any particular examples online that has example on how to do it using Node server. Mostly examples are with the desktop installed appium server. I need some guidelines on how to do that. To further break it down, I want to perform following things using the appium Node server (Not to right any test case in the application source code)
Start the emulator or possible if can do it on real device
Install the APK on the emulator/device
Fire an intent that launches the app on emulator/device . Intent also contains data in bundle
Perform a click on a button inside the app.
start appium server in your terminal
appium
Output of above command like below on your terminal
Sample code here :
public class AppTest {
AppiumDriver driver;
MobileElement appTitle;
#Before
public void setup() throws MalformedURLException {
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
desiredCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
desiredCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "7.0");
desiredCapabilities.setCapability(MobileCapabilityType.NO_RESET, true);
desiredCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Moto");
desiredCapabilities.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.android.vending");
desiredCapabilities.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, "com.google.android.finsky.activities.MainActivity");
driver = new AndroidDriver(new URL("http://0.0.0.0:4723/wd/hub"), desiredCapabilities);
}
#Test
public void testGooglePlayApp() throws InterruptedException {
String appName = "Amazon Now - Grocery Shopping";
//How to scroll to specific text
MobileElement scrollToText = (MobileElement) driver.findElement(MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector()).scrollIntoView(new UiSelector().text(\"" + appName + "\"));"));
scrollToText.click();
// Verifying the app detail page
appTitle = (MobileElement) driver.findElementById("com.android.vending:id/title_title");
Assert.assertTrue(appName.equals(appTitle.getText().trim()));
driver.navigate().back();
//Clicking the search bar icon
MobileElement scrollToElement = (MobileElement) driver.findElement(MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector()).scrollIntoView(new UiSelector().description(\"Search\"));"));
scrollToElement.click();
MobileElement editText = (MobileElement) driver.findElementById("com.android.vending:id/search_box_text_input");
editText.sendKeys(appName);
Thread.sleep(1000);
List<MobileElement> listOfSuggestedResults = driver.findElementsById("com.android.vending:id/suggest_text");
for (MobileElement element : listOfSuggestedResults) {
if (appName.equals(element.getText().trim())) {
element.click();
break;
}
}
appTitle = (MobileElement) driver.findElementById("com.android.vending:id/title_title");
Assert.assertTrue(appName.equals(appTitle.getText().trim()));
}
#After
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
}
Sample code in github : https://github.com/tech-tock-tech/apptest
hope above will help if you still facing issue please check below video link -
https://www.youtube.com/watch?v=jP2NAY8ylp8

Categories

Resources