Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 15 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,6 @@ brew install carthage
npm install -g ios-deploy
```

On some systems the default logger, `idevicesyslog`, does not work. You can install `deviceconsole` and specify its path with the `realDeviceLogger` capability
(**note:** This path should be the path to the _executable_ installed by the below command. It will be the directory created by the below command, followed by
`/deviceconsole`).

```
npm install -g deviceconsole
```

For real devices we can use [xcpretty](https://github.com/supermarin/xcpretty) to make Xcode output more reasonable. This can be installed by

```
Expand Down Expand Up @@ -135,16 +127,7 @@ targets. This should also auto select `Signing Ceritificate`. The outcome should

### Known problems

#### Logger not working

If the system stops with log output like

```
[XCUITest] Waiting for WebDriverAgent to start on device
[debug] [XCUITest] Log file for xcodebuild test: /Users/user/Library/Developer/Xcode/DerivedData/WebDriverAgent-dmeyhiwwsjtvnpfsgvqwxasavdxs/Logs/Test/23E16C13-3EFF-4980-95BD-8F69A04D91E3/Session-WebDriverAgentRunner-2016-10-07_095258-KgtUwt.log
```

The culprit is usually the real device logger. By default the system uses `idevicesyslog`, which is installed with `libimobiledevice`, but on some machines this does not work. You can test by running `idevicesyslog` in a terminal window. If it fails, you can use `deviceconsole`, specifying the full path to the program with the `realDeviceLogger` capability.
After many failures on real devices, there can be a state where the device will no longer accept connections. To possibly remedy this, set the `useNewWDA` capability to `true`.

#### Weird state

Expand Down Expand Up @@ -188,7 +171,6 @@ Differences noted here
|`processArguments`|Process arguments and environment which will be sent to the WebDriverAgent server.|`{ args: ["a", "b", "c"] , env: { "a": "b", "c": "d" } }` or `'{"args": ["a", "b", "c"], "env": { "a": "b", "c": "d" }}'`|
|`wdaLocalPort`|This value if specified, will be used to forward traffic from Mac host to real ios devices over USB. Default value is same as port number used by WDA on device.|e.g., `8100`|
|`showXcodeLog`|Whether to display the output of the Xcode command used to run the tests. If this is `true`, there will be **lots** of extra logging at startup. Defaults to `false`|e.g., `true`|
|`realDeviceLogger`|Device logger for real devices. It could be path to `deviceconsole` (installed with `npm install deviceconsole`, a compiled binary named `deviceconsole` will be added to `./node_modules/deviceconsole/`) or `idevicesyslog` (comes with libimobiledevice). Defaults to `idevicesyslog`|`idevicesyslog`, `/abs/path/to/deviceconsole`|
|`iosInstallPause`|Time in milliseconds to pause between installing the application and starting WebDriverAgent on the device. Used particularly for larger applications. Defaults to `0`|e.g., `8000`|
|`xcodeOrgId`|Apple developer team identifier string. Must be used in conjunction with `xcodeSigningId` to take effect.|e.g., `JWL241K123`|
|`xcodeSigningId`|String representing a signing certificate. Must be used in conjunction with `xcodeOrgId`. This is usually just `iPhone Developer`, so the default (if not included) is `iPhone Developer`|e.g., `iPhone Developer`|
Expand All @@ -199,7 +181,8 @@ Differences noted here
|`usePrebuiltWDA`|Skips the build phase of running the WDA app. Building is then the responsibility of the user. Only works for Xcode 8+. Defaults to `false`.|e.g., `true`|
|`preventWDAAttachments`|Sets read only permissons to Attachments subfolder of WebDriverAgent root inside Xcode's DerivedData. This is necessary to prevent XCTest framework from creating tons of unnecessary screenshots and logs, which are impossible to shutdown using programming interfaces provided by Apple.|Setting the capability to `true` will set Posix permissions of the folder to `555` and `false` will reset them back to `755`|
|`webDriverAgentUrl`|If provided, Appium will connect to an existing WebDriverAgent instance at this URL instead of starting a new one.|e.g., `http://localhost:8100`|

|`useNewWDA`|If `true`, forces uninstall of any existing WebDriverAgent app on device. This can provide stability in some situations. Defaults to `false`.|e.g., `true`|
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be useful to give at least one example of such situation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll work on documenting an example. I don't have the details of the problem right now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this require manual git pull of webdriveragent source into the wedriveragent under the xcuittestdriver node module ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. It just uninstalls the app from the device on session creation.

|`wdaLaunchTimeout`|Time, in ms, to wait for WebDriverAgewnt to be pingable. Defaults to 60000ms.|e.g., `30000`|



Expand Down Expand Up @@ -227,6 +210,18 @@ npm run watch
npm test
```

There are also a number of environment variables that can be used when running
the tests locally. These include:

* `REAL_DEVICE` - set to anything truthy, makes the tests use real device capabilities
* `_FORCE_LOGS` - set to `1` to get the log output, not just spec
* `PLATFORM_VERSION` - change the version to run the tests against (defaults to `9.3`)
* `XCCONFIG_FILE` - specify where the xcode config file is for a real device run (if
blank, and running a real device test, it will search for the first file in
the root directory of the repo with the extension "xcconfig")
* `UICATALOG_REAL_DEVICE` - path to the real device build of UICatalog, in case
the npm installed one is not built for real device


### WebDriverAgent Updating

Expand Down
11 changes: 7 additions & 4 deletions lib/desired-caps.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ let desiredCapConstraints = _.defaults({
showXcodeLog: {
isBoolean: true
},
realDeviceLogger: {
isString: true
},
wdaLocalPort: {
isNumber: true
},
Expand Down Expand Up @@ -53,7 +50,13 @@ let desiredCapConstraints = _.defaults({
},
webDriverAgentUrl: {
isString: true
}
},
useNewWDA: {
isBoolean: true
},
wdaLaunchTimeout: {
isNumber: true
},
}, iosDesiredCapConstraints);

export { desiredCapConstraints };
Expand Down
44 changes: 28 additions & 16 deletions lib/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { version } from '../../package.json'; // eslint-disable-line import/no-u


const SAFARI_BUNDLE_ID = 'com.apple.mobilesafari';
const WDA_STARTUP_RETRIES = 2;

const NO_PROXY_NATIVE_LIST = [
['GET', /^\/session\/[^\/]+$/],
Expand Down Expand Up @@ -250,33 +251,44 @@ class XCUITestDriver extends BaseDriver {
tries++;
this.wda = new WebDriverAgent(this.xcodeVersion, this.opts);

try {
await this.wda.launch(sessionId, realDevice);
} catch (err) {
if ((err.message || '').indexOf('xcodebuild failed with code 65') === -1) {
throw err;
}
// Xcode error code 65 means that the WDA app is still being installed
// and xcodebuild can't do its business, so it is reasonable to retry
log.debug('xcodebuild failure warrants retry. Retrying...');
if (this.opts.useNewWDA) {
log.debug(`Capability 'useNewWDA' set, so uninstalling WDA before proceeding`);
await this.wda.uninstall();
}

// local helper for the two places we need to uninstall wda and re-start it
let uninstallAndRestart = async () => {
log.debug('Quitting and uninstalling WebDriverAgent, then retrying');
await this.wda.quit();
await this.wda.uninstall();
await this.startWda(sessionId, realDevice, tries);
};

try {
await this.wda.launch(sessionId, realDevice);
} catch (err) {
if (tries > WDA_STARTUP_RETRIES) throw err;
log.debug(`Unable to launch WebDriverAgent because of xcodebuild failure: ${err.message}`);
await uninstallAndRestart();
}

this.proxyReqRes = this.wda.proxyReqRes.bind(this.wda);
this.jwpProxyActive = true;

try {
await this.startWdaSession(this.opts.bundleId, this.opts.processArguments);
await retryInterval(15, 500, async () => {
log.debug('Sending createSession command to WDA');
try {
await this.startWdaSession(this.opts.bundleId, this.opts.processArguments);
} catch (err) {
log.debug('Failed to create session. Retrying...');
throw err;
}
});
} catch (err) {
log.debug(`Unable to start WebDriverAgent session: ${err.message}`);
if (tries > 2) throw err;

log.debug('Quitting and uninstalling WebDriverAgent, then retrying');
await this.wda.quit();
await this.wda.uninstall();
await this.startWda(sessionId, realDevice, tries);
if (tries > WDA_STARTUP_RETRIES) throw err;
await uninstallAndRestart();
}

if (typeof this.opts.preventWDAAttachments !== 'undefined') {
Expand Down
2 changes: 1 addition & 1 deletion lib/ios-deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class IOSDeploy {

constructor (udid) {
this.udid = udid;
this.cmd = IOSDEPLOY_PATH;// this.cmd is in accordance with iDevice
this.cmd = IOSDEPLOY_PATH; // this.cmd is in accordance with iDevice
}

async checkStatus () {
Expand Down
Loading