Device conflict while running Appium test using selenium grid

So I have 2 iPhones and 2 Android devices connected with Grid server now when i am trying to run test parallel sometime test is running on correct device but sometime it is getting confuse and tries to execute test on unexpected device,is there any solution to point test on specific device ,i have tried passing udid while launching node appium server but didn’t work that way too.

any help would be appreciate

@Jawlitkp :- You can use session id to know which device is running, You can try my video

I saw your video before but here problem is how I can point to specific device , after extracting session I’d what I suposoe to do to point my test for that session Id

Hi , I have recorded a small video with parallel execution. i have it will help you.

Refer following link.

so my real issue is not that i am not able to run parallel test,issue i am facing is even though i use -u while launching appium server ,grid is not running test on correct device ,it is picking device which is first available ,so sometimes it is picking correct device but i am also seeing that many times my test is getting executed on wrong devices.

also following question is do we have to pass parameters from xml file ? I tried to pass using data provider but iOS driver is getting overwritten by android driver and i am getting error saying element is no longer attached with DOM

Were you able to fix this? We are having the same problem here.

Are you already solved that issue? I got the same problem here, grid is always picking the first device avaible and don’t respect capabilities i have send…

Hi @JoaoSilva,

What capabilities are you using?
Grid hub only uses browserName, version, platform and applicationName capabilities to select the grid node.

I are using mostly capabilities for devices like udid, platformName, platformVersion and my trouble is if i want redirect a test for a specific device with udid (unique device identifier), the grid just ignore my udid and send the test for a device it was avaible…
ApplicationName is used mostly for?

Thanks for your awnser btw .

My solution is to start the Appium node with a --default-capabilities argument set to something like {"udid":"deviceId"}. My setup maps 1 Appium process to 1 device, so when a test session request comes in on Selenium Grid, the grid will select a particular Appium node rather than having the nodes select a particular device.

It’s also good to stay up-to-date with the Selenium hub. I’m able to pass in custom capabilities through the grid on the 2.53.0 standalone JAR.

1 Like

Thanks for your anwser @afwang

I already use udid, in my node configuration file (json file) like this one:
“deviceName”: “Google (Motorola) Nexus 6”,
“maxInstances”: 1,
“platformName”: “Android”,
“plataformVersion”: “6.0.1”,
“browserName”: “Chrome”,
“udid”: “ZX1G426PCD”,
“automationName”: “Appium”

And my setup is probably like yours because im using also 1 appium process for 1 device, just to avoid this problem i said before, but what happen is when i run 2 tests almost sequencial, the first one goes to the right device and calls the right appium process but the second calls the wrong appium process, but goes to device who got the udid requested in test case. In android i have no trouble with that, but in iOS, its a blocker because we need a webkit-proxy associated to an appium process, and when grid calls the wrong appium process, the whole iOS proxys stop working, and i need restart my whole setup.
You said its possible pass custom capabilities through the grid on 2.53.0, how can you do that?

Hi @JoaoSilva,

Those capabilities are Appium capabilities and they are used by the Appium node to launch test, but they are not used by Selenium Grid to choose the grid node.

Grid hub reads only browserName, version, platform and applicationName capabilities. In your case, both Appium nodes have the same values for these 4 capabilities, so they are identical nodes for the grid hub and it sends one request to each node.

You must configure your nodes with different values, e.g. “version”: “android-6.0.1”, and, when running the test, use this capability to select the node (and indirectly the device, if udid value is already configured in Appium node).

1 Like

Hi @rgonalo,

Do you know for what is mostly used applicationName capability and how use custom capabilties like @afwang said before?

applicationName is undocumented (https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/3660) and it has no official use, but in practice it’s used to select a node (like version and platform capabilities). You can use any of them to configure and select the node.

To launch an Appium server configuring the device udid:
Appium 1.4.16: appium --udid device_udid
Appium 1.5: appium --default-capabilities ‘{“udid”: “device_udid”}’

@rgonalo I’m running Appium 1.5.2 and I launch my appium server, like you said in Appium 1.5 I just don’t use --default-capabilities ‘{“udid”: “device_udid”}’ because I send udid through --nodeconfig, but i think it was the same thing, right?
Did you know how use custom capabilties in selenium grid 2.53.0 like @afwang said before?

No, it’s not the same. Nodeconfig data is only used to configure the grid node, Appium does not read these capabilities.

I don’t know which custom capabilities @afwang is talking about.

2 Likes

@rgonalo finnaly i got this working perfect! I didn’t know aapium does not read from that nodeconfig, after I changed that this started working perfect. My thanks @rgonalo! :slight_smile:

Yes, that is correct.

As for custom capabilities, the hub will forward all capabilities that a session request includes in its desired capabilities. That is, if a desired capabilities object is defined with a key ‘my_custom_cap’, the hub server will forward a capabilities object to a node with a capabilities object that includes the key ‘my_custom_cap’ with its value.

During node registration, Appium can include additional capabilities that the hub does not use as well. For example, the capabilities section of my nodeconfig file looks like this:

    "capabilities": [
        {
            "browserName": "Android",
            "version": "4.4.4",
            "maxInstances": 1,
            "platform": "Android",
            "groups": "samsung"
        }
    ]

Note that “groups” is not a standard capability that Selenium uses. This key is something I added to my own set up. However, during registration, the Selenium hub will accept and store the “groups” capability internally.

By default, the standalone Selenium jar uses its internal DefaultCapabilityMatcher to check if a node’s capabilities matches a set of desired capabilities. This matcher uses only platform, version, and browser name IIRC. However, Selenium hub accepts a -hubConfig argument which allows you to specify a custom matcher to use when checking whether a node matches for a desired capability. I use this feature to add my own matcher to also check if a node matches for the “groups” capability that I pass through my tests, on top of doing what the DefaultCapabilityMatcher does.

1 Like

Thanks for your anwser @afwang!

Just one more thing, can I add more than one custom capability?
Can you add your hubConfig file here ?

Yes, you can add more than one custom capability. These additional capabilities are stored in the Selenium hub server as a map of Strings to Strings. However, in order for the Selenium hub to make use of your custom capabilities, you have to provide your own matcher that makes use of those additional capabilities.

My hub config file looks something like this:

{
  "capabilityMatcher": "com.example.GroupCapabilityMatcher",
  "newSessionWaitTimeout": 300000,
  "timeout": 1200000,
  "browserTimeout": 600000
}

If all you want to do is provide your own custom implementation of a capability matcher, you really only need to have the “capabilityMatcher” line in there. The other options are just additional options I use for tweaking my setup.

A quick example of my GroupCapabilityMatcher class looks like this:

package com.example;

import org.openqa.grid.internal.utils.DefaultCapabilityMatcher;

public class GroupCapabilityMatcher extends DefaultCapabilityMatcher {
    @Override
    public boolean matches(Map<String, Object> nodeCapabilities, Map<String, Object> requestedCapabilities) {
        boolean matches = super.matches(nodeCapability requestedCapability)
            && nodeCapabilities.get("groups").equals(requestedCapability.get("groups"));
        return matches
    }
}

I can add this class to the classpath when I launch the Selenium hub server, or I can package it with other supporting classes into a Jar, and then add the Jar to the classpath. In either case, I have to change my Selenium hub server launch command to look a bit something like the following:

java -cp selenium-server-standalone-2.53.0.jar:my-custom-capabilities.jar \
    org.openqa.grid.selenium.GridLauncher -role hub \
    -hubConfig my-hub-config.json

By the way, if you really want to know what sorts of features Selenium provides you, I recommend cloning the Selenium source code and taking a look around (and of course, reading the docs). This is where I found out how to customize the capability matchers.

3 Likes