Failing to initialize iOS driver when running Appium tests through Jenkins + Maven

Overview

I have a code repository for automated (web and mobile app) UI testing using the following tools:

  • Java 1.8 (w/ Maven)
  • Selenium WebDriver
  • Appium
  • TestNG

Note: I am running the latest version of macOS as my operating system

The issue I am about to describe only applies for my iOS test suite and none of the other ones contained in my repository.

Here are the ways in which I am currently able to successfully run the test suite:

  1. I open up Eclipse or IntelliJ and run my code via the TestNG .xml file containing the included @Test methods. This will kick off the test suite. (works)
  2. I open up a terminal and navigate to the local repository on my machine and kick off the suite via Maven. I am using maven-surefire-plugin v2.22.1 to do this, and I pass in the name of the test suite as a flag to the maven command. Here is what that looks like.

pom.xml:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.1</version>
    <inherited>true</inherited>
      <configuration>
        <suiteXmlFiles>
          <suiteXmlFile>${TestSuite.Name}</suiteXmlFile>
        </suiteXmlFiles>
      </configuration>
</plugin>

Then, for example, in terminal I could run any of these:

  • $ mvn clean test -DTestSuite.Name=RegressionIos.xml
  • $ mvn clean test -DTestSuite.Name=RegressionAndroid.xml

Problem

So since I can use either of the previously described methods to kick off the test suite, I would like to set up a Jenkins job using Maven to do basically what I described before. The problem I am having is this:

When I setup the Maven job in Jenkins and configure it with the appropriate parameters and environment variables, every test fails.

I get the following error message in the Jenkins console:

TestCases.I3002_RegisterUser_PasswordShouldHaveAtleastOneDigit:13453 Could not find a connected IOS device. org.openqa.selenium.WebDriverException: It is impossible to create a new session because 'createSession' which takes HttpClient, InputStream and long was not found or it is not accessible

Essentially, this happens in a method where I try to set the mobile driver to use. The method returns an object of type IOSDriver<MobileElement> I have included a snippet below of this method where the error message comes from:

try {
  Reporter.log("strAppiumPort"+strDeviceAppiumPort);
  iosdriver = new IOSDriver<MobileElement>(new URL("http://127.0.0.1:"+strDeviceAppiumPort+"/wd/hub"), capabilities);
  try {
    if(iosdriver.findElement(By.id("Allow While Using App")).isDisplayed()) {
	  iosdriver.findElement(By.name("Allow While Using App")).click();
	}
	iosdriver.switchTo().alert().accept();
  } catch (Exception a) {
    iosdriver.switchTo().alert().accept();
  }
  try {
    iosdriver.switchTo().alert().accept();
  } catch (Exception e) {}
  Reporter.log("Mobile App was loaded correctly on IOS Device");
} catch (Exception e) {
  UpdateErrorMessageWithPivotalData(objDictionary, null, "Could not find a connected IOS device. " +e+ "-" + strMethodName);
}

The code may help you see more clearly what is going on, but the main question here is why is running Maven through Jenkins behaving differently than running it locally via IntelliJ or Eclipse? Please let me know if I am missing something crucial. Any and all help is appreciated.

In case I forgot to mention something or left out information you need to help answer this, please kindly let me know and I will do my best to provide that for you.

Cause in Jenkins it runs under another user. Thus to see all paths to installed programs you need use inject paths in Jenkins. Just copy from user you run on same mac.

Thank you for your reply, Aleksei!

So let’s say my computer has 2 users: “Admin” (which I am currently using) and “Jenkins”. Are you saying that I need to switch my user to “Jenkins” and run it that way? Or are you suggesting that I copy the current $PATH environment variable from my “Admin” user into Jenkins manually?

Also it’s worth noting again that I am able to run each of the other suites (for Android and the web application) in Jenkins without any issue and I do not inject the path either. Any idea why the results are different specifically for iPhone tests?

At least make sure that you see all paths under jenkins job. Just echo $PATH.

To fix use ‘Environment Injector Plugin-’ for jenkins.

Also under jenkins job you can check that your phone connected successfully using xcode terminal commands.

instruments -s devices

@Aleksei Update: I installed the ‘Environment Injector’ plugin for Jenkins and I added build steps to inject the path as you suggested. I ran the command as well instruments -s devices and it shows that my device is connected in the Jenkins console output for the job I am running. It successfully displayed my connected iOS device, but the tests still fail. I went onto the appium-xcuitest-driver repository on GitHub and found some information that leads me to believe that this is more of an issue with macOS accessibility settings than Jenkins. My tests are failing at the point where the code tries to initialize a new IOSDriver<WebElement>, and tells me that the test failed because there is no iOS device connected, even though it is. See this StackOverflow post and this GitHub issue for more information on that.

So issue was anyway in Jenkins user but now in certificate locations. You fixed it finally?

Yes I was able to fix it by adding in my developer profile credentials into Jenkins via the “Keychains and Provisioning Profiles Management” plugin.