mirror of
https://github.com/appium/appium.git
synced 2026-11-09 19:38:26 +08:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
790d9e8df0 | ||
|
|
ec3e0bc7b3 |
@@ -1,13 +0,0 @@
|
||||
# editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -1,9 +1 @@
|
||||
**/coverage/**
|
||||
**/node_modules/**
|
||||
examples/javascript-wd
|
||||
**/build/**
|
||||
**/*.min.js
|
||||
sample-code
|
||||
**/build-fixtures/**
|
||||
packages/appium/docs/**/assets/**
|
||||
packages/appium/docs/**/js/**
|
||||
|
||||
@@ -1,62 +1,3 @@
|
||||
{
|
||||
"extends": ["@appium/eslint-config-appium-ts"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": "packages/fake-driver/**/*",
|
||||
"rules": {"require-await": "off"}
|
||||
},
|
||||
{"files": "packages/support/**/*", "globals": {"BigInt": "readonly"}},
|
||||
{
|
||||
"files": "packages/*/test/**/*",
|
||||
"rules": {"func-names": "off"}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"packages/appium/support.js",
|
||||
"packages/appium/driver.js",
|
||||
"packages/appium/plugin.js"
|
||||
],
|
||||
"parserOptions": {
|
||||
"sourceType": "script"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"./test/setup.js",
|
||||
"./**/scripts/**/*.js",
|
||||
"./packages/*/index.js",
|
||||
"./packages/docutils/bin/appium-docs.js"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-var-requires": "off"
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "script"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": "./packages/*/test/**/*.js",
|
||||
"rules": {
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"no-restricted-properties": [
|
||||
"error",
|
||||
{
|
||||
"object": "sinon",
|
||||
"property": "spy",
|
||||
"message": "Use `sandbox = sinon.createSandbox()` and `sandbox.spy()` instead. Don't forget to call `sandbox.restore()` in `afterEach`"
|
||||
},
|
||||
{
|
||||
"object": "sinon",
|
||||
"property": "stub",
|
||||
"message": "Use `sandbox = sinon.createSandbox()` and `sandbox.stub()` instead. Don't forget to call `sandbox.restore()` in `afterEach`"
|
||||
},
|
||||
{
|
||||
"object": "sinon",
|
||||
"property": "mock",
|
||||
"message": "Use `sandbox = sinon.createSandbox()` and `sandbox.mock()` instead. Don't forget to call `sandbox.restore()` in `afterEach`"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
"extends": "appium"
|
||||
}
|
||||
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
# Generated by FOSSA CLI (https://github.com/fossas/fossa-cli)
|
||||
# Visit https://fossa.com to learn more
|
||||
|
||||
version: 3
|
||||
|
||||
project:
|
||||
id: appium
|
||||
name: appium
|
||||
|
||||
paths:
|
||||
exclude:
|
||||
- ./sample-code
|
||||
- '**/fixtures/**'
|
||||
- '**/demo/**'
|
||||
- '**/example/**'
|
||||
- '**/examples/**'
|
||||
|
||||
targets:
|
||||
only:
|
||||
- type: npm
|
||||
path: .
|
||||
- type: npm
|
||||
path: ./packages/appium
|
||||
- type: npm
|
||||
path: ./packages/base-driver
|
||||
- type: npm
|
||||
path: ./packages/doctor
|
||||
- type: npm
|
||||
path: ./packages/eslint-config-appium
|
||||
- type: npm
|
||||
path: ./packages/fake-driver
|
||||
- type: npm
|
||||
path: ./packages/support
|
||||
- type: npm
|
||||
path: ./packages/test-support
|
||||
- type: npm
|
||||
path: ./packages/types
|
||||
- type: npm
|
||||
path: ./packages/schema
|
||||
- type: npm
|
||||
path: ./packages/universal-xmlplugin
|
||||
- type: npm
|
||||
path: ./packages/opencv
|
||||
- type: npm
|
||||
path: ./packages/images-plugin
|
||||
- type: npm
|
||||
path: ./packages/base-plugin
|
||||
- type: npm
|
||||
path: ./packages/relaxed-caps-plugin
|
||||
- type: npm
|
||||
path: ./packages/fake-plugin
|
||||
- type: npm
|
||||
path: ./packages/docutils
|
||||
|
||||
revision:
|
||||
branch: master
|
||||
@@ -1,4 +0,0 @@
|
||||
* text=auto eol=lf
|
||||
|
||||
# Handle as a text file but merge as binary.
|
||||
package-lock.json merge=binary
|
||||
@@ -0,0 +1,30 @@
|
||||
## The problem
|
||||
|
||||
Briefly describe the issue you are experiencing (or the feature you want to see added to Appium). Tell us what you were trying to do and what happened instead. Remember, this is _not_ a place to ask questions. For that, go to http://discuss.appium.io!
|
||||
|
||||
## Environment
|
||||
|
||||
* Appium version (or git revision) that exhibits the issue:
|
||||
* Last Appium version that did not exhibit the issue (if applicable):
|
||||
* Desktop OS/version used to run Appium:
|
||||
* Node.js version (unless using Appium.app|exe):
|
||||
* Mobile platform/version under test:
|
||||
* Real device or emulator/simulator:
|
||||
* Appium CLI or Appium.app|exe:
|
||||
|
||||
## Details
|
||||
|
||||
Describe in more detail the problem you have been experiencing, if necessary.
|
||||
|
||||
## Link to Appium logs
|
||||
|
||||
Create a [gist](https://gist.github.com) which is a paste of your _full_ Appium logs, and link them here. Do _not_ paste your full Appium logs here, as it will make this issue very long and hard to read! If you are reporting a bug, _always_ include Appium logs!
|
||||
|
||||
|
||||
## Code To Reproduce Issue [ Good To Have ]
|
||||
|
||||
Please remember that, with sample code; it's easier to reproduce bug and much faster to fix it.
|
||||
|
||||
Please git clone https://github.com/appium/sample-code and use one of your favourite languages and sample apps to reproduce issue.
|
||||
|
||||
In case a similar scenario is missing in sample-code, please submit a PR with one of the sample apps provided.
|
||||
@@ -1,92 +0,0 @@
|
||||
name: 🐞 Bug Report
|
||||
description: File a new bug report
|
||||
title: 'bug: <title>'
|
||||
labels: [Bug, Needs Triage]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: ':stop_sign: _For support questions, please visit [http://discuss.appium.io](http://discuss.appium.io) instead._'
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: 'Do I have the most recent component updates?'
|
||||
description: 'Appium 1-related issues are going to be ignored as this version has reached its end of life.'
|
||||
options:
|
||||
- label: 'I use the most recent available driver/plugin and server versions'
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: 'Is the component officially supported by the Appium team?'
|
||||
description: 'Make sure you report an issue for a component which is officially supported/maintained by the Appium team.'
|
||||
options:
|
||||
- label: 'I have verified the component repository is present under the Appium organization in GitHub'
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: 'Is there an existing issue for this?'
|
||||
description: 'Please [search :mag: the issues](https://github.com/appium/appium/issues) to check if this bug has already been reported.'
|
||||
options:
|
||||
- label: 'I have searched the existing issues'
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 'Current Behavior'
|
||||
description: 'Describe the problem you are experiencing. **Please do not paste your logs here.** Screenshots are welcome.'
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 'Expected Behavior'
|
||||
description: 'Describe what you expect to happen instead.'
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 'Minimal Reproducible Example'
|
||||
description: |
|
||||
Please provide a the _smallest, complete code snippet_ that Appium's maintainers can run to reproduce the issue ([read more about what this entails](https://stackoverflow.com/help/minimal-reproducible-example)). Failing this, any sort of reproduction steps are better than nothing!
|
||||
|
||||
An easy way to get started is to copy [sample code](https://github.com/appium/appium/tree/master/packages/appium/sample-code) and modify it accordingly.
|
||||
|
||||
If the result is more than a screenful of text _or_ requires multiple files, please:
|
||||
|
||||
- _Attach_ (do not paste) it to this textarea, _or_
|
||||
- Put it in a [Gist](https://gist.github.com) and paste the link, _or_
|
||||
- Provide a link to a new or existing public repository exhibiting the issue
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 'Environment'
|
||||
description: 'Please provide the following information about your environment; feel free to remove any items which are not relevant.'
|
||||
value: |
|
||||
- Operating system:
|
||||
- Appium server version (output of `appium --version`):
|
||||
- Appium driver(s) and their version(s) (`appium driver list`):
|
||||
- Appium plugin(s) and their version(s) (`appium plugin list`):
|
||||
- Node.js version (output of `node --version`):
|
||||
- `npm` version (output of `npm --version`):
|
||||
- Last component(s) version which did _not_ exhibit the problem:
|
||||
- Platform and version under test:
|
||||
- Real device or emulator/simulator:
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
attributes:
|
||||
label: 'Link to Appium Logs'
|
||||
description: |
|
||||
Create a [Gist](https://gist.github.com)—which contains your _full_ Appium logs—and link it here. Alternatively, you can attach a logfile to this issue (drag it into the "Further Information" field below).
|
||||
|
||||
:warning: _Remember to redact or remove any sensitive information!_
|
||||
placeholder: 'https://gist.github.com/...'
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Further Information
|
||||
description: |
|
||||
Links? References? Anything that will give us more context about the issue you are encountering!
|
||||
|
||||
_Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in._
|
||||
validations:
|
||||
required: false
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: ':stop_sign: _For support questions, please visit [http://discuss.appium.io](http://discuss.appium.io) instead._'
|
||||
@@ -1,5 +0,0 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: ❓ Question
|
||||
url: https://discuss.appium.io/
|
||||
about: Please use the Appium forum for questions
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[Feat]:"
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -10,19 +10,20 @@ _Put an `x` in the boxes that apply_
|
||||
- [ ] Bugfix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] Documentation Update (if none of the other choices apply)
|
||||
|
||||
## Checklist
|
||||
|
||||
_Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code._
|
||||
|
||||
- [ ] I have read the [Contributing Guide](https://appium.io/docs/en/latest/contributing/)
|
||||
- [ ] I have signed the CLA
|
||||
- [ ] I have read the [CONTRIBUTING](/CONTRIBUTING.md) doc
|
||||
- [ ] I have signed the [CLA](https://docs.google.com/forms/d/1lOfXRw_0VCk7gYzjj4WLetGu7yelDVo5LWh0z7pGftE/viewform)
|
||||
- [ ] Lint and unit tests pass locally with my changes
|
||||
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||
- [ ] I have added the necessary documentation (if appropriate)
|
||||
- [ ] I have added necessary documentation (if appropriate)
|
||||
- [ ] Any dependent changes have been merged and published in downstream modules
|
||||
|
||||
## Further comments
|
||||
|
||||
If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...
|
||||
|
||||
### Reviewers: @imurchie, @jlipps, ...
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
version: v1
|
||||
|
||||
labels:
|
||||
- label: 'Enhancement'
|
||||
sync: true
|
||||
matcher:
|
||||
commits: '^feat.*?:'
|
||||
title: '^feat.*?:'
|
||||
|
||||
- label: 'Bug'
|
||||
sync: true
|
||||
matcher:
|
||||
commits: '^fix.*?:'
|
||||
title: '^fix.*?:'
|
||||
|
||||
- label: 'Documentation'
|
||||
sync: true
|
||||
matcher:
|
||||
commits: '^docs.*?:'
|
||||
title: '^docs.*?:'
|
||||
files: ['packages/docutils/**', 'packages/appium/docs/**', '**/*.md']
|
||||
|
||||
- label: 'chore'
|
||||
sync: true
|
||||
matcher:
|
||||
commits: '^chore.*?:'
|
||||
title: '^chore.*?:'
|
||||
files: ['.github/**', '.husky/**', '.vscode/**', './.*', './*.js', '**/test/**']
|
||||
|
||||
- label: 'SemVer:Breaking'
|
||||
sync: true
|
||||
matcher:
|
||||
commits: '(^(.+?)!:)|(BREAKING CHANGE:)'
|
||||
|
||||
- label: 'Dependencies'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['**/package.json', 'package-lock.json', '**/requirements.txt']
|
||||
author: 'renovate'
|
||||
|
||||
- label: 'appium core'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/appium/**']
|
||||
|
||||
- label: '@appium/base-driver'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/base-driver/**']
|
||||
|
||||
- label: '@appium/base-plugin'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/base-plugin/**']
|
||||
|
||||
- label: '@appium/doctor'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/doctor/**']
|
||||
|
||||
- label: '@appium/docutils'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/docutils/**']
|
||||
|
||||
- label: '@appium/driver-test-support'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/driver-test-support/**']
|
||||
|
||||
- label: '@appium/eslint-config-appium'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/eslint-config-appium/**']
|
||||
|
||||
- label: '@appium/eslint-config-appium-ts'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/eslint-config-appium-ts/**']
|
||||
|
||||
- label: '@appium/execute-driver-plugin'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/execute-driver-plugin/**']
|
||||
|
||||
- label: '@appium/fake-driver'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/fake-driver/**']
|
||||
|
||||
- label: '@appium/fake-plugin'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/fake-plugin/**']
|
||||
|
||||
- label: '@appium/images-plugin'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/images-plugin/**']
|
||||
|
||||
- label: '@appium/logger'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/logger/**']
|
||||
|
||||
- label: '@appium/opencv'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/opencv/**']
|
||||
|
||||
- label: '@appium/plugin-test-support'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/plugin-test-support/**']
|
||||
|
||||
- label: '@appium/relaxed-caps-plugin'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/relaxed-caps-plugin/**']
|
||||
|
||||
- label: '@appium/schema'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/schema/**']
|
||||
|
||||
- label: '@appium/support'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/support/**']
|
||||
|
||||
- label: '@appium/strongbox'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/strongbox/**']
|
||||
|
||||
- label: '@appium/test-support'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/test-support/**']
|
||||
|
||||
- label: '@appium/tsconfig'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/tsconfig/**']
|
||||
|
||||
- label: '@appium/types'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/types/**']
|
||||
|
||||
- label: '@appium/universal-xml-plugin'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/universal-xml-plugin/**']
|
||||
@@ -1,26 +0,0 @@
|
||||
# Configuration for Lock Threads - https://github.com/dessant/lock-threads
|
||||
|
||||
# Number of days of inactivity before a closed issue or pull request is locked
|
||||
daysUntilLock: 365
|
||||
|
||||
# Skip issues and pull requests created before a given timestamp. Timestamp must
|
||||
# follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable
|
||||
skipCreatedBefore: false
|
||||
|
||||
# Issues and pull requests with these labels will be ignored. Set to `[]` to disable
|
||||
exemptLabels: []
|
||||
|
||||
# Label to add before locking, such as `outdated`. Set to `false` to disable
|
||||
lockLabel: false
|
||||
|
||||
# Comment to post before locking. Set to `false` to disable
|
||||
lockComment: >
|
||||
This thread has been automatically locked since there has not been
|
||||
any recent activity after it was closed. Please open a new issue for
|
||||
related bugs.
|
||||
|
||||
# Assign `resolved` as the reason for locking. Set to `false` to disable
|
||||
setLockReason: false
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
only: issues
|
||||
@@ -1,16 +0,0 @@
|
||||
name: Labeler
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize]
|
||||
branches: [master]
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
labeler:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
name: Auto-Label PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: fuxingloh/multi-labeler@v4
|
||||
@@ -1,102 +0,0 @@
|
||||
name: Appium Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
# this list of paths could potentially impact the build
|
||||
paths:
|
||||
- '**/tsconfig*.json'
|
||||
- 'packages/base-driver/static/**/*'
|
||||
- 'packages/*/test/**'
|
||||
- 'packages/*/bin'
|
||||
- 'packages/**/*.ts'
|
||||
- 'packages/**/*.json'
|
||||
- 'packages/**/*.js'
|
||||
- 'package*.json'
|
||||
- 'lerna.json'
|
||||
- '.npmrc'
|
||||
- '.mocharc.js'
|
||||
- '.github/workflows/build.yml' # this file
|
||||
- '.eslintrc'
|
||||
- '.eslintignore'
|
||||
- '!**/sample-code/**'
|
||||
- '!packages/*/docs/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**/tsconfig*.json'
|
||||
- 'packages/base-driver/static/**/*'
|
||||
- 'packages/*/test/**'
|
||||
- 'packages/*/bin'
|
||||
- 'packages/**/*.ts'
|
||||
- 'packages/**/*.json'
|
||||
- 'packages/**/*.js'
|
||||
- 'package*.json'
|
||||
- 'lerna.json'
|
||||
- '.npmrc'
|
||||
- '.mocharc.js'
|
||||
- '.github/workflows/build.yml' # this file
|
||||
- '.eslintrc'
|
||||
- '.eslintignore'
|
||||
- '!**/sample-code/**'
|
||||
- '!packages/*/docs/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
prepare_matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
versions: ${{ steps.generate-matrix.outputs.active }}
|
||||
steps:
|
||||
- name: Select all active LTS versions of Node.js
|
||||
id: generate-matrix
|
||||
uses: msimerson/node-lts-versions@v1
|
||||
|
||||
test:
|
||||
needs:
|
||||
- prepare_matrix
|
||||
name: Tests
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
|
||||
os:
|
||||
- ubuntu-latest
|
||||
# TODO: Windows is not stable and slow to run
|
||||
# - windows-latest
|
||||
# TODO: Enable below envs after all tests have been verified green
|
||||
# - macos-latest
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
uses: bahmutov/npm-install@v1
|
||||
with:
|
||||
useRollingCache: true
|
||||
install-command: npm ci --foreground-scripts
|
||||
- name: Run smoke, unit & E2E tests
|
||||
run: npm run test:ci
|
||||
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
uses: bahmutov/npm-install@v1
|
||||
with:
|
||||
useRollingCache: true
|
||||
install-command: npm ci
|
||||
- name: ESLint
|
||||
run: npm run lint:ci
|
||||
@@ -1,36 +0,0 @@
|
||||
name: Cache Cleanup
|
||||
|
||||
# from https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cleanup
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
|
||||
REPO=${{ github.repository }}
|
||||
BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
|
||||
|
||||
echo "Fetching list of cache keys"
|
||||
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
|
||||
|
||||
## Setting this to not fail the workflow while deleting cache keys.
|
||||
set +e
|
||||
echo "Deleting caches..."
|
||||
for cacheKey in $cacheKeysForPR
|
||||
do
|
||||
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
|
||||
done
|
||||
echo "Done"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,68 +0,0 @@
|
||||
name: Appium Deploy
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
prepare_matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
versions: ${{ steps.generate-matrix.outputs.active }}
|
||||
steps:
|
||||
- name: Select all active LTS versions of Node.js
|
||||
id: generate-matrix
|
||||
uses: msimerson/node-lts-versions@v1
|
||||
|
||||
check:
|
||||
needs:
|
||||
- prepare_matrix
|
||||
name: Check
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install Appium
|
||||
run: |
|
||||
if [[ "$GITHUB_REF_TYPE" == tag ]]; then
|
||||
npm i --location=global $GITHUB_REF_NAME
|
||||
else
|
||||
npm i --location=global appium
|
||||
fi
|
||||
shell: bash
|
||||
- name: Install drivers and plugins
|
||||
run: |
|
||||
if grep -q macos <<< ${{ matrix.os }}; then
|
||||
appium driver install xcuitest
|
||||
fi
|
||||
appium driver install uiautomator2
|
||||
appium plugin install images
|
||||
shell: bash
|
||||
- name: Verify installation
|
||||
run: |
|
||||
installed_drivers=$(appium driver list --installed 2>&1)
|
||||
if grep -q macos <<< ${{ matrix.os }}; then
|
||||
grep -q xcuitest <<< $installed_drivers
|
||||
fi
|
||||
grep -q uiautomator2 <<< $installed_drivers
|
||||
installed_plugins=$(appium plugin list --installed 2>&1)
|
||||
grep -q images <<< $installed_plugins
|
||||
shell: bash
|
||||
- name: Verify Appium could be executed
|
||||
run: |
|
||||
appium --use-plugins=images &
|
||||
pid=$(echo $!)
|
||||
sleep 5
|
||||
ps -p $pid || exit 1
|
||||
kill -2 $pid
|
||||
shell: bash
|
||||
@@ -1,53 +0,0 @@
|
||||
name: Build Docs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**/tsconfig*.json'
|
||||
- '**/package*.json'
|
||||
- '**/*mkdocs*.ya?ml'
|
||||
- 'packages/docutils/requirements.txt'
|
||||
- 'packages/*/README.md'
|
||||
- 'packages/*/docs/**'
|
||||
- 'packages/*/**/*.ts'
|
||||
- 'packages/*/**/*.js'
|
||||
- '.github/workflows/docs.yml' # this file
|
||||
- '!**/test/**'
|
||||
- '!**/sample-code/**'
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**/tsconfig*.json'
|
||||
- '**/package*.json'
|
||||
- '**/*mkdocs*.ya?ml'
|
||||
- 'packages/docutils/requirements.txt'
|
||||
- 'packages/*/README.md'
|
||||
- 'packages/*/docs/**'
|
||||
- 'packages/*/**/*.ts'
|
||||
- 'packages/*/**/*.js'
|
||||
- '.github/workflows/docs.yml' # this file
|
||||
- '!**/test/**'
|
||||
- '!**/sample-code/**'
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
name: Docs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies (Node.js)
|
||||
uses: bahmutov/npm-install@v1
|
||||
with:
|
||||
useRollingCache: true
|
||||
install-command: npm ci
|
||||
- name: Install dependencies (Python)
|
||||
run: PIP_BREAK_SYSTEM_PACKAGES=1 pip install -r packages/docutils/requirements.txt
|
||||
- name: Configure Git User
|
||||
run: |
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
- name: Build Docs
|
||||
run: npm run docs:preview
|
||||
@@ -1,31 +0,0 @@
|
||||
name: License Checks
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
fossa-check:
|
||||
name: Run FOSSA Analysis
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
FOSSA_API_KEY: ${{secrets.FOSSA_API_KEY}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
- name: Install dependencies
|
||||
uses: bahmutov/npm-install@v1
|
||||
- name: Install fossa-cli
|
||||
run: |
|
||||
curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install-latest.sh | bash
|
||||
- name: Run FOSSA analysis
|
||||
run: |
|
||||
if [ -n "$FOSSA_API_KEY" ]; then
|
||||
fossa analyze
|
||||
fossa test
|
||||
else
|
||||
echo "License checks did not run. FOSSA_API_KEY is not defined for this fork."
|
||||
fi
|
||||
@@ -1,15 +0,0 @@
|
||||
name: Disallow "On Hold" PRs
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, labeled, unlabeled, synchronize]
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
label-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check for "On Hold" label
|
||||
uses: egmacke/action-check-label@v3
|
||||
with:
|
||||
label: On Hold
|
||||
state: absent
|
||||
@@ -1,38 +0,0 @@
|
||||
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
|
||||
|
||||
name: Publish docs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.x]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install dependencies (Node.js)
|
||||
uses: bahmutov/npm-install@v1
|
||||
with:
|
||||
useRollingCache: true
|
||||
install-command: npm ci
|
||||
- name: Install dependencies (Python)
|
||||
run: PIP_BREAK_SYSTEM_PACKAGES=1 pip install -r packages/docutils/requirements.txt
|
||||
- name: Publish docs
|
||||
run: |
|
||||
cd packages/appium
|
||||
npm run publish:docs
|
||||
@@ -1,30 +0,0 @@
|
||||
name: Validate Renovate Configs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '.github/workflows/renovate.yml' # this file
|
||||
- '.renovaterc.json'
|
||||
- 'renovate/default.json'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '.github/workflows/renovate.yml' # this file
|
||||
- '.renovaterc.json'
|
||||
- 'renovate/default.json'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
renovate:
|
||||
name: Check Renovate Configs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Validate Renovate Config
|
||||
uses: rinchsan/renovate-config-validator@v0.2.0
|
||||
with:
|
||||
pattern: '{.renovaterc.json,renovate/default.json}'
|
||||
+3
-38
@@ -2,20 +2,19 @@
|
||||
*.swp
|
||||
.DS_Store
|
||||
node_modules
|
||||
sample-code
|
||||
*.trace
|
||||
xcuserdata
|
||||
*.sublime-*
|
||||
test/functional/_joined
|
||||
*.iml
|
||||
!examples/java/*.iml
|
||||
*.autosave
|
||||
.idea/
|
||||
!examples/java/.idea/
|
||||
*.log
|
||||
*.t
|
||||
artifacts
|
||||
input
|
||||
./output
|
||||
output
|
||||
lib/devices/android/bootstrap/bin/*
|
||||
lib/devices/android/bootstrap/local.properties
|
||||
lib/devices/android/bootstrap/project.properties
|
||||
@@ -24,45 +23,11 @@ lib/devices/android/bootstrap/target/
|
||||
.*~
|
||||
*~
|
||||
org.eclipse.ltk.core.refactoring.prefs
|
||||
/selendroid
|
||||
.appiumconfig*
|
||||
build/
|
||||
.idea
|
||||
*DerivedData
|
||||
__pycache__
|
||||
certificate.cert
|
||||
certificate.key
|
||||
|
||||
# csharp
|
||||
*.pyc
|
||||
*.pdb
|
||||
.vs
|
||||
|
||||
#vscode
|
||||
.history
|
||||
|
||||
old
|
||||
.tern-project
|
||||
coverage
|
||||
docs/mkdocs.yml
|
||||
examples/javascript-wd/node_modules
|
||||
examples/php/vendor
|
||||
examples/php/composer.lock
|
||||
examples/java/out/
|
||||
examples/ruby/Gemfile.lock
|
||||
examples/python/test/results/
|
||||
examples/python/test/input
|
||||
examples/python/.pytest_cache/
|
||||
examples/csharp/test/bin
|
||||
examples/csharp/test/obj
|
||||
examples/csharp/test/bin
|
||||
examples/csharp/packages
|
||||
appium.zip
|
||||
.vscode/settings.json
|
||||
.nyc_output
|
||||
*.lerna_backup
|
||||
**/build-fixtures/**
|
||||
*.tsbuildinfo
|
||||
packages/*/LICENSE
|
||||
\!packages/*/LICENSE
|
||||
local_appium_home
|
||||
*.tgz
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"excludeFiles": ["node_modules/**"],
|
||||
"requireCurlyBraces": ["for", "while", "do", "try", "catch"],
|
||||
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch",
|
||||
"return", "try", "catch", "function"],
|
||||
"disallowMixedSpacesAndTabs": true,
|
||||
"disallowTrailingWhitespace": true,
|
||||
"requireSpacesInFunctionExpression": {
|
||||
"beforeOpeningCurlyBrace": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
submodules
|
||||
node_modules
|
||||
lib/server/static
|
||||
lib/devices/firefoxos/atoms
|
||||
/Users/baba/Work/appium/ci/standalone-tools/node_modules
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"laxcomma": true,
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"node": true,
|
||||
"eqeqeq": true,
|
||||
"trailing": true,
|
||||
"indent": 2,
|
||||
"esnext": true,
|
||||
"experimental": ["asyncawait"]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
module.exports = {
|
||||
'*.(js|ts)': ['eslint --fix', 'prettier --write'],
|
||||
'appium-config-schema.js': () => [
|
||||
'npm run --workspace=./packages/schema build',
|
||||
'git add -A packages/schema/lib/appium-config.schema.json',
|
||||
'npm run --workspace=./packages/types build',
|
||||
'git add -A packages/types/lib/appium-config.ts',
|
||||
],
|
||||
'!(package|package-lock)*.json': ['prettier --write'],
|
||||
};
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
require: ['ts-node/register'],
|
||||
// forbids use of .only() in CI
|
||||
forbidOnly: Boolean(process.env.CI),
|
||||
color: true,
|
||||
timeout: '5s',
|
||||
};
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
assets/
|
||||
submodules/
|
||||
test/
|
||||
_vimrc_local.vim
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.*~
|
||||
.DS_Store
|
||||
.travis.yml
|
||||
*.log
|
||||
*.trace
|
||||
*.sublime-
|
||||
*.prefs
|
||||
.jshintrc
|
||||
./.npmignore
|
||||
@@ -1,4 +0,0 @@
|
||||
# Do not disable package-lock. Disabling package-lock also disables npm-shrinkwrap
|
||||
package-lock=true
|
||||
save-exact=true
|
||||
foreground-scripts=true
|
||||
@@ -1,13 +0,0 @@
|
||||
**/node_modules/**
|
||||
**/build/**
|
||||
**/fixtures/**
|
||||
**/*.min.*
|
||||
**/*.md
|
||||
package-lock.json
|
||||
package.json
|
||||
**/.vscode/**
|
||||
**/*.html
|
||||
**/generated/**
|
||||
# generated
|
||||
packages/types/lib/appium-config.ts
|
||||
**/*.hbs
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["github>appium/appium//renovate/default"],
|
||||
"schedule": [
|
||||
"after 10pm",
|
||||
"before 5:00am"
|
||||
],
|
||||
"timezone": "America/Vancouver"
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- "stable"
|
||||
- "4"
|
||||
script:
|
||||
- npm run lint
|
||||
- npm run test
|
||||
after_success:
|
||||
- gulp coveralls
|
||||
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"stateful.runme"
|
||||
]
|
||||
}
|
||||
Vendored
-50
@@ -1,50 +0,0 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"args": [
|
||||
"--log-level=debug"
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {
|
||||
"_FORCE_LOGS": "1"
|
||||
},
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"name": "Run Appium",
|
||||
"program": "${workspaceFolder}/node_modules/.bin/appium",
|
||||
"request": "launch",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"sourceMaps": true,
|
||||
"type": "node"
|
||||
},
|
||||
{
|
||||
"args": [
|
||||
"--colors",
|
||||
"--no-timeout",
|
||||
"${file}"
|
||||
],
|
||||
"autoAttachChildProcesses": true,
|
||||
"console": "integratedTerminal",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"name": "Test Current File w/ Mocha",
|
||||
"program": "${workspaceFolder}/node_modules/.bin/mocha",
|
||||
"request": "launch",
|
||||
"runtimeArgs": [
|
||||
"--require",
|
||||
"ts-node/register"
|
||||
],
|
||||
"skipFiles": [
|
||||
"<node_internals>/**",
|
||||
"**/node_modules/mocha/**",
|
||||
"**/node_modules/lodash/**",
|
||||
"**/node_modules/ts-node/**"
|
||||
],
|
||||
"sourceMaps": true,
|
||||
"type": "node"
|
||||
}
|
||||
],
|
||||
"version": "0.2.0"
|
||||
}
|
||||
Vendored
-19
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "dev",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$tsc-watch"
|
||||
],
|
||||
"label": "npm: dev",
|
||||
"detail": "npm run dev",
|
||||
"isBackground": true
|
||||
}
|
||||
]
|
||||
}
|
||||
+2169
-31
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,63 @@
|
||||
# Contributing to Appium
|
||||
|
||||
There are a lot of different ways to contribute to Appium. See below for
|
||||
everything you can do and the processes to follow for each contribution method.
|
||||
Note that no matter how you contribute, your participation is governed by our
|
||||
[Code of Conduct](CONDUCT.md).
|
||||
|
||||
### Make changes to the Appium code or docs
|
||||
|
||||
Fork the project, make a change, and send a pull request! Please have a look at
|
||||
our [Style Guide](/docs/en/contributing-to-appium/style-guide-2.0.md) before
|
||||
getting to work. Please make sure the unit and functional tests pass before
|
||||
sending a pull request; for more information on how to run tests, keep reading!
|
||||
|
||||
Make sure you read and follow the setup instructions in the README first. And note
|
||||
that all participation in the Appium community (including code submissions) is
|
||||
governed by our [Code of Conduct](CONDUCT.md). Then, have a look at our
|
||||
[running from source doc](/docs/en/contributing-to-appium/appium-from-source.md) for more
|
||||
information on how to get set up to run tests and start slinging code.
|
||||
|
||||
You will probably also want to have a look at this more in-depth [Developer's
|
||||
Overview](/docs/en/contributing-to-appium/developers-overview.md) of the Appium
|
||||
project, how Appium is architected, how to make changes to modules, and so on.
|
||||
|
||||
Finally, before we accept your code, you will need to have signed our
|
||||
[Contributor License
|
||||
Agreement](https://docs.google.com/forms/d/1lOfXRw_0VCk7gYzjj4WLetGu7yelDVo5LWh0z7pGftE/viewform).
|
||||
|
||||
### Become an Appium Triager
|
||||
|
||||
You can help us manage our issue tracker! All you need is enough familiarity
|
||||
with Appium to try and reproduce bugs. We triage issues by having conversations
|
||||
with the issue creator and then either closing the issue or moving it into the
|
||||
[Bugs](https://github.com/appium/appium/milestones/Bugs) or
|
||||
[Features](https://github.com/appium/appium/milestones/Features) milestone. We
|
||||
use these buckets as the backlogs for our upcoming releases.
|
||||
|
||||
We use this "algorithm" for triaging issues, which anyone can jump in and follow:
|
||||
|
||||
1. If issue is a feature request, discuss amongst Appium devs.
|
||||
* If we decide to build it, add to the Features milestone.
|
||||
* If we decide not to build it, just close.
|
||||
2. If issue is a bug report, attempt to verify
|
||||
* If it's a duplicate, close with link to bug already reported.
|
||||
* If it ultimately can't be verified, close until we have enough information to verify (e.g., in most cases we need a full set of Appium logs to help diagnose an issue).
|
||||
* If the user hasn't provided enough information, keep asking for enough information to verify.
|
||||
* If it's a verified new bug, add it to the Bugs milestone.
|
||||
* If we have been waiting for a reply from the user for over 3 weeks, close.
|
||||
|
||||
If you're interested in joining our triage rotation, contact
|
||||
[@jlipps](https://github.com/jlipps) or
|
||||
[@imurchie](https://github.com/imurchie).
|
||||
|
||||
### Help out on our forums
|
||||
|
||||
We can always use help on our forums at
|
||||
[discuss.appium.io](https://discuss.appium.io)! Hop on over and see if there
|
||||
are any questions that you can answer.
|
||||
|
||||
### Submit bug reports or feature requests
|
||||
|
||||
Just use the GitHub issue tracker to submit your bug reports and feature
|
||||
requests. If you are submitting a bug report, please follow the [issue template](https://github.com/appium/appium/issues/new).
|
||||
+24
-138
@@ -12,22 +12,19 @@ Appium are also incentivized to give back.
|
||||
### The Technical Committee
|
||||
|
||||
The project is officially led by a Technical Committee (TC), currently
|
||||
consisting of:
|
||||
|
||||
* [@jlipps](https://github.com/jlipps)
|
||||
* [@mykola-mokhnach](https://github.com/mykola-mokhnach)
|
||||
* [@eglitise](https://github.com/eglitise)
|
||||
* [@KazuCocoa](https://github.com/KazuCocoa)
|
||||
|
||||
They all represent different companies and different types of contribution to
|
||||
the Appium Project. The TC is responsible for high-level decisions (like
|
||||
establishing a feature roadmap, accepting sponsorship, organizing conferences,
|
||||
etc...), adjudicating conflicts between members of the community, and making
|
||||
changes to the project's governance processes.
|
||||
consisting of [@jlipps](https://github.com/jlipps),
|
||||
[@bootstraponline](https://github.com/bootstraponline),
|
||||
[@penguinho](https://github.com/penguinho), and
|
||||
[@dandoveralba](https://github.com/dandoveralba), who all represent different
|
||||
companies and different types of contribution to the Appium Project. The TC is
|
||||
responsible for high-level decisions (like establishing a feature roadmap,
|
||||
accepting sponsorship, organizing conferences, etc...), adjudicating conflicts
|
||||
between members of the community, and making changes to the project's
|
||||
governance processes.
|
||||
|
||||
* Membership in the TC is granted by unanimous vote of current TC members.
|
||||
* TC members can step down at any time.
|
||||
* No more than 1/3 (or 2, whichever is higher) of TC members may belong to the same company.
|
||||
* No more than 1/4 of TC members may belong to the same company.
|
||||
* Changes to project governance require unanimous vote of the TC.
|
||||
|
||||
### Project Committers
|
||||
@@ -46,104 +43,25 @@ and so on.
|
||||
* Any committer can decide to close a PR or issue if they determine the change doesn't suit the project.
|
||||
* Appium has a large ecosystem of repositories. Some are 'core' in the sense of being central subpackages with a lot of traffic like `appium/appium` or `appium/appium-ios-driver`. Others are 'peripheral' in the sense of receiving few changes, being maintained by 1 person or no one, etc..., like `appium/ruby_lib` or `appium/appium_thor` For 'core' repos, committers should not merge their own code straightaway. Like all contributors they should open a PR and get a +1 from another committer. For 'peripheral' repos for which they are the sole maintainer or for which they have a good understanding, it is obtuse to insist on another contributor's +1 and this rule should be relaxed in that case. In sum: use good judgment and don't ram code through without a review when you can help it.
|
||||
|
||||
The current committers are (along with their primary areas(s) of ownership or maintenance):
|
||||
The current committers are (in addition to the TC members above):
|
||||
[imurchie](https://github.com/imurchie), [sebv](https://github.com/sebv),
|
||||
[Jonahss](https://github.com/Jonahss), [moizjv](https://github.com/moizjv),
|
||||
[scottdixon](https://github.com/scottdixon),
|
||||
[Astro03](https://github.com/Astro03) (appium-dot-exe),
|
||||
[edgy360](https://github.com/edgy360) (appium-dot-app).
|
||||
|
||||
* [@dan-maor](https://github.com/Dan-Maor) - XCUITest driver and iOS internals
|
||||
* [@dor-bl](https://github.com/Dor-bl) - DotNet client
|
||||
* [@eglitise](https://github.com/eglitise) - Appium server, Inspector
|
||||
* [@jlipps](https://github.com/jlipps) - Appium server, Inspector
|
||||
* [@kazucocoa](https://github.com/KazuCocoa) - all Appium projects
|
||||
* [@laolubenson](https://github.com/laolubenson) - DotNet client
|
||||
* [@mwakizaka](https://github.com/mwakizaka) - XCUITest driver
|
||||
* [@mykola-mokhnach](https://github.com/mykola-mokhnach) - all Appium projects
|
||||
* [@rerorero](https://github.com/rerorero) - XCUITest/UIA2 driver
|
||||
* [@saikrishna321](https://github.com/saikrishna321) - Java client
|
||||
* [@srinivasantarget](https://github.com/SrinivasanTarget) - Java client
|
||||
* [@tomriddly](https://github.com/tomriddly) - appium-ios-device
|
||||
* [@valfirst](https://github.com/valfirst) - Java client
|
||||
### Contributors
|
||||
|
||||
See [Emeritus Contributors](#emeritus-contributors) below for a list of people who formerly made
|
||||
significant contributions to the project but are no longer actively committing.
|
||||
|
||||
### Other Contributors
|
||||
|
||||
Other, less formal, kinds of contribution are outlined in our [Contributing Guide](https://appium.io/docs/en/latest/contributing/).
|
||||
We also very much appreciate those who spend their valuable time assisting with the [Appium forums](https://discuss.appium.io).
|
||||
Current high-level forum contributors and mods include:
|
||||
|
||||
* [aleksei](https://discuss.appium.io/u/aleksei/summary)
|
||||
* [wreed](https://discuss.appium.io/u/wreed/summary)
|
||||
Other, less formal, kinds of contribution are outlined in our
|
||||
[CONTRIBUTING](/CONTRIBUTING.md) doc.
|
||||
|
||||
### Sponsorship
|
||||
|
||||
The Appium project welcomes the sponsorship of individuals and organizations. There are two types
|
||||
of sponsorship: those related to contributions of Appium maintenance and leadership, and those
|
||||
related to contributions of funds. Both are extremely important to the ongoing health of the
|
||||
project. Financial sponsorship is mediated through our [OpenCollective page](https://opencollective.com/appium).
|
||||
Sponsorship tiers and benefits are described below:
|
||||
|
||||
- **Development Partners**: The primary need of any open source project is for sustained maintenance and contributorship. Companies that officially sponsor such development with dedicated employee time are recognized as Development Partners, and receive the same benefits as the highest tier of financial sponsorship. To be considered a Development Partner, a company must devote at least 50% of a full-time employee's time to Appium maintenance. This means that the contributors designated by the company must have been appointed as "committers" in good standing of one or more core Appium repositories. (See above for a description of how to become a committer).
|
||||
- **Strategic Partners**: Representing the highest tier of ongoing financial support for the project, Strategic Partners are what make our compensation scheme for contributors possible, and we thank them for their significant investment into the project! More than financial contribution, Strategic Partners help elevate Appium's position in the industry through marketing and evangelism efforts, and partner with the Appium team to help make Appium better. Along with the Development Partners, Strategic Partners have their logos displayed prominently on our website, and have the ability to link to their Appium-related products in a few relevant places in our documentation.
|
||||
- **Gold, Silver, and Bronze Sponsors**: these sponsorship levels correspond to different amounts of recurring financial contribution that generously support our contributor compensation scheme. Sponsors at these levels also have the opportunity to display their logo on our website.
|
||||
- **Backers**: individuals who benefit from the Appium project can also donate on a one-time or recurring basis, at any amount, and will be recognized as Backers for their contribution!
|
||||
|
||||
To become a sponsor at one of these levels, follow the process indicated at the [OpenCollective
|
||||
page](https://opencollective.com/appium).
|
||||
|
||||
### Compensation Scheme
|
||||
|
||||
With funds received through sponsorship, the Appium project wants to incentivize contributions of
|
||||
code, documentation efforts, maintenance, and project leadership. We have developed a scheme
|
||||
(inspired by one developed at the [WebdriverIO](https://github.com/webdriverio/webdriverio)
|
||||
project) for disbursing funds on a monthly basis to those who contribute to the project, as well as
|
||||
some other "upstream" open source projects.
|
||||
|
||||
Each month, 15% of sponsorship funds received will be donated to upstream projects, based on the
|
||||
discretion of the current TC. At this point, no attempt will be made to formalize quantitative
|
||||
notions of relevance. If you manage a project upstream of Appium and would like to be considered as
|
||||
part of this donation group, give us a shout!
|
||||
|
||||
Of the remaining 85% of sponsorship funds, 70% (roughly 60% of the original total) will go to
|
||||
project Committers (i.e., those in a role of maintenance), and 30% (roughly 25% of the original
|
||||
total) will go to Contributors (i.e., those making one-off or periodic contributions). The way that
|
||||
Committers and Contributors are paid for their efforts differs.
|
||||
|
||||
For Committers, each Committer will keep a monthly time sheet of hours contributed to the project.
|
||||
At the end of each month, the hours tracked from all Committers will be totalled, and then the
|
||||
Committer-allocated funds will be disbursed (via OpenCollective) on a pro rata basis. Within this
|
||||
scheme, Committers agree not to submit hours worked as part of their employment with a Development
|
||||
Partner (since this is part of the "sponsorship" contribution of the Development Partner).
|
||||
|
||||
For Contributors, when they make contributions which are successfully merged into the project,
|
||||
a Committer can discretionarily assign a "value tier" to the contribution. The "value tiers" and
|
||||
corresponding payouts are as follows:
|
||||
|
||||
- XS: a trivial change (e.g. a typo change or applying of an automatically suggested security
|
||||
patch). \$0.
|
||||
- S: a small but useful change. \$25.
|
||||
- M: a medium-small or slightly more complex change. \$50.
|
||||
- L: a very valuable or sizable change. \$100.
|
||||
- XL: a massive change or set of changes. \$500.
|
||||
|
||||
At the end of each month, Committers will total up the number of changes receiving potential
|
||||
payout. If the total amount of funds allocated for Contributor payout exceeds the total amount to
|
||||
be paid, then each Contributor will receive an OpenCollective link to claim their funds. If not
|
||||
enough funds exist to cover all payouts, then the payout amounts will be scaled down in a pro rata
|
||||
fashion.
|
||||
|
||||
The scope for Committer or Contributor payouts is work completed within any "core" Appium
|
||||
repository (i.e., those officially maintained by the Appium team, residing within the Appium
|
||||
organization on GitHub, under `https://github.com/appium`).
|
||||
|
||||
Some disclaimers: Payments will happen exclusively via OpenCollective. Recipients of funds are
|
||||
responsible for maintaining their OpenCollective account in a fashion where funds can be disbursed,
|
||||
and are responsible for any and all tax, financial, or legal consequences of receiving money in
|
||||
this way. Receipt of funds from this scheme holds the Appium project and the OpenJS Foundation free
|
||||
of any claim or obligation. While this document exists to clearly and publicly lay out the terms
|
||||
under which payments are generally made, the TC retains the right to grant or withhold funding on
|
||||
a discretionary of special basis. Basically, this scheme is run at the project's discretion, and is
|
||||
not a public service. Making contributions to the project under this scheme does not obligate the
|
||||
project to pay you for such work, or otherwise compensate you in any way.
|
||||
The Appium project welcomes sponsorship of various organizations. Specific
|
||||
details are not yet available but in general we will accept monetary donations,
|
||||
contribution of code, contribution of dedicated committers, or donations of
|
||||
other goods or service (internet hosting, etc...). To begin the conversation,
|
||||
reach out to one of the TC members.
|
||||
|
||||
### Raising Issues Related to Governance
|
||||
|
||||
@@ -151,35 +69,3 @@ This governance model necessarily leaves many situations unspecified. If
|
||||
questions arise as to how a given situation should proceed according to the
|
||||
overall goals of the project, the best thing to do is to open a GitHub issue
|
||||
and ping the TC members.
|
||||
|
||||
### Emeritus Contributors
|
||||
|
||||
* [@aluedeke](https://github.com/aluedeke)
|
||||
* [@astro03](https://github.com/Astro03)
|
||||
* [@bayandin](https://github.com/bayandin)
|
||||
* [@boneskull](https://github.com/boneskull)
|
||||
* [@bootstraponline](https://github.com/bootstraponline)
|
||||
* [@dandoveralba](https://github.com/dandoveralba)
|
||||
* [@ddkjin](https://github.com/ddkjin)
|
||||
* [@drpy](https://github.com/drpy)
|
||||
* [@dylanLacey](https://github.com/DylanLacey)
|
||||
* [@filmaj](https://github.com/filmaj)
|
||||
* [@gempesaw](https://github.com/gempesaw)
|
||||
* [@hugs](https://github.com/hugs)
|
||||
* [@imurchie](https://github.com/imurchie)
|
||||
* [@jamieEdge](https://github.com/JamieEdge)
|
||||
* [@jdeff](https://github.com/jdeff)
|
||||
* [@jonahss](https://github.com/Jonahss)
|
||||
* [@maudineormsby](https://github.com/maudineormsby)
|
||||
* [@moizjv](https://github.com/moizjv)
|
||||
* [@peepa](https://github.com/peepa)
|
||||
* [@penguinho](https://github.com/penguinho)
|
||||
* [@sbonebrake](https://github.com/sbonebrake)
|
||||
* [@scottdixon](https://github.com/scottdixon)
|
||||
* [@sebv](https://github.com/sebv)
|
||||
* [@sravanmedarapu](https://github.com/sravanmedarapu)
|
||||
* [@stuartbrussell-intuit](https://github.com/stuartbrussell-intuit)
|
||||
* [@tikhomirovSergey](https://github.com/TikhomirovSergey)
|
||||
* [@titusfortner](https://github.com/titusfortner)
|
||||
* [@vgrigoruk](https://github.com/vgrigoruk)
|
||||
* [@vmaxim](https://github.com/vmaxim)
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
Google Summer of Code Ideas
|
||||
=====
|
||||
|
||||
Appium is excited to participate as a [Google Summer of Code](https://summerofcode.withgoogle.com/) sponsor project. Here's a fun list of ideas that a Summer of Code student participant can use as a foundation for thinking about what to contribute to Appium!
|
||||
|
||||
|Idea|Description|
|
||||
|----|-----------|
|
||||
|Apple tvOS Support|Our users have been asking for an Appium driver for Apple tvOS apps. Is this possible? We're not entirely sure! Why not be awesome and build it?|
|
||||
|Test App revamp|Appium uses a number of poorly-designed mobile applications in its own testing. We have to use a variety of apps because we need to test that Appium can automate all the various controls and platform features that mobile vendors provide. Really what we need is one cross-platform app (or one app per platform) that exhibit all and only the features we need to test. This would be a fun project to build some mobile apps used for testing and also demoing Appium at events and in training videos, etc...|
|
||||
|Tooling and Performance|We haven't instrumented Appium with very many performance metrics, and don't really know if we're missing some low-hanging fruit in terms of performance. Maybe you can help us do that?|
|
||||
|Babel|We have a lot of repos, and they're all on a really old version of Babel. They all need to stay in sync. How can we make this situation better, and upgrade to the latest and greatest?|
|
||||
|Unity3d Driver|Historically, Appium hasn't been great at automating games. We don't have any particular support for the frameworks used to create games. Unity is a popular one, for example. What if we could write an Appium driver that talked to an embedded process in a test version of a Unity game, that allowed us to find and interact with 3d elements? It would be amazing! You can also be amazing and lead Appium into this new world.|
|
||||
|Testing the Internet of Things|Appium's architecture makes it dead simple to integrate drivers for automating new technologies. What about _really_ new technologies like IoT devices? Help to redefine the semantics of the WebDriver protocol for use with IoT, and build a driver for an IoT device to prove it out.|
|
||||
|Driver for X|Have an idea of something else Appium could automate that it doesn't already? Build a driver for it! This would involve some awesome Node.js code, plus whatever else is needed to integrate with the platform you have in mind.|
|
||||
|
||||
Hopefully this gives you some ideas of fun projects that would be substantial and long-lasting contributions to the Appium community.
|
||||
@@ -1,192 +1,4 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright OpenJS Foundation and other contributors, https://openjsf.org/
|
||||
Copyright 2012-2016 Sauce Labs, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,222 +1,165 @@
|
||||
[](https://vshymanskyy.github.io/StandWithUkraine/)
|
||||
|
||||
<p align="center">
|
||||
<a href="https://appium.io/">
|
||||
<img alt="Appium" src="https://raw.githubusercontent.com/appium/appium/master/packages/appium/docs/overrides/assets/images/appium-logo-horiz.png" width="500">
|
||||
</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
Cross-platform test automation for native, hybrid, mobile web and desktop apps.
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
## Appium
|
||||
|
||||
[](https://npmjs.org/package/appium)
|
||||
[](https://david-dm.org/appium/appium)
|
||||
[](https://david-dm.org/appium/appium#info=devDependencies)
|
||||
|
||||
[](https://npmjs.org/package/appium)
|
||||
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium?ref=badge_shield)
|
||||
[](https://github.com/vshymanskyy/StandWithUkraine/)
|
||||
[](http://issuestats.com/github/appium/appium)
|
||||
[](http://issuestats.com/github/appium/appium)
|
||||
|
||||
</div>
|
||||
[](https://team-appium.ci.cloudbees.com/job/Appium/)
|
||||
|
||||
***
|
||||
Appium is an open source, cross-platform test automation tool for native, hybrid and mobile web apps, tested on simulators (iOS, FirefoxOS), emulators (Android), and real devices (iOS, Android, Windows, FirefoxOS).
|
||||
|
||||
<p align="center"><b>
|
||||
<a href="https://appium.io">Documentation</a> |
|
||||
<a href="https://appium.io/docs/en/latest/intro/">Get Started</a> |
|
||||
<a href="https://appium.io/docs/en/latest/ecosystem/">Ecosystem</a> |
|
||||
<a href="https://github.com/appium/appium/blob/master/packages/appium/CHANGELOG.md">Changelog</a> |
|
||||
<a href="https://appium.io/docs/en/latest/contributing/">Contributing Guide</a> |
|
||||
<a href="https://discuss.appium.io">Discussion Forum</a>
|
||||
</b></p>
|
||||
|
||||
***
|
||||
### Supported Platforms
|
||||
|
||||
Appium is an open-source automation framework that provides
|
||||
[WebDriver](https://www.w3.org/TR/webdriver/)-based automation possibilities for a wide range of
|
||||
different mobile, desktop and IoT platforms. Appium is modular and extensible, and supports multiple
|
||||
programming languages, which means there is an entire ecosystem of related software:
|
||||
* [__Drivers__](#drivers) add support for automating specific platforms
|
||||
* [__Clients__](#clients) allow writing Appium tests in your programming language of choice
|
||||
* [__Plugins__](#plugins) allow to further extend Appium functionality
|
||||
* iOS
|
||||
* Android
|
||||
* Windows
|
||||
* FirefoxOS
|
||||
|
||||
## Migrating From Appium 1 to Appium 2
|
||||
See the [platform support doc](/docs/en/appium-setup/platform-support.md) for more detailed information.
|
||||
|
||||
As of January 1st, 2022, the Appium team no longer maintains or supports Appium 1. All officially
|
||||
supported platform drivers are only compatible with Appium 2.
|
||||
### Why Appium?
|
||||
|
||||
__[Please read the Migration Guide](https://appium.io/docs/en/latest/guides/migrating-1-to-2/) if you
|
||||
are still using Appium 1.__
|
||||
|
||||
> [!WARNING]
|
||||
> If you use Appium Desktop or Appium Server GUI, you will not be able to upgrade to Appium 2, as
|
||||
both of these tools have been deprecated. Please use [Appium Inspector](https://github.com/appium/appium-inspector)
|
||||
in combination with a standalone Appium 2 server.
|
||||
|
||||
## Installation
|
||||
|
||||
Appium can be installed using `npm` (other package managers are not currently supported). Please
|
||||
check the [installation docs](http://appium.io/docs/en/latest/quickstart/install/) for the
|
||||
system requirements and further information.
|
||||
|
||||
If upgrading from Appium 1, make sure Appium 1 is fully uninstalled (`npm uninstall -g appium`).
|
||||
Unexpected errors might appear if this has not been done.
|
||||
|
||||
```bash
|
||||
npm i -g appium
|
||||
```
|
||||
|
||||
Note that this will only install the core Appium server, which cannot automate anything on its own.
|
||||
Please install [drivers](#drivers) for your target platforms in order to automate them.
|
||||
|
||||
## Drivers
|
||||
|
||||
Appium supports app automation across a variety of platforms, like iOS, Android, macOS, Windows,
|
||||
and more. Each platform is supported by one or more "drivers", which know how to automate that
|
||||
particular platform. You can find a full list of officially-supported and third-party drivers in
|
||||
[Appium Ecosystem's Drivers page](http://appium.io/docs/en/latest/ecosystem/drivers/).
|
||||
|
||||
Driver management is done using [Appium's Extension command-line interface](http://appium.io/docs/en/latest/cli/extensions/):
|
||||
|
||||
```bash
|
||||
# Install an official driver from npm (see documentation for a list of such drivers)
|
||||
appium driver install <driver-name>
|
||||
# Install any driver from npm
|
||||
appium driver install --source=npm <driver-name>
|
||||
# See documentation for installation from other sources
|
||||
|
||||
# List already installed drivers
|
||||
appium driver list --installed
|
||||
# Update a driver (it must be already installed)
|
||||
# This will NOT update the major version, in order to prevent breaking changes
|
||||
appium driver update <driver-name>
|
||||
# Update a driver to the most recent version (may include breaking changes)
|
||||
appium driver update <driver-name> --unsafe
|
||||
# Uninstall a driver (it won't last forever, will it?)
|
||||
appium driver uninstall <driver-name>
|
||||
```
|
||||
|
||||
## Clients
|
||||
|
||||
Client libraries enable writing Appium tests in different programming languages. There are
|
||||
officially-supported clients for Java, Python, Ruby, and .NET C#, as well as third-party clients
|
||||
for other languages. You can find a full list of clients in
|
||||
[Appium Ecosystem's Clients page](http://appium.io/docs/en/latest/ecosystem/clients/).
|
||||
|
||||
## Plugins
|
||||
|
||||
Plugins allow you to extend server functionality without changing the server code. The main
|
||||
difference between drivers and plugins is that the latter must be explicitly enabled on
|
||||
Appium server startup (all installed drivers are enabled by default):
|
||||
|
||||
```bash
|
||||
appium --use-plugins=<plugin-name>
|
||||
```
|
||||
|
||||
You can find a full list of officially-supported and third-party plugins in
|
||||
[Appium Ecosystem's Plugins page](http://appium.io/docs/en/latest/ecosystem/plugins/).
|
||||
|
||||
Similarly to drivers, plugin management is also done using
|
||||
[Appium's Extension command-line interface](http://appium.io/docs/en/latest/cli/extensions/):
|
||||
|
||||
```bash
|
||||
# Install an official plugin from npm (see documentation for a list of such plugins)
|
||||
appium plugin install <plugin-name>
|
||||
# Install any plugin from npm
|
||||
appium plugin install --source=npm <plugin-name>
|
||||
# See documentation for installation from other sources
|
||||
|
||||
# List already installed plugins
|
||||
appium plugin list --installed
|
||||
# Update a plugin (it must be already installed)
|
||||
# This will NOT update the major version, in order to prevent breaking changes
|
||||
appium plugin update <plugin-name>
|
||||
# Update a plugin to the most recent version (may include breaking changes)
|
||||
appium plugin update <plugin-name> --unsafe
|
||||
# Uninstall a plugin
|
||||
appium plugin uninstall <plugin-name>
|
||||
```
|
||||
|
||||
## Server Command Line Interface
|
||||
|
||||
In order to start sending commands to the Appium server, it must be running on the URL and port
|
||||
where your client library expects it to listen. [Appium's command-line interface](http://appium.io/docs/en/latest/cli/args/)
|
||||
is used to launch and configure the server:
|
||||
|
||||
```bash
|
||||
# Start the server on the default host (0.0.0.0) and port (4723)
|
||||
appium server
|
||||
# You can also omit the 'server' subcommand
|
||||
appium
|
||||
# Start the server on the given host, port and use a custom base path prefix (the default prefix is '/')
|
||||
appium --address 127.0.0.1 --port 9000 --base-path /wd/hub
|
||||
```
|
||||
|
||||
Appium supports execution of parallel server processes, as well as parallel driver sessions within a
|
||||
single server process. Refer the corresponding driver documentations regarding which mode is optimal
|
||||
for the particular driver or whether it supports parallel sessions.
|
||||
|
||||
## Why Appium?
|
||||
|
||||
1. You usually don't have to recompile your app or modify it in any way, due to the use of standard
|
||||
automation APIs on all platforms.
|
||||
2. You can write tests with your favorite dev tools using any WebDriver-compatible language such as
|
||||
Java, Python, Ruby and C#. There are also third party client implementations for other languages.
|
||||
1. You don't have to recompile your app or modify it in any way, due
|
||||
to use of standard automation APIs on all platforms.
|
||||
2. You can write tests with your favorite dev tools using any [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html)-compatible
|
||||
language such as Java, [Objective-C](https://github.com/appium/selenium-objective-c),
|
||||
JavaScript with Node.js (in [promise, callback](https://github.com/admc/wd) or [generator](https://github.com/jlipps/yiewd) flavors),
|
||||
PHP, Python, [Ruby](https://github.com/appium/ruby_lib), C#, Clojure, or Perl
|
||||
with the Selenium WebDriver API and language-specific client libraries.
|
||||
3. You can use any testing framework.
|
||||
4. Some drivers like `xcuitest` and `uiautomator2` have built-in mobile web and hybrid app support.
|
||||
Within the same script, you can switch seamlessly between native app automation and webview
|
||||
automation, all using the WebDriver model that's already the standard for web automation.
|
||||
5. You can run your automated tests locally and in a cloud. There are multiple cloud providers that
|
||||
support various Appium drivers (mostly targeting iOS and Android mobile automation).
|
||||
6. [Appium Inspector](https://github.com/appium/appium-inspector) can be used to visually inspect
|
||||
the page source of applications across different platforms, facilitating easier test development.
|
||||
|
||||
Investing in the [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) protocol means you
|
||||
are betting on a single, free, and open protocol for testing that has become a web standard. Don't
|
||||
lock yourself into a proprietary stack.
|
||||
Investing in the [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) protocol means you are betting on a single, free and open protocol for testing that has become a defacto standard. Don't lock yourself into a proprietary stack.
|
||||
|
||||
For example, if you use Apple's XCUITest library without Appium, you can only write tests using
|
||||
Obj-C/Swift, and you can only run tests through Xcode. Similarly, with Google's UiAutomator or
|
||||
Espresso, you can only write tests in Java/Kotlin. Appium opens up the possibility of true
|
||||
cross-platform native app automation, for mobile and beyond!
|
||||
If you use Apple's UIAutomation library without Appium you can only write tests
|
||||
using JavaScript and you can only run tests through the Instruments application.
|
||||
Similarly, with Google's UiAutomator you can only write tests in Java. Appium
|
||||
opens up the possibility of true cross-platform native mobile automation. Finally!
|
||||
|
||||
If you are looking for a more comprehensive description of what this is all about, please read our
|
||||
documentation on [How Does Appium Work?](https://appium.io/docs/en/latest/intro/appium/).
|
||||
### I don't get it yet...
|
||||
|
||||
## Sponsors
|
||||
If you're new to Appium, or want a fuller description of what this is all about, please read our [Introduction to Appium Concepts](/docs/en/about-appium/intro.md).
|
||||
|
||||
Appium has a [Sponsorship Program](GOVERNANCE.md#sponsorship)! If you or your company uses Appium
|
||||
and wants to give back financially to the project, we use these funds to [encourage development and
|
||||
contributions](GOVERNANCE.md#compensation-scheme), as well as support other open source projects we
|
||||
rely on. [Become a sponsor](https://opencollective.com/appium) via our OpenCollective page.
|
||||
### Requirements
|
||||
|
||||
### Development and Strategic Partners
|
||||
Your environment needs to be setup for the particular mobile platforms that you
|
||||
want to run tests on. See below for particular platform requirements.
|
||||
|
||||
Appium is incredibly grateful to our Development and Strategic Partners for their sustained
|
||||
contribution of project development and leadership!
|
||||
If you want to run Appium via an `npm install`, hack with or contribute to Appium, you will need
|
||||
[node.js and npm](http://nodejs.org) 4 or greater (use [n](https://github.com/visionmedia/n) or
|
||||
`brew install node` to install Node.js. Make sure you have not installed Node or Appium with `sudo`,
|
||||
otherwise you'll run into problems). We recommend the latest stable version.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.browserstack.com/browserstack-appium?utm_campaigncode=701OW00000AoUTQYA3&utm_medium=partnered&utm_source=appium">
|
||||
<picture>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-browserstack-dark.png" media="(prefers-color-scheme: dark)"/>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-browserstack-light.png" media="(prefers-color-scheme: light)"/>
|
||||
<img src="packages/appium/docs/overrides/assets/images/sponsor-logo-browserstack-dark.png" width="300" alt="Browserstack"/>
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
To verify that all of Appium's dependencies are met you can use
|
||||
`appium-doctor`. Install it with `npm install -g appium-doctor` (or run it
|
||||
from [source](https://github.com/appium/appium-doctor)), then run
|
||||
`appium-doctor` and supply the `--ios` or `--android` flags to verify that all
|
||||
of the dependencies are set up correctly.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://saucelabs.com/resources/blog/appium-strategic-partner"><img src="packages/appium/docs/overrides/assets/images/sponsor-logo-sauce.png"
|
||||
width="300" alt="Sauce Labs" /></a>
|
||||
</p>
|
||||
You also need to download the Appium client for your language so you can write tests. The Appium clients are simple extensions to the WebDriver clients. You can see the list of clients and links to download instructions at the [Appium clients list](/docs/en/about-appium/appium-clients.md).
|
||||
|
||||
### Other Sponsors
|
||||
#### iOS Requirements
|
||||
|
||||
A full list of sponsors is available at our [Sponsors page](https://appium.io/docs/en/latest/sponsors/).
|
||||
* Mac OS X 10.10 or higher, 10.11.1 recommended
|
||||
* XCode >= 6.0, 7.1.1 recommended
|
||||
* Apple Developer Tools (iPhone simulator SDK, command line tools)
|
||||
* [Ensure you read our documentation on setting yourself up for iOS testing!](/docs/en/appium-setup/running-on-osx.md)
|
||||
|
||||
## License
|
||||
#### Android Requirements
|
||||
|
||||
[Apache-2.0](./LICENSE)
|
||||
* [Android SDK](http://developer.android.com) API >= 17 (Additional features require 18/19)
|
||||
* Appium supports Android on OS X, Linux and Windows. Make sure you follow the
|
||||
directions for setting up your environment properly for testing on different OSes:
|
||||
* [linux](/docs/en/appium-setup/running-on-linux.md)
|
||||
* [osx](/docs/en/appium-setup/running-on-osx.md)
|
||||
* [windows](/docs/en/appium-setup/running-on-windows.md)
|
||||
|
||||
#### Windows Requirements
|
||||
|
||||
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium?ref=badge_large)
|
||||
* Windows 10
|
||||
* [Documentation](/docs/en/appium-setup/running-on-windows.md)
|
||||
|
||||
`@appium/logger` package is under [ISC](./packages/logger/LICENSE) License.
|
||||
#### FirefoxOS Requirements
|
||||
|
||||
* [Firefox OS Simulator](https://developer.mozilla.org/en/docs/Tools/Firefox_OS_Simulator)
|
||||
|
||||
### Quick Start
|
||||
|
||||
Kick up an Appium server, and then run a test written in your favorite [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html)-compatible language!
|
||||
You can run an Appium server using node.js or using the application, see below.
|
||||
|
||||
#### Using Node.js
|
||||
|
||||
```
|
||||
$ npm install -g appium
|
||||
$ appium
|
||||
```
|
||||
|
||||
#### Using the App
|
||||
|
||||
* [Download the Appium app](https://bitbucket.org/appium/appium.app/downloads/)
|
||||
* Run it!
|
||||
|
||||
### Writing Tests for Appium
|
||||
|
||||
The main guide for getting started writing and running tests is [the running tests](/docs/en/writing-running-appium/running-tests.md) doc, which includes explanations for iOS, Android, and Android older devices. If you're interested in testing on physical hardware, you might be interested in our [real devices guide](/docs/en/appium-setup/real-devices.md).
|
||||
|
||||
Essentially, we support a subset of the [Selenium WebDriver JSON Wire Protocol](https://w3c.github.io/webdriver/webdriver-spec.html), and extend it so that you can specify mobile-targeted [desired capabilities](/docs/en/writing-running-appium/caps.md) to run your test through Appium.
|
||||
|
||||
You find elements by using a subset of WebDriver's element-finding strategies.
|
||||
See [finding elements](/docs/en/writing-running-appium/finding-elements.md) for detailed information. We also have several extensions to the JSON Wire Protocol for [automating mobile gestures](/docs/en/writing-running-appium/touch-actions.md) like tap, flick, and swipe.
|
||||
|
||||
You can also automate web views in hybrid apps! See the [hybrid app guide](/docs/en/advanced-concepts/hybrid.md)
|
||||
|
||||
This repository contains [many examples of tests in a variety of different languages](https://github.com/appium/sample-code)!
|
||||
|
||||
For the full list of Appium doc pages, visit [this directory](/docs/en/).
|
||||
|
||||
### How It Works
|
||||
|
||||
Appium drives various native automation frameworks and provides an API based on
|
||||
Selenium's [WebDriver JSON wire protocol](https://w3c.github.io/webdriver/webdriver-spec.html).
|
||||
|
||||
Appium drives Apple's UIAutomation library for iOS support, which is based on
|
||||
[Dan Cuellar's](http://github.com/penguinho) work on iOS Auto.
|
||||
|
||||
Android support uses the UiAutomator framework for newer platforms and
|
||||
[Selendroid](http://github.com/DominikDary/selendroid) for older Android platforms.
|
||||
|
||||
Windows support uses Microsoft's [WinAppDriver](https://github.com/Microsoft/WinAppDriver)
|
||||
|
||||
FirefoxOS support leverages [Marionette](https://developer.mozilla.org/en-US/docs/Marionette),
|
||||
an automation driver that is compatible with WebDriver and is used to automate
|
||||
Gecko-based platforms.
|
||||
|
||||
### Contributing
|
||||
|
||||
Please take a look at our [contribution documentation](CONTRIBUTING.md)
|
||||
for instructions on how to build, test and run Appium from source.
|
||||
|
||||
### Roadmap
|
||||
|
||||
Interested in where Appium is heading in the future? Check out the [Roadmap](ROADMAP.md)
|
||||
|
||||
### Project Credits & Inspiration
|
||||
|
||||
[Credits](/docs/en/contributing-to-appium/credits.md)
|
||||
|
||||
### Mailing List
|
||||
|
||||
Announcements and debates often take place on the [Discussion Group](https://discuss.appium.io), be sure to sign up!
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
We put together a [troubleshooting guide](/docs/en/appium-setup/troubleshooting.md).
|
||||
Please have a look here first if you run into any problems. It contains instructions for checking a lot
|
||||
of common errors and how to get in touch with the community if you're stumped.
|
||||
|
||||
### Using Robots
|
||||
|
||||
Using Appium with [Tapster](https://github.com/hugs/tapsterbot) and other robots is possible,
|
||||
check out the [Appium Robots](https://github.com/appium/robots) project!
|
||||
|
||||
+44
-25
@@ -1,30 +1,49 @@
|
||||
# Roadmap
|
||||
Appium Roadmap
|
||||
---------------
|
||||
|
||||
This is not a traditional roadmap. We don't have a typical product team with a typical product
|
||||
manager. The fact that the items below exist on a roadmap is no indication that we will ever have
|
||||
the opportunity to work on them. Instead this is more like a wishlist of outcomes that the project
|
||||
thinks would be valuable. If and when we get additional contributions of development work, this is
|
||||
a set of items that would be great for someone to work on! Ideally, interested devs would find
|
||||
something on this list and own it from start to finish! Let anyone on the project know if you're
|
||||
interested and we can help get you going.
|
||||
This document is designed to be a living record of the current and projected
|
||||
priorities for the Appium project. It is, of course, always subject to change
|
||||
and exists solely to give the community an idea of where we're going. The
|
||||
roadmap is set by the Appium core team. If you have feature suggestions for
|
||||
Appium, please submit a [GitHub issue](https://github.com/appium/appium/issues)
|
||||
and, if of sufficient size and approved by the team, it will be added here. If
|
||||
you have concerns about the roadmap, you can e-mail the Appium devs at
|
||||
`appium-developers@googlegroups.com` or raise a GitHub issue. Note that
|
||||
bugfixes and miscellaneous features are not considered "roadmap projects", and
|
||||
will be addressed in the due course of normal Appium development. This page
|
||||
exists to outline large-scale future plans for Appium.
|
||||
|
||||
### Core projects
|
||||
- **WebDriver BiDi support in the Appium server**: the WebDriver BiDi spec is underway, which details a different method for communicating with drivers. We should implement handling for these methods in our server so that Appium drivers can take advantage of the BiDi spec without additional work on their part.
|
||||
- **Redevelop automatically generated command docs**: due to changing TypeDoc support and the departure of one of our team, we were forced to remove our TypeDoc-based automatic docs generation tool. It would be nice to bring this back in a more maintainable form!
|
||||
## Current Roadmap Projects
|
||||
|
||||
### Driver/platform-specific projects
|
||||
- **Better maintenance for our Android drivers**: we're looking for Android specialists to help maintain our Android drivers (UiAutomator2 and Espresso)
|
||||
- **Better maintenance for our iOS driver**: we're looking for iOS specialists to help maintain our XCUITest driver
|
||||
- **Better maintenance for [appium-ios-device](https://github.com/appium/appium-ios-device)**: this project is using outdated approaches and libraries. If it could be improved it would have a big impact on the performance of the XCUITest driver
|
||||
| Project | Description | ETD | Projected Appium Release |
|
||||
|---------|-------------|-----|--------------------------|
|
||||
|[Architecture Overhaul](https://github.com/appium/appium/issues/5169)|Appium's architecture has grown unwieldy enough that adding new features and preventing regressions has become difficult. A rearchitecture is in order to solve these issues as well as migrate the codebase to a form of JS much easier to work in and understand.|1/2016|1.5|
|
||||
|XCUITest backend integration|Instruments + UIAutomation has been working well for many Appium users, but requires crazy workarounds to deal with bugs which remain unfixed on the Apple side. We should explore Apple's newer technology, XCUITest, in order to see if the overall experience is more stable. This new backend would exist alongside the UIAutomation backend.|3/2016?|Beta in 1.6?|
|
||||
|UiAutomator2 backend integration|Google has released [UiAutomator 2](http://developer.android.com/reference/android/support/test/uiautomator/package-summary.html), and it promises to fix some issues and limitations with the previous UiAutomator support. We will build this inside of Selendroid since it requires an instrumentation context.|3/2016?|TBD|
|
||||
|iOS 9.3 support|Appium should support iOS 9.3 / Xcode 7.3|2/2016|1.6?||
|
||||
|
||||
### Client library projects
|
||||
- **Selenium compatibility client updates**: we'd like to rearchitect our flagship Appium clients to extend rather than wrap Selenium clients, reducing the overall surface area of the Appium clients and making them work more closely with existing Selenium client functionality.
|
||||
## Upcoming Projects (in rough order of priority)
|
||||
|
||||
### Appium Inspector projects
|
||||
- **Full support for web inspection**: currently the Appium Inspector has poor to no support for inspecing web pages (either mobile browsers or web content embedded in webviews). It's a common requirement to inspect web elements as part of writing Appium tests, and at the present time users are required to leave the Inspector and open up a browser's devtools.
|
||||
- **Record/Playback**: we have a basic record-to-code feature already. It would be nice to be able to save recorded steps and play them back with a little player/editor.
|
||||
- **Support for more platforms**: currently there is a fair bit of specialized handling for iOS and Android in the Appium inspector. Other platforms either work poorly or not at all with the Inspector. It would be great to establish a way for drivers to report all the information about how they work to the Inspector, so it can support any platform without needing special-cased code for it.
|
||||
- **Locator analysis and comparison**: it would be nice for users to get more information about the relative suitability of using different locators to find elements, as poor locator performance is a leading cause of Appium test instability.
|
||||
- **Dark theme**: for true hackers!
|
||||
- **Export/import of saved gestures**: it's currently not possible to port your saved gestures to other instances of the Inspector (i.e., to share with team members).
|
||||
- **Bulk export/import saved sessions**: would be nice to take your sessions and capabilities with you or to share with colleagues.
|
||||
| Project | Description |
|
||||
|---------|-------------|
|
||||
|Apple Watch support|Appium should support Apple Watch apps via the Watch simulator|
|
||||
|Onboarding Overhaul|The current Appium docs leave a lot to be desired. The format is confusing (it would be better for API docs), the content is outdated, and many things are still undocumented. This project would go back to the drawing board in all of these areas and put together something genuinely helpful for the community, which hopefully reduces the kind of support issues we're currently flooded by.|
|
||||
|New Appium GUIs|The current Appium GUIs (Appium.app and Appium.exe) have a number of issues. They aren't maintained by the core Appium team. They're written in Objective-C and C# respectively: two languages, and specifically, two languages other than Appium's core language. Because of this they lag behind the Appium server and are often broken. However, users love them primarily because of the Inspector feature (the thing that lets them graphically navigate their app), so we have to field a ton of complaints about these projects. There's an opportunity to start over. With [Electron](http://electron.atom.io/), we'd be able to take the new version of Appium we're working on and embed it directly inside a Node-based GUI app written using the languages and technologies the core team is experienced with. We'd have one codebase and could distribute the app on Mac, Windows, and Linux. The GUIs would become an official part of Appium's release cycle so they wouldn't be broken.|
|
||||
|Unity3d backend POC|This is a research project to determine whether we can add some kind of support for 3d game automation, probably based on the Unity3d game development platform.|
|
||||
|Dynamic Test App|Our current test applications (the ones used to test Appium's iOS and Android support) are not ideal. We use too many of them and the ones we use have a random hodgepodge of app SDK features, sometimes not enough to sufficiently test automation support. Using [Titanium](https://github.com/appcelerator/titanium_mobile), we can develop an app that allows us to inject whatever native code we need, as we need it. The app thus changes itself test-by-test to have whatever UI features we need for that particular test. It gives us much more fine-grained control over what we're testing. The app code would also be cross-platform and written in JS, which would make it easier for the core team to write and maintain.|
|
||||
|
||||
## Projects Under Consideration (unprioritized)
|
||||
|
||||
| Project | Description |
|
||||
|---------|-------------|
|
||||
|Windows Phone Support|There has been some work done on automating Windows Phone apps. We could take this all the way to integration with Appium in the form of a WindowsDriver.|
|
||||
|
||||
## Completed Roadmap Projects
|
||||
|
||||
| Project | Description | Completed | Appium Release | Notes |
|
||||
|---------|-------------|-----------|----------------|-------|
|
||||
|iOS 9.2 support|Appium should support iOS 9.2 / Xcode 7.2|11/2015|1.4.14||
|
||||
|iOS 9.1 support|Appium should support iOS 9.1 / Xcode 7.1|10/2015|1.4.12||
|
||||
|iOS 9.0 support|Appium should support iOS 9.0 / Xcode 7.0|10/2015|1.4.11||
|
||||
|iOS 8.4 support|Appium should support iOS 8.4 / Xcode 6.2|5/2015|1.4.0||
|
||||
|Appium CI|Appium has unique needs for Continuous Integration because of the highly specialized environments required (iOS simulators, Xcode, Android emulators, the Android SDK, etc...). We therefore need to create a custom CI solution (perhaps sitting underneath Cloudbees or some other OSS-friendly CI server) that can be used for all Appium projects which need integration tests.|5/2015|_N/A_|Usage instructions at [appium/appium-ci](https://github.com/appium/appium-ci)|
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Sponsors & Backers
|
||||
|
||||
Please check [Sponsors & Backers](https://appium.io/docs/en/latest/sponsors/)
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/* eslint no-console:0 */
|
||||
|
||||
/*
|
||||
* Small tool, launching and monitoring ios-web-kit-proxy, and relauching
|
||||
* on predefined errors.
|
||||
*
|
||||
* Usage:
|
||||
* ./bin/ios-webkit-debug-proxy-launcher.js [args]
|
||||
* args: ios-webkit-debug-proxy args (they will be passed over)
|
||||
*
|
||||
* Example:
|
||||
* ./bin/ios-webkit-debug-proxy-launcher.js -c <UDID>:27753 -d
|
||||
*
|
||||
* Note:
|
||||
* For iOS8.1 try this first:
|
||||
* brew install --HEAD ideviceinstaller
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
var spawn = require('child_process').spawn,
|
||||
_ = require('lodash');
|
||||
|
||||
var args = process.argv.slice(2);
|
||||
|
||||
var RESTART_ON_MESSAGES = [
|
||||
'Invalid message _rpc_applicationUpdated',
|
||||
'Invalid message _rpc_applicationSentListing'];
|
||||
|
||||
var PROXY_CMD = 'ios_webkit_debug_proxy';
|
||||
var proxy;
|
||||
|
||||
var handleKillProcess = function (exitCode) {
|
||||
console.log('\nKilling proxy process!');
|
||||
proxy.kill('SIGTERM');
|
||||
process.exit((exitCode || 0));
|
||||
};
|
||||
|
||||
var startProxy = function () {
|
||||
console.log('RUNNING:', PROXY_CMD, args.join(' '));
|
||||
|
||||
proxy = spawn(PROXY_CMD, args);
|
||||
|
||||
proxy.stdout.on('data', function (data) {
|
||||
console.log('stdout: ' + data);
|
||||
});
|
||||
|
||||
proxy.stderr.on('data', function (data) {
|
||||
console.log('stderr: ' + data);
|
||||
var restartMessage = _(RESTART_ON_MESSAGES).find(function (message) {
|
||||
return ('' + data).indexOf(message) >= 0;
|
||||
});
|
||||
if (restartMessage) {
|
||||
console.log('Detected error message:', restartMessage);
|
||||
console.log('Killing proxy!');
|
||||
proxy.kill('SIGTERM');
|
||||
process.nextTick(startProxy);
|
||||
}
|
||||
});
|
||||
|
||||
proxy.on('close', function (code) {
|
||||
console.log('child process exited with code ' + code);
|
||||
});
|
||||
};
|
||||
|
||||
process.on('SIGINT', handleKillProcess);
|
||||
process.on('SIGTERM', handleKillProcess);
|
||||
|
||||
startProxy();
|
||||
+9
-4
@@ -1,6 +1,11 @@
|
||||
# Docs moved
|
||||
# docs
|
||||
|
||||
The old Appium 1.x docs used to be in this directory. Now, they are available only on the [1.x
|
||||
branch](https://github.com/appium/appium/tree/1.x/docs).
|
||||
##doc site
|
||||
|
||||
Appium 2.x docs are located in [packages/appium/docs](../packages/appium/docs) in this repo.
|
||||
Formatted doc is [here](http://appium.io/documentation.html?lang=en).
|
||||
|
||||
##doc translation
|
||||
|
||||
At the moment we are focusing on improving the english documentation. When it
|
||||
is done we are planning to setup proper i18n l10n processes so that it is
|
||||
easier for people to help in translating the documentation.
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
## Appium
|
||||
|
||||
[](https://npmjs.org/package/appium)
|
||||
[](https://david-dm.org/appium/appium)
|
||||
[](https://david-dm.org/appium/appium#info=devDependencies)
|
||||
|
||||
[](https://team-appium.ci.cloudbees.com/job/appium-master/)
|
||||
|
||||
Appium 是一个开源的,跨平台的自动化测试工具。
|
||||
它支持模拟器(iOS,FirefoxOS,Android)和真机(iOS, Android, FirefoxOS)上的原生应用,混合应用和移动 web 应用。
|
||||
|
||||
**Note:** 我们最近发布了Appium 1.0。如果已有 Appium 测试脚本,你可以参考这个文件[迁移到 1.0](advanced-concepts/migrating-to-1-0.cn.md)!
|
||||
|
||||
### 支持平台
|
||||
|
||||
* iOS
|
||||
* Android
|
||||
* FirefoxOS
|
||||
|
||||
### 详细请参见[文档网站](http://appium.io/documentation.html?lang=zh)
|
||||
|
||||
### 为什么选择appium ?
|
||||
|
||||
1. 因为 Appium 在所有平台上都使用了标准的自动化接口,
|
||||
所以你不需要以重新编译或者修改你的 app。
|
||||
2. 你可以用你喜欢的开发工具,使用任何 [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) 兼容的语言来编写测试用例。比如
|
||||
Java, [Objective-C](https://github.com/appium/selenium-objective-c),
|
||||
JavaScript with Node.js (in both [callback](https://github.com/admc/wd) and [yield-based](https://github.com/jlipps/yiewd) flavours),
|
||||
PHP, Python, [Ruby](https://github.com/appium/ruby_lib), C#, Clojure, 或者 Perl。
|
||||
可以使用标准的Selenium WebDriver API和特定语言的客户端库。
|
||||
3. 你可以使用任何测试框架。
|
||||
|
||||
投资 [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) 意味着你可以押宝在一个已经成为标准的独立,自由和开放的协议。你不会被任何专利限制。
|
||||
|
||||
|
||||
如果没有 Appium,你就只能用 Javascript 来写 Apple 的 UIAutomation 脚本,并且只能通过Instruments 应用来运行你的测试。同样的,在 Google 的UiAutomator体系下,你只能用 Java 写你的测试案例。Appium 最终开启了跨平台原生移动自动化的可能。
|
||||
|
||||
### 我还是不太明白……
|
||||
|
||||
如果你第一次接触 Appium 或者想要一个完整的描述,请通读我们的 [Introduction to Appium Concepts](about-appium/intro.cn.md)。
|
||||
|
||||
|
||||
### 依赖
|
||||
|
||||
为了运行测试,针对不同的移动平台,你需要配置下环境,下面列出相关的依赖平台的需求。
|
||||
|
||||
如果你想通过 `npm install` 安装的 appium 来运行 Appium 或者研究 Appium 或者为 Appium 贡献力量。你需要安装 [node.js 和 npm](http://nodejs.org) 0.10 或者更高版本 (使用 [n](https://github.com/visionmedia/n)或者`brew install node`来安装 Nodejs,确保安装过程中,你没有使用任何 sudo,否则你会遇到很多问题)。我们推荐最新的稳定版本。
|
||||
|
||||
你可以使用 `appium-doctor` 来验证 Appium 的所有依赖。运行 `appium-doctor`,然后提供 `--ios` 或者 `--android` 参数来验证两个平台的依赖是否配置正确。如果从源代码运行,你可以使用 `bin/appium-doctor.js` 或者 `node bin/appium-doctor.js`
|
||||
|
||||
#### iOS 需求
|
||||
|
||||
* Mac OS X 10.7 或者更高,推荐 10.9.2
|
||||
* XCode >= 4.6.3,推荐 5.1.1
|
||||
* Apple Developer Tools (iPhone simulator SDK, command line tools)
|
||||
* [确保你已经读了我们写的如何配置 iOS 测试环境的文档](appium-setup/running-on-osx.cn.md)
|
||||
|
||||
|
||||
#### Android 需求
|
||||
|
||||
* [Android SDK](http://developer.android.com) API >= 17 (额外的特性需要 18/19)
|
||||
* Appium 支持OS X,Linux,Windows 上的 Android,确保你是按照如下文档的指示来配置不同的测试环境的。
|
||||
* [linux](appium-setup/running-on-linux.cn.md)
|
||||
* [osx](appium-setup/running-on-osx.cn.md)
|
||||
* [windows](appium-setup/running-on-windows.cn.md)
|
||||
|
||||
#### FirefoxOS 需求
|
||||
|
||||
* [Firefox OS Simulator](https://developer.mozilla.org/en/docs/Tools/Firefox_OS_Simulator)
|
||||
|
||||
### 快速开始
|
||||
启动 Appium server,并运行用你喜欢的 [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) 兼容的语言编写的测试用例。
|
||||
你可以用 node.js 或者下面的应用程序来运行 Appium
|
||||
|
||||
#### 使用 Node.js
|
||||
|
||||
```center
|
||||
$ npm install -g appium
|
||||
$ appium &
|
||||
```
|
||||
|
||||
#### 使用 app
|
||||
|
||||
* [下载 Appium app](https://github.com/appium/appium/releases)
|
||||
* 运行它!
|
||||
|
||||
### 为Appium编写测试
|
||||
|
||||
如何开始写测试用例,运行测试用例,可以看[the running tests](writing-running-appium/running-tests.cn.md),这个文档描述了iOS,Android 和老版本的 Android 机器的情况。如果你想在实体机上运行测试的话,
|
||||
你可能会对[真机指南](appium-setup/real-devices.cn.md)感兴趣。
|
||||
|
||||
我们支持 [Selenium WebDriver JSON Wire Protocol](https://github.com/appium/appium/wiki/JSON-Wire-Protocol:-Supported-Methods) 的一个子集,而且在此之上扩展了移动平台相关的特性。所以你可以
|
||||
指定特定移动平台[desired capabilities](writing-running-appium/caps.cn.md) 来运行你的测试。
|
||||
|
||||
你可以通过 [WebDriver](https://w3c.github.io/webdriver/webdriver-spec.html) 元素定位策略的子集来定位元素。更多信息请参考 [finding elements](writing-running-appium/finding-elements.cn.md)
|
||||
为了支持移动手势[automating mobile gestures](writing-running-appium/touch-actions.cn.md),比如
|
||||
tap,flick 和 swipe,我们扩展了JSON Wire Protocolor。
|
||||
|
||||
你也可以对混合应用中的webview进行自动化 [hybrid app guide](advanced-concepts/hybrid.cn.md)
|
||||
|
||||
该代码库有 [很多不同语言的测试例子](https://github.com/appium/sample-code)!
|
||||
|
||||
### 工作原理
|
||||
|
||||
Appium 可以驱动多种原生自动化框架,同时也提供基于 Selenium 的 [WebDriver JSON wire protocol](https://w3c.github.io/webdriver/webdriver-spec.html) api。
|
||||
|
||||
基于[Dan Cuellar's](http://github.com/penguinho) 在 iOS 自动化上的成果,Appium 通过驱动 Apple 的 UIAutomation 库来提供 iOS 支持。
|
||||
|
||||
而在新版本的 Android 上,我们使用 Uiautomator 框架,老版本的 Android,则使用了
|
||||
[Selendroid](http://github.com/DominikDary/selendroid)
|
||||
|
||||
FirefoxOS 的支持依赖一个基于 Gecko 平台并且兼容 WebDriver 的自动化驱动[Marionette](https://developer.mozilla.org/en-US/docs/Marionette)。
|
||||
|
||||
|
||||
### 如何贡献代码
|
||||
可以看下我们的文档 [contribution documentation](../../CONTRIBUTING.md)
|
||||
以了解如何从源代码中进行编译,测试和运行
|
||||
|
||||
|
||||
## 其他项目的授权和灵感来源
|
||||
|
||||
[Credits](contributing-to-appium/credits.cn.md)
|
||||
|
||||
### 邮件列表
|
||||
|
||||
声明和公告经常放到讨论组 [Discussion Group](https://groups.google.com/d/forum/appium-discuss), 需要注册
|
||||
|
||||
### 问题定位
|
||||
|
||||
我们增加了一个 [问题定位指南](appium-setup/troubleshooting.cn.md)。
|
||||
如果你遇到一些问题,请看下这个问的那个。它包含了一些常见的错误说明,以及在无法解决的情况如何和社区联系。
|
||||
|
||||
|
||||
### 使用Robots扩展
|
||||
可以使用 appium 的一些 robots 扩展。或者其他的 robots。想了解更多可以看看 [Appium Robots](https://github.com/appium/robots)
|
||||
|
||||
|
||||
### 翻译工作
|
||||
文档翻译工作由[testerhome](http://testerhome.com)在推动, 我们会不断补充更多的文档和测试用例.
|
||||
欢迎对 Appium 感兴趣的同学加入我们, 为开源社区贡献中国人的力量.
|
||||
@@ -0,0 +1,19 @@
|
||||
## 客户端类库列表及Appium服务端支持
|
||||
|
||||
这些类库封装了标准Selenium客户端类库,为用户提供所有常见的[JSON](https://w3c.github.io/webdriver/webdriver-spec.html) 格式selenium命令以及额外的移动设备控制相关的命令,如多点**触控手势**和**屏幕朝向**。
|
||||
|
||||
Appium客户端类库实现了[Mobile JSON Wire Protocol](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md)(一个标准协议的官方扩展草稿)和[W3C Webdriver spec](https://dvcs.w3.org/hg/webdriver/raw-file/default/webdriver-spec.html)(一个传输不可预知的自动化协议,该协议定义了MultiAction 接口)的元素。
|
||||
|
||||
Appium 服务端定义了官方协议的扩展,为Appium 用户提供了方便的接口来执行各种设备动作,例如在测试过程中安装/卸载app。这就是为什么我们需要Appium 特定的客户端,而不是通用的Selenium 客户端。当然,Appium 客户端类库只是增加了一些功能,而实际上这些功能就是简单的扩展了Selenium 客户端,所以他们仍然可以用来运行通用的selenium会话。
|
||||
|
||||
|
||||
语言/框架 | Github版本库以及安装指南 |
|
||||
----- | ----- |
|
||||
Ruby | [https://github.com/appium/ruby_lib](https://github.com/appium/ruby_lib)
|
||||
Python | [https://github.com/appium/python-client](https://github.com/appium/python-client)
|
||||
Java | [https://github.com/appium/java-client](https://github.com/appium/java-client)
|
||||
JavaScript (Node.js) | [https://github.com/admc/wd](https://github.com/admc/wd)
|
||||
Objective C | [https://github.com/appium/selenium-objective-c](https://github.com/appium/selenium-objective-c)
|
||||
PHP | [https://github.com/appium/php-client](https://github.com/appium/php-client)
|
||||
C# (.NET) | [https://github.com/appium/appium-dotnet-driver](https://github.com/appium/appium-dotnet-driver)
|
||||
RobotFramework | [https://github.com/jollychang/robotframework-appiumlibrary](https://github.com/jollychang/robotframework-appiumlibrary)
|
||||
@@ -0,0 +1,64 @@
|
||||
# Appium 介绍
|
||||
|
||||
Appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平台上的原生应用,web 应用和混合应用。
|
||||
|
||||
所谓的“移动原生应用”是指那些用 iOS 或者 Android SDK 写的应用。所谓的“移动 web 应用”是指使用移动浏览器访问的应用(Appium 支持 iOS 上的 Safari 和 Android 上的 Chrome)。所谓的“混合应用”是指原生代码封装网页视图——原生代码和 web 内容交互。比如,像 [Phonegap](http://phonegap.com/),可以帮助开发者使用网页技术开发应用,然后用原生代码封装,这些就是混合应用。
|
||||
|
||||
重要的是,Appium 是一个跨平台的工具:它允许测试人员在不同的平台(iOS,Android)使用同一套API来写自动化测试脚本,这样大大增加了 iOS 和 Android 测试套件间代码的复用性。
|
||||
|
||||
想知道 Appium 如何支持平台,版本和自动化形态的详细信息,请参见[platform support doc](/docs/cn/appium-setup/platform-support.cn.md)。
|
||||
|
||||
## Appium 的理念
|
||||
|
||||
为了满足移动自动化需求,Appium 遵循着一种哲学,重点体现于以下4个需求:
|
||||
|
||||
1. 你无需为了自动化,而重新编译或者修改你的应用。
|
||||
2. 你不必局限于某种语言或者框架来写和运行测试脚本。
|
||||
3. 一个移动自动化的框架不应该在接口上重复造轮子。(移动自动化的接口应该统一)
|
||||
4. 无论是精神上,还是名义上,都必须开源。
|
||||
|
||||
## Appium 设计
|
||||
|
||||
那么 Appium 架构是如何实现这个哲学呢?为了满足第一条,Appium 真正的工作引擎其实是第三方自动化框架。这样,我们就不需在你的应用里植入 Appium 相关或者第三方的代码。这意味着你测试使用的应用与最终发布的应用并无二致。我们使用以下的第三方框架:
|
||||
|
||||
* iOS: 苹果的 [UIAutomation](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef)
|
||||
* Android 4.2+: Google's [UiAutomator](http://developer.android.com/tools/help/uiautomator/index.html)
|
||||
* Android 2.3+: Google's [Instrumentation](http://developer.android.com/reference/android/app/Instrumentation.html). (Instrumentation由单独的项目[Selendroid](http://selendroid.io)提供支持 )
|
||||
|
||||
为了满足第二点,我们把这些第三方框架封装成一套 API,[WebDriver](http://docs.seleniumhq.org/projects/webdriver/) API.WebDriver(也就是 "Selenium WebDriver") 指定了客户端到服务端的协议。
|
||||
(参见 [JSON Wire Protocol](https://w3c.github.io/webdriver/webdriver-spec.html))。使用这种客户端-服务端的架构,我们可以使用任何语言来编写客户端,向服务端发送恰当的 HTTP 请求。
|
||||
目前已经实现了大多数流行语言版本的客户端,这意味着你可以使用任何测试套件或者测试框架。客户端库就是简单的HTTP 客户,可以以任何你喜欢的方式潜入你的代码。换句话说,Appium 和 WebDriver 客户端不是技术意义上的“测试框架”,而是“自动化库”。你可以在你的测试环境中随意使用这些自动化库!
|
||||
|
||||
事实上 WebDriver 已经成为 web 浏览器自动化的标准,也成了 W3C 的标准 —— [W3C Working Draft](https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html)。我们又何必为移动做一个完全不同的呢?所以我们扩充了[WebDriver 的协议](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md),在原有的基础上添加移动自动化相关的 API 方法,这也满足了第三条理念。
|
||||
|
||||
第四条就不用说了,[Appium 是开源的](https://github.com/appium/appium)。
|
||||
|
||||
## Appium 概念
|
||||
|
||||
**C/S 架构**<br/>
|
||||
Appium 的核心是一个 web 服务器,它提供了一套 REST 的接口。它收到客户端的连接,监听到命令,接着在移动设备上执行这些命令,然后将执行结果放在 HTTP响应中返还给客户端。事实上,这种客户端/服务端的架构给予了许多的可能性:比如我们可以使用任何实现了该客户端的语言来写我们的测试代码。比如我们可以把服务端放在不同
|
||||
的机器上。比如我们可以只写测试代码,然后使用像 [Sauce Labs](https://saucelabs.com/mobile) 这样的云服务来解释命令。
|
||||
|
||||
**Session**<br/>
|
||||
自动化始终围绕一个session进行,客户端初始化一个seesion(会话)来与服务端交互,不同的语言有不同的实现方式,但是他们最终都是发送为一个POST请求给服务端,请求中包含一个JSON对象,被称作“desired capabilities”。此时,服务端就会开启一个自动化的 session,然后返回一个 session ID,session ID将会被用户发送后续的命令。
|
||||
|
||||
**Desired Capabilities**<br/>
|
||||
Desired capabilities 是一些键值对的集合 (比如,一个 map 或者 hash),客户端将这些键值对发给服务端,告诉服务端我们想要怎么测试。比如,我们可以把`platformName` capability 设置为 `iOS`,告诉 Appium 服务端,我们想要一个iOS 的 session,而不是一个 Android 的。我们也可以设置 `safariAllowPopups` capability 为 `true`,确保在 Safari 自动化 session 中,我们可以使用 javascript 来打开新窗口。参见 [capabilities 文档](/docs/cn/writing-running-appium/caps.cn.md),查看完整的 capabilities 列表。
|
||||
|
||||
**Appium Server**<br/>
|
||||
Appium server 是用 Node.js 写的。我们可以用源码编译或者从 NPM 直接安装。
|
||||
|
||||
**Appium 服务端**<br/>
|
||||
|
||||
Appium 服务端有很多语言库 Java, Ruby, Python, PHP, JavaScript 和 C#,这些库都实现了
|
||||
Appium 对 WebDriver 协议的扩展。当使用 Appium 的时候,你只需使用这些库代替常规的 WebDriver 库就可以了。
|
||||
你可以从[这里](appium-clients.cn.md)看到所有的库的列表。
|
||||
|
||||
**[Appium.app](https://github.com/appium/appium-dot-app), [Appium.exe](https://github.com/appium/appium-dot-exe)**<br/>
|
||||
|
||||
我们提供了 GUI 封装的 Appium 服务端下载,它封装了运行 Appium服务端的所有依赖,而不需要担心怎样安装Node.js。其中还包括一个Inspector工具,可以帮助你检查应用的界面层级,这样写测试用例时更方便。
|
||||
|
||||
## Getting Started
|
||||
|
||||
恭喜!你现在有足够的知识来使用 Appium 了。 来我们回到 [getting started doc](/docs/cn/README.md) 继续了解更加
|
||||
细节的需求和指南。
|
||||
@@ -0,0 +1,47 @@
|
||||
# Selenium Grid
|
||||
|
||||
使用 <b>"--nodeconfig"</b> 服务器参数,你可以在本地 selenium grid 里注册你的 appium 服务器。
|
||||
|
||||
```bash
|
||||
> node . -V --nodeconfig /path/to/nodeconfig.json
|
||||
```
|
||||
|
||||
在 node 的配置文件里,你需要定义 <b>"browserName"</b>,<b>"version"</b> 和 <b>"platform"</b>。
|
||||
基于这些参数,selenium grid 会将你的测试定向到正确的设备上去。你还需要配置你的 <b>host</b> 详细信息和
|
||||
<b>selenium grid</b> 的详细信息。你可以在 <a href="http://code.google.com/p/selenium/source/browse/java/server/src/org/openqa/grid/common/defaults/GridParameters.properties">这里</a> 找到详细的参数列表和描述信息。
|
||||
|
||||
一旦你启动了 appium 服务器并且在 grid 里注册了信息,你会在 grid 控制台发现你的设备:
|
||||
|
||||
"http://<b>\<grid-ip-adress\></b>:<b>\<grid-port\></b>/grid/console"
|
||||
|
||||
## Grid 配置文件例子
|
||||
|
||||
```xml
|
||||
{
|
||||
"capabilities":
|
||||
[
|
||||
{
|
||||
"browserName": "<e.g._iPhone5_or_iPad4>",
|
||||
"version":"<version_of_iOS_e.g._6.1>",
|
||||
"maxInstances": 1,
|
||||
"platform":"<platform_e.g._MAC_or_ANDROID>"
|
||||
}
|
||||
],
|
||||
"configuration":
|
||||
{
|
||||
"cleanUpCycle":2000,
|
||||
"timeout":30000,
|
||||
"proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
|
||||
"url":"http://<host_name_appium_server_or_ip-address_appium_server>:<appium_port>/wd/hub",
|
||||
"maxSession": 1,
|
||||
"register": true,
|
||||
"registerCycle": 5000,
|
||||
"hubPort": <grid_port>,
|
||||
"hubHost": "<Grid_host_name_or_grid_ip-address>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
可以在 <a href="http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/Platform.html">这里</a>查看有效的 platform 参数。
|
||||
如果没有给出url、host和 port,配置会自动指向本地:whatever-port-Appium-started-on。
|
||||
如果你的Appium服务和Selenium Grid服务没有运行在同一台机器上,为确保Selenium Grid连接正常,请在你的host & url docs上使用外部其它名称或IP地址,而非localhost 和 127.0.0.1
|
||||
@@ -0,0 +1,202 @@
|
||||
# 自动化混合应用
|
||||
|
||||
Appium 其中一个理念就是你不能为了测试应用而修改应用。为了符合这个方法学,我们可以使用 Selenium 测试传统 web 应用的方法来测试混合 web 应用 (比如,iOS 应用里的元素 "UIWebView" ),这是有可能的。这里会有一些技术性的复杂,Appium 需要知道你是想测试原生部分呢还是web部分。幸运的是,我们还能遵守 WebDriver 的协议。
|
||||
|
||||
* [混合 iOS 应用](hybrid.cn.md)
|
||||
* [混合 Android 应用](hybrid.cn.md)
|
||||
|
||||
## 自动化混合 iOS 应用
|
||||
|
||||
在你的 Appium 测试里,你需要以下几步来和 web 页面交涉:
|
||||
|
||||
1. 前往到应用里 web 视图激活的部分。
|
||||
1. 调用 [GET session/:sessionId/window_handles](http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/window_handles)
|
||||
1. 这会返回一个我们能访问的 web 视图的 id 的列表。
|
||||
1. 使用你想访问的这个 web 视图的 id 作为参数,调用 [POST session/:sessionId/window](http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/window)
|
||||
1. (这会将你的 Appium session 放入一个模式, 在这个模式下,所有的命令都会被解释成自动化web视图而不是原生的部分。比如,当你运行 getElementByTagName,它会在 web 视图的 DOM 上操作,而不是返回 UIAElements。当然,一个 Webdriver 的方法只能在一个上下文中有意义,所以如果在错误的上下文,你会收到错误信息。)
|
||||
1. 如果你想停止 web 视图的自动化,回到原生部分,你可以简单地使用 `execute_script` 调用 `"mobile: leaveWebView"` 方法来离开 web 层。
|
||||
|
||||
## 在 iOS 真机上运行
|
||||
|
||||
appium 使用一个远程调试器建立连接来实现和 web 视图的交互。当在模拟器上执行下面例子的时候,我们可以直接建立连接,因为模拟器和 appium 服务器在同一台机器上。
|
||||
|
||||
当在真机上运行用例时,appium 无法直接访问 web 视图,所以我们需要通过 USB 线缆来建立连接。我们使用 [ios-webkit-debugger-proxy](https://github.com/google/ios-webkit-debug-proxy)建立连接。
|
||||
|
||||
使用 brew 安装最新的 ios-webkit-debug-proxy。在终端运行一下命令:
|
||||
|
||||
``` bash
|
||||
# 如果你没有安装 brew 的话,先安装 brew。
|
||||
> ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go/install)"
|
||||
> brew update
|
||||
> brew install ios-webkit-debug-proxy
|
||||
```
|
||||
|
||||
你也可以通过 git 克隆项目来自己安装最新版本:
|
||||
|
||||
``` bash
|
||||
# Please be aware that this will install the proxy with the latest code (and not a tagged version).
|
||||
> git clone https://github.com/google/ios-webkit-debug-proxy.git
|
||||
> cd ios-webkit-debug-proxy
|
||||
> ./autogen.sh
|
||||
> ./configure
|
||||
> make
|
||||
> sudo make install
|
||||
```
|
||||
|
||||
一旦安装好了, 你就可以启动代理:
|
||||
|
||||
``` bash
|
||||
# 将udid替换成你的设备的udid。确保端口 27753 没有被占用
|
||||
# remote-debugger 将会使用这个端口。
|
||||
> ios_webkit_debug_proxy -c 0e4b2f612b65e98c1d07d22ee08678130d345429:27753 -d
|
||||
```
|
||||
|
||||
<b>注意:</b> 这个 ios-webkit-debug-proxy 需要 <b>"web inspector"</b> 打开着以便建立连接。在 <b> settings > safari > advanced </b> 里打开它。请注意 web inspector <b>在 iOS6 时候加入的</b> 以前的版本没有。
|
||||
|
||||
## Wd.js Code example
|
||||
|
||||
```js
|
||||
// 假设我们已经有一个初始化好了的 `driver` 对象。
|
||||
driver.elementByName('Web, Use of UIWebView', function(err, el) { // 找到按钮,打开 web 视图
|
||||
el.click(function(err) { // 引导到 UIWebView
|
||||
driver.windowHandles(function(err, handles) { // 得到能访问的视图列表。
|
||||
driver.window(handles[0], function(err) { // 因为只有一个,所以选择第一个。
|
||||
driver.elementsByCss('.some-class', function(err, els) { // 通过 css 拿到元素。
|
||||
els.length.should.be.above(0); // 肯定有元素。
|
||||
els[0].text(function(elText) { // 得到第一个元素的文本。
|
||||
elText.should.eql("My very own text"); // 比较匹配文本。
|
||||
driver.execute("mobile: leaveWebView", function(err) { // 离开web视图上下文。
|
||||
// 如果你想的话,做一些原生应用的操作。
|
||||
driver.quit(); // 退出。
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
* 想看到具体的上下文,请看[该node 的例子](/sample-code/examples/node/hybrid.js)
|
||||
* *我们正在完善 web 视图下面的方法。[加入我们!](http://appium.io/get-involved.html)
|
||||
|
||||
## Wd.java 代码例子
|
||||
|
||||
```java
|
||||
//配置 webdriver 并启动 webview 应用。
|
||||
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
|
||||
desiredCapabilities.setCapability("device", "iPhone Simulator");
|
||||
desiredCapabilities.setCapability("app", "http://appium.s3.amazonaws.com/WebViewApp6.0.app.zip");
|
||||
URL url = new URL("http://127.0.0.1:4723/wd/hub");
|
||||
RemoteWebDriver remoteWebDriver = new RemoteWebDriver(url, desiredCapabilities);
|
||||
|
||||
// 切换到最新的web视图
|
||||
for(String winHandle : remoteWebDriver.getWindowHandles()){
|
||||
remoteWebDriver.switchTo().window(winHandle);
|
||||
}
|
||||
|
||||
//在 guinea-pig 页面用 id 和 元素交互。
|
||||
WebElement div = remoteWebDriver.findElement(By.id("i_am_an_id"));
|
||||
Assert.assertEquals("I am a div", div.getText()); //验证得到的文本是否正确。
|
||||
remoteWebDriver.findElement(By.id("comments")).sendKeys("My comment"); //填写评论。
|
||||
|
||||
//离开 webview,回到原生应用。
|
||||
remoteWebDriver.executeScript("mobile: leaveWebView");
|
||||
|
||||
//关闭应用。
|
||||
remoteWebDriver.quit();
|
||||
```
|
||||
|
||||
## Wd.rb cucumber 的例子
|
||||
|
||||
```ruby
|
||||
TEST_NAME = "Example Ruby Test"
|
||||
SERVER_URL = "http://127.0.0.1:4723/wd/hub"
|
||||
APP_PATH = "https://dl.dropboxusercontent.com/s/123456789101112/ts_ios.zip"
|
||||
capabilities =
|
||||
{
|
||||
'browserName' => 'iOS 6.0',
|
||||
'platform' => 'Mac 10.8',
|
||||
'device' => 'iPhone Simulator',
|
||||
'app' => APP_PATH,
|
||||
'name' => TEST_NAME
|
||||
}
|
||||
@driver = Selenium::WebDriver.for(:remote, :desired_capabilities => capabilities, :url => SERVER_URL)
|
||||
|
||||
## 这里切换到最近一个窗口是因为在我们的例子里这个窗口一直是 webview。其他的用例里,你需要自己指定。
|
||||
## 运行 @driver.window_handles,查看 appium 的日志,找出到底哪个窗口是你要的,然后找出相关的数字。
|
||||
## 然后用 @driver.switch_to_window(number),切换过去。
|
||||
|
||||
Given(/^I switch to webview$/) do
|
||||
webview = @driver.window_handles.last
|
||||
@driver.switch_to.window(webview)
|
||||
end
|
||||
|
||||
Given(/^I switch out of webview$/) do
|
||||
@driver.execute_script("mobile: leaveWebView")
|
||||
end
|
||||
|
||||
# 你可以使用 CSS 选择器在你的 webview 里来选择元素
|
||||
|
||||
And(/^I click a webview button $/) do
|
||||
@driver.find_element(:css, ".green_button").click
|
||||
end
|
||||
```
|
||||
### 用 ruby 调试 web 视图:
|
||||
我在我的帮助类里创建了一个快速方法来定位web元素,无论它在哪一个窗口视图。
|
||||
(这非常有帮助,特别是你的 webview 的 id 变化或者你用同一份代码来测试 Android 和 iOS。)
|
||||
https://gist.github.com/feelobot/7309729
|
||||
|
||||
## 自动化混合 Android 应用
|
||||
|
||||
Appium 通过 Chromedriver 内建混合应用支持。Appium 也可以使用 Selendroid 做为 4.4 之前的设备对 webview 支持的背部引擎。(你需要在 desired capability 里指定 `"device": "selendroid"`)。然后:
|
||||
|
||||
1. 前往你应用里 web 视图激活的部分。
|
||||
1. 用 "WEBVIEW" 做窗口句柄调用 [POST session/:sessionId/window](http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/window) , 比如 `driver.window("WEBVIEW")`。
|
||||
1. (这会将你的 Appium session 放入一个模式, 在这个模式下,所有的命令都会被解释成自动化web视图而不是原生的部分。比如,当你运行 getElementByTagName,它会在 web 视图的 DOM 上操作,而不是返回 UIAElements。当然,一个 Webdriver 的方法只能在一个上下文中有意义,所以如果在错误的上下文,你会收到错误信息。)
|
||||
1. 如果要停止web上下文里的自动化,回到原生部分的自动化,简单地使用 "NATIVE_APP" 调用 `window` 方法。比如 `driver.window("NATIVE_APP")`。
|
||||
|
||||
注意:我们可以像上面说的,使用同样的策略。然而,Selendroid 使用 `WEBVIEW`/`NATIVE_APP` 窗口设置策略。 Appium 常规的混合支持也使用这种策略。
|
||||
|
||||
## Wd.js 代码例子
|
||||
|
||||
```js
|
||||
// 假设我们已经初始化了一个 `driver` 实例。
|
||||
driver.window("WEBVIEW", function(err) { // 选择唯一的 WebView
|
||||
driver.elementsByCss('.some-class', function(err, els) { // 通过 CSS 取得元素
|
||||
els.length.should.be.above(0); // 验证元素存在
|
||||
els[0].text(function(elText) { // 得到第一个元素的文本
|
||||
elText.should.eql("My very own text"); // 验证文本内容
|
||||
driver.window("NATIVE_APP", function(err) { // 离开 webview 上下文
|
||||
// 可以做些原生应用的测试
|
||||
driver.quit(); // 关闭 webdriver
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Wd.java 代码例子
|
||||
|
||||
```java
|
||||
//配置 webdriver 并启动 webview 应用。
|
||||
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
|
||||
desiredCapabilities.setCapability("device", "Selendroid");
|
||||
desiredCapabilities.setCapability("app", "/path/to/some.apk");
|
||||
URL url = new URL("http://127.0.0.1:4723/wd/hub");
|
||||
RemoteWebDriver remoteWebDriver = new RemoteWebDriver(url, desiredCapabilities);
|
||||
|
||||
// 切换到最新的web视图
|
||||
remoteWebDriver.switchTo().window("WEBVIEW");
|
||||
|
||||
//在 guinea-pig 页面用 id 和 元素交互。
|
||||
WebElement div = remoteWebDriver.findElement(By.id("i_am_an_id"));
|
||||
Assert.assertEquals("I am a div", div.getText()); //验证得到的文本是否正确。
|
||||
remoteWebDriver.findElement(By.id("comments")).sendKeys("My comment"); //填写评论。
|
||||
|
||||
//离开 webview,回到原生应用。
|
||||
remoteWebDriver.switchTo().window("NATIVE_APP");
|
||||
|
||||
//关闭应用。
|
||||
remoteWebDriver.quit();
|
||||
```
|
||||
@@ -0,0 +1,109 @@
|
||||
# 把appium 0.18.x上的测试用例集迁移到appium1.x上
|
||||
|
||||
Appium 1.0 已经从先前的版本中移除了一部分过时的特性, 这个指导文档会帮助你了解使用Appium 1.0需要做的具体改变.
|
||||
|
||||
## 新的客户端库
|
||||
|
||||
你需要关注的最大的改变是利用新的appium的client libraries来替换原生的WebDriver ciients. 访问[Appium client list](appium-clients.md) 去寻找符合你自己编程语言的客户端库吧. 在每个客户端的网站上都可以找到用于集成到你代码中的依赖库相关介绍和下载
|
||||
|
||||
基本上, 你需要做如下的改变(以Python作为例子)
|
||||
|
||||
用
|
||||
```
|
||||
from appium import webdriver
|
||||
```
|
||||
|
||||
替换原来的:
|
||||
|
||||
```
|
||||
from selenium import webdriver
|
||||
```
|
||||
|
||||
## 新的适配参数
|
||||
|
||||
下面的适配参数将不再使用
|
||||
* `device`
|
||||
* `version`
|
||||
|
||||
取而代之的是利用下面的配置参数
|
||||
|
||||
* `platformName` ("iOS" 或者 "Android")
|
||||
* `platformVersion` (你希望测试的os版本)
|
||||
* `deviceName` (你想用的设备, 比如 "iPhone Simulator")
|
||||
* `automationName` ("Selendroid" 如果你想使用Selendroid的话, 否则可以省略)
|
||||
|
||||
|
||||
`app` 配置参数保持不变, 但是特指非浏览器的app, 如果你想使用类似Safari或者Chrome这样的浏览器, 你需要设置`browserName`. 这代表`app`和`browserName`是互斥的.
|
||||
|
||||
我们把appium的配置参数都规范为驼峰拼写法(camelCase), 这代表着原来的`app-package`或者`app-wait-activity`现在会变成`appPackage`和`appWaitActivity`. 当然目前android的app package和activity都已经是自动探测了, 大部分情况下你可以省略这两个配置项.
|
||||
|
||||
## 新的定位方式
|
||||
|
||||
我们已经移除了下面的定位方式
|
||||
|
||||
* `name`
|
||||
* `tag name`
|
||||
|
||||
我们增加了`accessibility_id`定位方法去做过去`name`做的事情. 具体的细节还得跟你使用的Appium客户端库有关.
|
||||
|
||||
`tag name`已经被替换为`class name`. 所以想通过UI的类型来定位某个元素, 你需要使用class name定位方式
|
||||
|
||||
关于`class name`和`xpath`的定位方式: 现在需要使用完整的全类名, 这意味着如果你有一个如下的定位用的xpath
|
||||
|
||||
```
|
||||
//table/cell/button
|
||||
```
|
||||
现在需要改成
|
||||
|
||||
```
|
||||
//UIATableView/UIATableCell/UIAButton
|
||||
```
|
||||
|
||||
如果是android的话, `button`需要改变成`android.widget.Button`
|
||||
|
||||
我们也增加了如下的定位方式
|
||||
|
||||
* `-ios uiautomation`
|
||||
* `-android uiautomator`
|
||||
|
||||
根据你使用的客户端去相应的使用新的定位方式
|
||||
|
||||
## 使用xml, 不再是json了
|
||||
|
||||
App source方法先前返回JSON, 现在修改成返回XML. 所以如果你有代码是依赖解析app source的, 那么就需要更新
|
||||
|
||||
## 通过context支持混合应用, 不再是window了
|
||||
|
||||
以前混合app的切换支持是通过"windows"
|
||||
|
||||
* `window_handles`
|
||||
* `window`
|
||||
* `switch_to.window`
|
||||
|
||||
现在Appium支持"context" 概念了, 要获得当前环境下所有的上下文(contexts), 或者特定的context, 你可以用
|
||||
|
||||
```python
|
||||
driver.contexts
|
||||
current = driver.context
|
||||
```
|
||||
|
||||
在这些context之间切换, 可以使用
|
||||
|
||||
```python
|
||||
driver.switch_to.context("WEBVIEW")
|
||||
```
|
||||
|
||||
## 没有了`execute_script("mobile: xxx")`
|
||||
|
||||
所有的`mobile:`方法都已经被移除, 并且被替换为appium client libraries的原生方法. 这意味着如果一个方法调用原来的方式是
|
||||
`driver.execute("mobile: lock", [5])`
|
||||
现在需要更新为
|
||||
`driver.lock(5)`
|
||||
在这个地方`lock`已经变成了原生的客户端方法. 当然具体的调用细节在不同的客户端库中的实现可能会有所差别.
|
||||
|
||||
特别需要注意的是, 手势(gesture)方法已经被替换为TouchAction / MultiAction API, 它允许更强大通用的组合手势的自动化. 可以参考你的客户端库的具体用法.
|
||||
|
||||
这就是全部啦, 祝迁移愉快
|
||||
|
||||
(文档由testerhome.com翻译, 欢迎更多热爱技术的同学加入到翻译中来, We Love Appium)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
## Settings
|
||||
|
||||
Settings 是 Appium 引入的一个新的概念。 它目前还没有被纳入 Mobile JSON Wire Protocol 及 Webdriver 标准之中。
|
||||
|
||||
Settings 是一种用来配置 Appium 服务器的方式。
|
||||
|
||||
Settings 有以下特点:
|
||||
- 可变的,它在同一会话中是可以被修改的。
|
||||
- 唯一的,它在被测应用会话中是唯一的。 它在每创建一个新会话时会被重置。
|
||||
- 可控的,它在自动化测试过程中控制着 Appium 服务器的运行。 它们不会被用来控制被测应用或被测终端。
|
||||
|
||||
在 Android 环境中 以 `ignoreUnimportantViews` 设置举例,该参数在 Android 环境中可以被设置成忽略所有与当前视图无关的元素,它将使测试过程更加有效率。 然而当我们希望能够访问被忽略的元素时,我们必须在将 `ignoreUnimportantViews` 设置成 *true* 后,重新修改成 *false* 。
|
||||
|
||||
另外也可以通过 Settings 配置让 Appium 忽略所有当前不可见的元素。
|
||||
|
||||
Settings 可以通过以下 API 方法进行配置:
|
||||
|
||||
**POST** /session/:sessionId/appium/settings
|
||||
|
||||
>以 JSON 格式提交 key:value 键值对形式的Settings配置。
|
||||
```
|
||||
{
|
||||
settings: {
|
||||
ignoreUnimportantViews : true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**GET** /session/:sessionId/appium/settings
|
||||
|
||||
>以 JSON 格式返回当前所有 Settings 配置。
|
||||
```
|
||||
{
|
||||
ignoreUnimportantViews : true
|
||||
}
|
||||
```
|
||||
|
||||
### 其它 Settings 配置参考
|
||||
|
||||
**"ignoreUnimportantViews"** -该参数值为 *true* 或 *false*。 如果你希望能够尽量减少测试过程的交互确认过程,或希望测试脚本能更快的执行,可以在 Android 终端环境下使用 `setCompressedLayoutHeirarchy()` 参数。它将忽略所有被标记为 IMPORTANT_FOR_ACCESSIBILITY_NO 或 IMPORTANT_FOR_ACCESSIBILITY_AUTO(以及那些被认为不是很重要的系统元素)的元素。
|
||||
@@ -0,0 +1,11 @@
|
||||
# Intel® 硬件加速器管理
|
||||
|
||||
如果你发现android模拟器太慢, 并且你的系统运行在Intel® 的cpu上. 那么你可以尝试下HAXM, HAXM能够让你充分利用硬件虚拟化技术来加速android模拟器。
|
||||
|
||||
* 要安装HAXM, 你可以打开Android SDK Manager, 你可以在Extras中发现这个安装选项;
|
||||
* 你可以在[Intel官方网站][1]找到所有相关的文档;
|
||||
* 这将需要x86的模拟镜像;
|
||||
* 利用Intel的包来安装HAXM; Android SDK Manager有时候会安装不成功,这主要取决于你安装的版本是否兼容。
|
||||
|
||||
[1]: http://software.intel.com/en-us/articles/intel-hardware-accelerated-execution-manager/ "Hax"
|
||||
[2]: http://software.intel.com/en-us/search/site/language/en?query=Intel%20Hardware%20Accelerated%20Execution%20Manager%20%28HAXM%29 "Hax all"
|
||||
@@ -0,0 +1,38 @@
|
||||
## Android Setup
|
||||
|
||||
使用前,你需要安装node.js(版本大于等于0.10)。 请参照 [instructions for your flavor of linux](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager)。
|
||||
|
||||
当node.js安装成功后,请安装 [Android SDK](http://developer.android.com/sdk/index.html)。
|
||||
运行'android' tool(位于SDK,tool文件目录下)。
|
||||
|
||||
运行'android' tool 来安装大于等于Level 17的API。
|
||||
|
||||
(如果你想从Appium的源码来运行,可在真机或者模拟器上用 [Apache Ant](http://ant.apache.org/) 来编译bootstrap jar包)。
|
||||
|
||||
最后,将环境变量`$ANDROID_HOME`设置为 Android SDK 的路径。例如,如果你将Android SDK 解压到 /usr/local/adt/,你需要把这个路径加到你的shell环境变量中去:
|
||||
|
||||
export ANDROID_HOME="/usr/local/adt/sdk"
|
||||
|
||||
现在就可以启动Appium了!如果你在源码中运行Appium请运行
|
||||
`./reset.sh --android` 版本从Appium checkout会安装所有的依赖。
|
||||
|
||||
### 老版本的额外安装
|
||||
|
||||
当android的版本是2.3到4.1的时候,appium用的是selendroid。 当它检测到时低版本时,它会自动应用Selendroid。但是需要配置一些额外的设置如果从source运行。
|
||||
|
||||
* 已经安装 [Maven 3.1.1](http://maven.apache.org/download.cgi) 或更新 (`mvn`)
|
||||
* 运行 `./reset.sh --selendroid` 从checkout的Appium源码
|
||||
|
||||
### (运行Appium Android 测试)
|
||||
|
||||
在Linux上运行,启动一个API大于等于level17的AVD。 在源文件目录下运行 (`appium`) 在安装好 NPM, 或者 `node`。如果你选择的是从源代码方式运行。
|
||||
参照 [server documentation](/docs/cn/writing-running-appium/server-args.cn.md) 来了解所有命令和参数。
|
||||
|
||||
### 注意
|
||||
|
||||
* Android 加速模拟器需要存在,它有自己的局限性,如果想了解更多,请看这里
|
||||
[page](/docs/cn/appium-setup/android-hax-emulator.cn.md)。
|
||||
* 如果你想运行任何Appium的测试,或者任何强大的命令,确保你的 `hw.battery=yes` 在 AVD's `config.ini`文件中。
|
||||
* Selendroid 需要你APP中的如下权限:
|
||||
`<uses-permission android:name="android.**permission.INTERNET"/>`,
|
||||
如果你在使用selendroid或者低版本的android(如版本2.3到4.1),请确保你的App已设置internet权限。
|
||||
@@ -0,0 +1,72 @@
|
||||
# 部署iOS app 到手机上
|
||||
|
||||
准备在真机上执行appium测试, 需要如下准备:
|
||||
|
||||
1. 用特殊的设备参数来构建app
|
||||
1. 使用 [fruitstrap](https://github.com/ghughes/fruitstrap), 这是一个第三方程序,可以用来部署你构建的app到手机上
|
||||
|
||||
## Xcodebuild 命令的参数:
|
||||
新的参数运行指定设置. 参考 [developer.apple.com](https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html):
|
||||
|
||||
```
|
||||
xcodebuild [-project projectname] [-target targetname ...]
|
||||
[-configuration configurationname] [-sdk [sdkfullpath | sdkname]]
|
||||
[buildaction ...] [setting=value ...] [-userdefault=value ...]
|
||||
```
|
||||
|
||||
这有一个资料来参考可用的[设置](https://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-DontLinkElementID_10)
|
||||
|
||||
```
|
||||
CODE_SIGN_IDENTITY (Code Signing Identity)
|
||||
介绍: 标识符,指定一个签名。
|
||||
例如: iPhone Developer
|
||||
```
|
||||
|
||||
PROVISIONING_PROFILE 已经从可用的的命令中消失了,但还是有必要设置的。
|
||||
|
||||
在xcodebuild命令中设置 "CODE_SIGN_IDENTITY" & "PROVISIONING_PROFILE":
|
||||
|
||||
```
|
||||
xcodebuild -sdk <iphoneos> -target <target_name> -configuration <Debug> CODE_SIGN_IDENTITY="iPhone Developer: Mister Smith" PROVISIONING_PROFILE="XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX"
|
||||
```
|
||||
|
||||
成功的话, app会构建到如下目录 ```<app_dir>/build/<configuration>-iphoneos/<app_name>.app```
|
||||
|
||||
## 用Fruitstrap进行部署
|
||||
clone一个fruitstrap的fork版本在[ghughes version](https://github.com/ghughes/fruitstrap) ,这个已经不再维护. 已确认该fork可用[unprompted fork](https://github.com/unprompted/fruitstrap), 但是其它的据说也可用。
|
||||
|
||||
clone成功的话, 执行 ``make fruitstrap``
|
||||
然后, 然后复制生成的 ``fruitstrap``到app的所在的目录或上级目录下。
|
||||
|
||||
运行fruitstrap 通过输入以下命令 (命令是否可用依赖于你fork的 fruitstrap):
|
||||
|
||||
```
|
||||
./fruitstrap -d -b <PATH_TO_APP> -i <Device_UDID>
|
||||
```
|
||||
|
||||
如果是为了持续集成,你可以发现很有用的方法来记录fruitstrap命令行和日志文件中的记录, 像这样:
|
||||
|
||||
```
|
||||
./fruitstrap -d -b <PATH_TO_APP> -i <Device_UDID> 2>&1 | tee fruit.out
|
||||
```
|
||||
|
||||
在node服务启动前fruitstrap进行需要被结束, 一个方法是扫描fruitstrap的输出来得知app完成启动。 有一个有效的方法是通过一个Rakefile 和一个 ``go_device.sh`` 脚本:
|
||||
|
||||
|
||||
```
|
||||
bundle exec rake ci:fruit_deploy_app | while read line ; do
|
||||
echo "$line" | grep "text to identify successful launch"
|
||||
if [ $? = 0 ]
|
||||
then
|
||||
# Actions
|
||||
echo "App finished launching: $line"
|
||||
sleep 5
|
||||
kill -9 `ps -aef | grep fruitstrap | grep -v grep | awk '{print $2}'`
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
一旦fruitstrap的进程被结束, node 服务就可以启动并且appium测试可以被执行!
|
||||
|
||||
下一步:
|
||||
[在真机上运行appium](real-devices.cn.md)
|
||||
@@ -0,0 +1,31 @@
|
||||
## Android并发测试
|
||||
|
||||
Appium提供了在一台设备上启动多个Android会话的方案,而这个方案需要你输入不同的指令来启动多个Appium服务来实现。
|
||||
|
||||
启动多个Android会话的重要指令包括:
|
||||
|
||||
- `-p` Appium的主要端口
|
||||
- `-U` 设备id
|
||||
- `-bp` Appium bootstrap端口
|
||||
- `--chromedriver-port` chromedriver端口(当使用了webviews或者chrome)
|
||||
- `--selendroid-port` selendroid端口(当使用了selendroid)
|
||||
|
||||
|
||||
更多参数的解释详见 [here](../writing-running-appium/caps.cn.md)。
|
||||
|
||||
|
||||
如果我们有两台设备,设备ID分别为43364和32456,我们应该用下面的命令启动来两个不同的Appium服务:
|
||||
|
||||
`node . -p 4492 -bp 2251 -U 32456`
|
||||
|
||||
`node . -p 4491 -bp 2252 -U 43364`
|
||||
|
||||
只要你的Appium和Appium bootstrap端口介于0和65536即可,并且保证是两个不同的端口以便两个Appium服务不会监听相同的端口。确认你的-u参数绑定正确的设备ID。这可以让Appium知道连接哪台设备,所以参数一定要准确。
|
||||
|
||||
如果你用了chromedriver或selendroid,不同的服务要设置不同的端口。
|
||||
|
||||
### iOS并发测试
|
||||
|
||||
不幸的是,IOS不能进行本地并发测试。跟Android不一样,IOS在同一时间只能启动一个版本的模拟器来运行多个测试。
|
||||
如果你想在IOS上进行并发测试,你需要用到Sauce。只需上传你的Appium测试脚本到Sauce,它就可以按照你的设置执行多个IOS或Android的并发测试。在Sauce上执行测试的更多信息,详见[here](https://docs.saucelabs.com/tutorials/appium/)。
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# Appium支持的平台
|
||||
|
||||
Appium支持很多的运行平台和测试方式(包括原生、混合应用、内嵌浏览器、真机、模拟器等)。这篇文档主要用来让大家明确在使用
|
||||
Appimu的时候支持的平台版本和上述测试方式的必备条件。
|
||||
|
||||
## iOS平台支持
|
||||
|
||||
请移步到[Running on OS X: iOS](running-on-osx.cn.md) 。这里介绍了在iOS系统下使用Appium的必备条件和安装说明。
|
||||
|
||||
* 版本号:6.1,7.0,以及7.1。
|
||||
* 支持设备:iPhone模拟器,iPad模拟器以及iPhones和iPads真机。
|
||||
* 是否支持原生应用:支持。同时支持模拟器中调试应用版本和正确签名的真机ipa。其他相关支持由苹果的[UIAutomation](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/)框架提供。
|
||||
* 是否支持内置移动浏览器:支持。Safari浏览器已经通过测试。对于真机,则需要安装调试工具ios-webkit-remote-debugger。很遗憾,对于Safari的原生界面的自动化是不支持的。更多信息请移步至[mobile web doc](/docs/cn/writing-running-appium/mobile-web.cn.md) 。
|
||||
* 是否支持混合应用:支持。同样对于真机需要安装调试工具ios-webkit-remote-debugger,更多详情请移步至[hybrid doc](/docs/cn/advanced-concepts/hybrid.cn.md) 查看详情。
|
||||
* 是否支持在同一个session中执行多个应用的自动化:不支持。
|
||||
* 是否支持同时再多个设备上执行自动化:不支持。
|
||||
* 是否支持第三方提供应用:只支持在模拟器上有限的第三方应用(例如:喜好设置、地图等)。
|
||||
* 是否支持自定义的、非标准UI控件的自动化:仅支持很少一部分。最好对控件添加可识别信息,以方便对元素进行一些基础的自动化操作。
|
||||
|
||||
## Android平台支持
|
||||
|
||||
请移步至 [Running on OS X: Android](running-on-osx.cn.md),[Running on Windows](running-on-windows.cn.md),或者[Running on Linux](running-on-linux.cn.md) 获得在不同操作系统下android平台对appium的支持和安装配置文档。
|
||||
|
||||
* 支持版本:android 2.3平台及以上。
|
||||
* android 4.2平台及以上通过Appium自有的[UiAutomator](http://developer.android.com/tools/help/uiautomator/index.html)类库支持。默认在自动化后台。
|
||||
* 从android 2.3到4.3平台,Appium是通过绑定[Selendroid](http://selendroid.io),实现自动化测试的,你可以到android开发社区的[Instrumentation](http://developer.android.com/reference/android/app/Instrumentation.html)。(仪表盘)中查看相关介绍。Selendroid拥有一套不同的命令行和不同的profile文件(这部分差距正在逐步缩小)。要获得在后台运行自动化的权限,需要配置`automationName` 组件的值为 `Selendroid`。
|
||||
* 支持的设备:Android模拟器和Android真机。
|
||||
* 是否支持原生应用:支持。
|
||||
* 是否支持内置移动浏览器:支持(除了使用Selendroid后台运行的情况)。通过代理方式绑定到[Chromedriver](https://code.google.com/p/selenium/wiki/ChromeDriver)来运行自动化测试。在android4.2和4.3版本中,只有在官方版本的谷歌浏览器或者Chromium下才能运行自动化测试。伴随着android 4.4+版本的出现。自动化测试则可以运行在内置浏览器的应用程序。但是需要在测试设备环境下安装Chrome/Chromium/浏览器。请移步至[mobile web doc](/docs/cn/writing-running-appium/mobile-web.cn.md) 获取更多详情。
|
||||
* 是否支持混合应用: 支持。请移步至[hybrid doc](/docs/cn/advanced-concepts/hybrid.cn.md)参考相关文档。
|
||||
* 通过默认的Appium的后台支持android 4.4以上的版本。
|
||||
* 通过Selendroid的后台支持android 2.3以上的版本。
|
||||
* 是否支持在同一个session中执行多个应用的自动化:支持(但是不支持使用Selendroid后台的场景)。
|
||||
* 是否支持同时再多个设备上执行自动化:支持,。尽管Appium必须要启动另一个端口即通过添加参数的方式运行命令行,例如`--port`,`--bootstrap-port`(或者`--selendroid-port`)或者`--chromedriver-port`。更多详情请移步至[server args doc](/docs/cn/writing-running-appium/server-args.cn.md)。
|
||||
* 是否支持第三方应用自动化:支持(但是不支持Selendroid后台运行的场景)。
|
||||
* 是否支持自定义的、非标准UI控件的自动化:不支持。
|
||||
@@ -0,0 +1,38 @@
|
||||
# Appium在真机上
|
||||
|
||||
Appium已经初步支持真机测试。
|
||||
|
||||
如果要在真机上执行测试,你将要做如下准备:
|
||||
|
||||
1.一个苹果的开发者ID和有效的开发者对应的配置文件和签名文件
|
||||
|
||||
2.一台iPad或者iPhone
|
||||
|
||||
3. 你要测试的应用的源码
|
||||
|
||||
4. 一台安装了XCode和XCode Command Line Developer Tools的Mac机器
|
||||
|
||||
## Provisioning Profile
|
||||
|
||||
要在真机上测试就需要一个有效的iOS开发者的Distribution Certificate and Provisioning Profile。你可以在这个上面找到配置这些的相关信息[Apple documentation](http://developer.apple.com/library/ios/#documentation/ToolsLanguages/Conceptual/YourFirstAppStoreSubmission/TestYourApponManyDevicesandiOSVersions/TestYourApponManyDevicesandiOSVersions.html)
|
||||
|
||||
同样的,你还需要对你的应用签名,更多的信息可以查看[sign your app](http://developer.apple.com/library/ios/#documentation/ToolsLanguages/Conceptual/YourFirstAppStoreSubmission/ProvisionYourDevicesforDevelopment/ProvisionYourDevicesforDevelopment.html#//apple_ref/doc/uid/TP40011375-CH4-SW1).
|
||||
|
||||
你必须使用Xcode的执行按钮来安装你的应用
|
||||
|
||||
## 使用Appium运行你的测试
|
||||
|
||||
一旦你的设备和应用设置好了之后,你就能够用如下的命令在你的机器上执行测试:
|
||||
|
||||
```
|
||||
node . -U <UDID> --app <bundle_id>
|
||||
```
|
||||
|
||||
这将会启动Appium并且开始在真机上测试应用。
|
||||
|
||||
## 疑问解答思路
|
||||
|
||||
0. 确认UDID已经正确的在xcode organizar或itunes中设置了。很长的字符串(20多个字符串)
|
||||
0.确认你测试代码中的测试对象设备的设置
|
||||
0. 再次确认你从instruments启动你的自动化测试
|
||||
0. 确认instruments已经关闭
|
||||
@@ -0,0 +1,32 @@
|
||||
# 在 Linux 上运行 Appium
|
||||
|
||||
### 限制
|
||||
|
||||
如果你在 Linux 上使用 Appium, 那么你没法使用已经构建好的 '.app',那是为 OS X 准备的。 另外由于 Appium 在测试 iOS 应用时 依赖 OS X 特有的库, 所以你也没有办法测试在 Linux 上测试 iOS 应用。
|
||||
|
||||
## 配置
|
||||
|
||||
首先,安装版本高于或等于 0.8 的 nodejs。可以根据 [instructions for your flavor of linux](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager) 进行安装。
|
||||
|
||||
安装好了 node.js 之后,安装 [Android SDK](http://developer.android.com/sdk/index.html)。 你会需要运行 `android` `adb` 等工具,这些工具都在 SDK 里包含了, 你要做的是配置环境变量。当然你要确保你的 API level 大于等于 17。 你也需要使用 Ant 来构建 bootstrap jar 以便 Appium 使用它来测试 Android 应用。
|
||||
|
||||
最后, 设置 `$ANDROID_HOME` 为你的 Android SDK 的路径。比如, 你将 Android SDK 解压在 `/usr/local/adt/`, 那你就要将如下添加到你的 `.bashrc` 或 `.zshrc` 或 `.bash_profile` 等 shell 配置文件中去:
|
||||
|
||||
export ANDROID_HOME="/usr/local/adt/sdk
|
||||
|
||||
现在你可以运行 Appium 了, 在你 checkout 出来的 Appium 目录里, 运行 `.reset.sh --android`, 它会帮助你安装好所有的依赖。
|
||||
|
||||
## 运行 Appium
|
||||
|
||||
运行测试前, 你需要启动一个 API Level 大于等于 17 的 Android 模拟器或者连接一个系统是 4.1 以上的 Android 真机。然后在 Appium 目录运行
|
||||
|
||||
node .
|
||||
|
||||
你可以在 [server documentation](server-args.cn.md) 找到所有的命令行参数。
|
||||
|
||||
|
||||
## 备注
|
||||
* There exists a hardware accelerated emulator for android, it has it's own
|
||||
limitations. For more information you can check out this
|
||||
Android 有一些硬件加速的模拟器,这些模拟器有自己的限制。你可以在 [page](android-hax-emulator.cn.md) 找到更多的信息。
|
||||
* 确保你使用的 AVD 里面的 `config.ini` 有这条指令 `hw.battery=yes`。
|
||||
@@ -0,0 +1,28 @@
|
||||
# 在 Mac OS X 上使用 Appium
|
||||
|
||||
在 OS X 上, Appium 支持 iOS 和 Android 测试
|
||||
|
||||
## 系统配置 (iOS)
|
||||
|
||||
* Appium 需要 Mac OS X 10.7, 推荐 10.8。 (经过测试, 10.9 也能工作。)
|
||||
* 确保 Xcode 和 iOS SDK 都已经安装好了。 (当前 Appium 支持 Xcode 4.6.3/iOS 6.1 和 Xcode 5/iOS 7.0。 注意不推荐在基于 Xcode 5 下且低于 7.0 的 iOS 版本进行测试。 参照下篇可以获取更多信息)
|
||||
* 你需要授权 iOS 模拟器的使用。如果你是通过 NPM 安装的 Appium,那么你可以运行 `sudo authorize_ios` (`authorize_ios`)是来自 Appium npm 包里的一个二进制执行文件。如果你是从源代码运行 Appium,那么你可以简单的使用 `sudo grunt authorize`。如果你使用[Appium.app](https://github.com/appium/appium-dot-app), 那你只要用界面来操作。
|
||||
* 如果你使用的是Xcode 6,在启动Appium之前,你需要打开模拟器,并且在你需要进行输入文字的操作之前,必须先将输入法提前调出。你可以通过点击输入区域或通过快捷键`command-K`来将软键盘唤出。
|
||||
* Xcode 6中,有一个Devices的模块(command-shift-2可唤出)。你必须确保Appium 的capabilities参数中,所使用到的deviceName要存在于Devices里。换句话说,如果capabilities中的deviceName为"iPhone 5s",platformVersion为"8.0",那么你必须确保Devices中要存在那么一个设备是"iOS8系统的iPhone5s",否则Appium将不知道使用哪一个设备进行测试。
|
||||
* 在iOS8设置中的开发者选项里面,你可以打开或关闭UIAutomation。如果你的是iOS8设备,请在运行Appium之前,确保UIAutomation是打开状态的。
|
||||
|
||||
## 使用多种 iOS SDK 进行测试
|
||||
|
||||
Appium 使用苹果提供的 `instruments` 来启动 iOS 模拟器,默认它会使用当前安装的 Xcode 和该 Xcode 下安装好的最高版本的 iOS SDK。这就意味着如果你想测试 iOS 6.1, 但是你安装了 iOS 7.0, 那么 Appium 会强制使用 7.0 的模拟器。 唯一的方法就是安装多个Xcode,然后在安装不同的 SDK。然后在启动 Appium 前,切换到你要测试的特定的版本。
|
||||
|
||||
另外,我们发现 Xcode 5 上的 iOS 6.1 测试,会很慢而且不稳定。所以我们推荐,如果要在 6.1 及 6.1 以下版本的 iOS 上进行测试,请使用 Xcode 4.6.3。如果要在 iOS 7.0 上测试,请使用 Xcode 5。假设我们的 Xcode 5 在 `/Applications/Xcode.app`, Xcode 4.6 在 `/Applications/Xcode-4.6.app`,我们就可以用下面的命令来切换到 Xcode 4.6 来为 iOS 6.1 测试做准备。
|
||||
|
||||
sudo xcode-select -switch /Applications/Xcode-4.6.app/Contents/Developer/
|
||||
|
||||
如果要回到 Xcode 5 的话,我们再运行一次:
|
||||
|
||||
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer/
|
||||
|
||||
## 系统配置 (Android)
|
||||
|
||||
* 在Mac OSX 上运行Android项目所需要的配置,与Linux的配置方法是一致的,请参考 [Android setup docs](/docs/cn/appium-setup/android-setup.cn.md)。
|
||||
@@ -0,0 +1,58 @@
|
||||
# 在Windows上运行Appium
|
||||
|
||||
### 局限性
|
||||
|
||||
如果你在windows上安装appium,你没法使用预编译专用于OS X的.app文件,你也将不能测试IOS apps,因为appium依赖OS X专用的库来支持IOS测试。这意味着你只能通过在mac上来运行IOS的app测试。这点限制挺大。
|
||||
|
||||
## 开始安装
|
||||
|
||||
1. 安装[nodejs](http://nodejs.org/download/) 0.8版本及以上, 通过官方的安装程序来安装。
|
||||
|
||||
2. 安装android的sdk包,(http://developer.android.com/sdk/index.html), 运行依赖sdk中的'android'工具。并确保你安装了Level17或以上的版本api。设置`ANDROID_HOME`系统变量为你的Android SDK路径,并把tools platform-tools两个目录加入到系统的Path路径里。因为这里面包含有一些执行命令
|
||||
|
||||
3. 安装java的JDK,并设置`JAVA_HOME` 变量为你的JDK目录。
|
||||
|
||||
4. 安装[Apache Ant](http://ant.apache.org/bindownload.cgi)
|
||||
或者直接使用Android Windows SDK自带的ant,地址在eclipse\plugins目录,你需要把这个目录加到你的系统PATH变量中
|
||||
|
||||
5. 安装[Apache Maven](http://maven.apache.org/download.cgi). 并且设置M2HOME和M2环境变量,把M2环境变量添加到你的系统PATH变量中。
|
||||
|
||||
6. 安装[Git](http://git-scm.com/download/win). 确保你安装了windows下的Git,以便可以运行常用的command命令
|
||||
|
||||
|
||||
现在,你已经下载安装了所有的依赖,开始运行
|
||||
reset.bat
|
||||
|
||||
### 运行Appium
|
||||
|
||||
要在windows上运行测试用例,你需要先启动Android模拟器或者连接上一个API Level17以上的android真机。然后在命令行运行`appium`。
|
||||
如果你是使用源码运行Appium的,请在你所安装的appium目录下执行node.js命令:
|
||||
```center
|
||||
node .
|
||||
```
|
||||
|
||||
### 备注
|
||||
* 在windows系统下运行appium.app时,需要使用管理员权限;当你通过源码的形式运行Appium时,也需要使用管理员权限启动CMD。
|
||||
* 在windows系统下运行Android项目时,启动Appium时请带上`--no-reset`或`--full-reset`命令。
|
||||
* 有一个硬件加速模拟器用于android,但是它有自己的一些限制,如果你想了解更多,请参考[页面](android-hax-emulator.cn.md)
|
||||
* 确保在你的AVD的`config.ini`中有一个配置项为`hw.battery=yes`
|
||||
|
||||
|
||||
|
||||
### 最简略的安装方式
|
||||
出于对官方文档的尊重,我按照原文翻译,如下介绍我的安装心得。官方提到的一些工具,其实并不需要安装。
|
||||
下面介绍我已经测试过的安装和使用过程
|
||||
|
||||
### 安装appium
|
||||
|
||||
1. 安装nodejs
|
||||
|
||||
2. 使用npm安装appium,npm install -g appium
|
||||
|
||||
### 运行appium
|
||||
启动appium,直接运行appium 即可。
|
||||
|
||||
### 更新appium
|
||||
通过`npm install -g appium` 来更新appium即可
|
||||
|
||||
如果有任何疑问,欢迎到testerhome.com来交流
|
||||
@@ -0,0 +1,96 @@
|
||||
## Appium 故障排除
|
||||
|
||||
当你遇到问题时,请不要急着将问题提交到Github,也不用急着发到[appium-discuss discussion group](https://discuss.appium.io),也许你可以在本文中找到答案。
|
||||
|
||||
### 常见问题解决办法
|
||||
|
||||
* 确保你的每一个步骤都是遵循 [入门指南](/docs/cn/README.cn.md) 来做的。
|
||||
* 确保你的系统配置正确。(例如:Xcode是否升级到了最新版本,Android SDK是否有设置到环境变量`ANDROID_HOME`中去。)
|
||||
* 确保你的应用存放路径没有错误。
|
||||
|
||||
### Appium.app运行出现问题的解决办法
|
||||
|
||||
* 升级Appium.app后重新打开即可解决。如果提示你不能升级,则需要重新下载Appium.app,下载地址:[appium.io](http://appium.io)
|
||||
|
||||
|
||||
### 通过源码启用Appium出现问题的解决办法
|
||||
|
||||
* 使用`git pull`拉取最新源码,确保运行的代码是当前最新版本。
|
||||
* 针对你所自动化的平台,运行`reset.sh`命令:
|
||||
|
||||
|命令 | 说明 |
|
||||
|-------------------------|-------------|
|
||||
|./reset.sh | # all |
|
||||
|./reset.sh --ios | # ios-only |
|
||||
|./reset.sh --android | # android-only |
|
||||
|./reset.sh --selendroid | # selendroid-only |
|
||||
|
||||
* 当你需要下载以及构建测试应用时,运行`reset.sh`时你需要用到`--dev`指令。
|
||||
* 你也可以使用`appium-doctor`来自动检测你的环境依赖都是否正常。如果你是使用源码运行,则需要使用到`bin/appium-doctor.js`或`node bin/appium-doctor.js`。
|
||||
* 当你将Android SDK升级到22后,可能出现如下错误:
|
||||
`{ANDROID_HOME}/tools/ant/uibuild.xml:155: SDK does not have any Build Tools installed.`
|
||||
这是因为在Android SDK 22中,platform 和 build 工具被分拆到他们各自的SDK管理包中去了。你需要确保你的机器上正确安装了build-tools 和 platform-tools。
|
||||
|
||||
### Android常见问题解决办法
|
||||
|
||||
* 确保 Android 模拟器启动并运行着。
|
||||
* 出现设备连接问题时,运行`adb kill-server && adb devices`是非常有效的。它能够帮助重置和连接Android设备。
|
||||
* 请确保环境变量 ANDROID_HOME 指向的是正确的Android SDK的路径。
|
||||
|
||||
### IOS常见问题解决方案
|
||||
|
||||
* 确保Instruments.app是关闭的。
|
||||
* 如果你是使用模拟器运行的,请不要将真机设备连接电脑。
|
||||
* 确保模拟器或真机中,设置里面的accessibility辅助功能是关闭状态的。
|
||||
* 确保App是编译在当前运行的模拟器上。
|
||||
* 确保App是编译在合适的模拟器(或真机)上,不然会出现`posix spawn`的报错。(比如:运行在debug模式下的模拟器)
|
||||
* 如果你曾经用 sudo 运行过 Appium, 你需要先删除/tmp/instruments_sock, 执行`sudo rm /tmp/instruments_sock`。然后在不适用SUDO的情况下再次启动Appium即可。
|
||||
* 第一次运行Appium时,需要对Instruments进行授权。不然的话会经常弹出对话框要求你输入密码。如果你从源代码运行 Appium,你只需在主分支上运行`sudo grunt authorize`来回避该弹窗。如果用 npm 安装的话,运行 `sudo authorize_ios` 即可。注意,当你每次安装了新版本的xcode,你都需要重复以上操作。
|
||||
* 如果检查路径正确,但仍然报 `iOS Simulator failed to install the application.`的错误的时候,请尝试重启你的电脑。
|
||||
|
||||
### Webview/Hybrid/Safari 应用支持
|
||||
|
||||
* 确保真机上的'Web Inspector'为打开状态。
|
||||
* 确保打开了Safari的开发模式。(Safari - Advance Preferences- Developer menu for
|
||||
simulators)
|
||||
* 确保由client library提供的Appium命令-`context`能够正常得对contexts进行切换。
|
||||
* 当你尝试打开代理的时候,出现如下错误:select_port() failed,请参考[discussion](https://groups.google.com/forum/#!topic/appium-discuss/tw2GaSN8WX0)
|
||||
|
||||
### FirefoxOS常见问题解决办法
|
||||
|
||||
* 确保 Boot-to-Gecko 模拟器启动并运行着。
|
||||
* 确保模拟器的屏幕是亮着并无锁屏的(可能需要重启 B2G).
|
||||
|
||||
### 到社区寻求帮助
|
||||
|
||||
若通过上述方法你的问题依然没有得到解决,你可以:
|
||||
|
||||
如果你的 Appium 无法正常工作,然后错误信息不够清晰,欢迎加入 [discussion group](https://discuss.appium.io)中发表你的问题,你的问题需要包括以下内容:
|
||||
|
||||
* 你是如何运行Appium的?(Appium.app, npm, source)
|
||||
* 你使用的是什么操作系统?
|
||||
* 你使用的是什么设备?版本是什么? (i.e. Android 4.4, or iOS 7.1)
|
||||
* 你使用的是真机还是模拟器?
|
||||
* 给出你得到的客户端和服务端的出错日志 (比如,"我的Python代码中报了如下错误:balabala,在Appium server中的输出内容如链接中所示")
|
||||
* 除了上述, 贴出 Appium 服务器端的输出也非常重要,特别是运行在 verbose 模式。这样我们可以分析诊断问题在哪里。
|
||||
|
||||
如果你确信你发现的是一个BUG,请到[issue tracker](https://github.com/appium/appium/issues)中提交一个issue,并将BUG的内容描述清楚。
|
||||
|
||||
### 已知问题
|
||||
|
||||
* 如果你从 Node 官网安装的 Node,那需要你使用 sudo 运行 `npm`。 但这么做并不是非常理想。请尝试从
|
||||
[n](https://github.com/visionmedia/n) 获取node 或运行`brew install node`来安装 。
|
||||
* Webview通过代理可以支持iOS真机设备,请参考[discussion](https://groups.google.com/d/msg/appium-discuss/u1ropm4OEbY/uJ3y422a5_kJ)
|
||||
* 有时候, iOS 的 UI 元素在定位到之后几毫秒会突然变得无效。这会导致一个类似(null) cannot be tapped的错误。唯一的解决方法就是把finding-and-acting的代码放到 retry 块里。
|
||||
* 如果你是通过MacPorts安装了Node和Npm,你必须确保MacPorts的bin文件夹已经被添加到环境变量`PATH`中去,不然Appium会出现难以找到可执行`node`的情况。
|
||||
|
||||
|
||||
### 特定的错误
|
||||
|
||||
|Action|Error|Resolution|
|
||||
|------|-----|----------|
|
||||
|Running reset.sh|xcodebuild: error: SDK "iphonesimulator6.1" cannot be located|安装 iPhone 6.1 SDK 或者 使用单独的 SDK 构建 待测应用 比如: `grunt buildApp:UICatalog:iphonesimulator5.1`|
|
||||
|Running reset.sh|Warning: Task "setGitRev" not found. Use --force to continue.|使用`git submodule update --init`更新模块并再次运行`reset.sh`|
|
||||
|Running reset.sh|`[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2:compile (default-compile) on project selendroid-server: Compilation failure [ERROR] Failure executing javac, but could not parse the error: [ERROR] [ERROR] [ERROR] The system is out of resources. [ERROR] Consult the following stack trace for details. [ERROR] java.lang.StackOverflowError `|`export MAVEN_OPTS="-Xms1024m -Xmx2048m -Xss2048k"`|
|
||||
|Running ios test|`[INST STDERR] posix spawn failure; aborting launch`|你的应用没有正确编译在模拟器或真机上。|
|
||||
|Running mobile safari test|`error: Could not prepare mobile safari with version '7.1'`|你可能需要在此运行授权脚本以保证使iOS SDK文件为可写状态。 E.g., `sudo authorize_ios`|
|
||||
@@ -0,0 +1,179 @@
|
||||
##从源码运行Appium
|
||||
|
||||
你想要从源码运行 Appium 并帮助修复 bug 和添加新的特性么?很好! fork 这个项目,做一点更改,并且发送一个请求吧!
|
||||
另外,在工作之前请先看下我们的[代码风格指南](style-guide.cn.md)。请在发送请求前,确保单元测试与功能测试都测试通过;
|
||||
关于如何运行测试的更多信息,请继续阅读!
|
||||
首先确保你阅读并遵循 README 中的安装说明。
|
||||
|
||||
###从源码配置Appium
|
||||
|
||||
Appium 的安装,包含在你的测试代码与设备/模拟器之间来回发送消息的 Appium 服务端,和一个用任何存在且兼容Appium的语言编写的测试脚本。
|
||||
运行一个 Appium 服务器实例,然后进行你的测试。
|
||||
|
||||
快速开始的方式:
|
||||
|
||||
```center
|
||||
$ git clone https://github.com/appium/appium.git
|
||||
$ cd appium
|
||||
$ ./reset.sh
|
||||
$ sudo ./bin/authorize-ios.js # for ios only
|
||||
$ node .
|
||||
```
|
||||
|
||||
### Appium 开发环境搭建
|
||||
|
||||
确保你安装了 ant,maven,adb 并且将他们加入到了系统环境变量 PATH 中,与此同时你还需要安装 android-16 sdk(Selendroid) 和android-19 sdk。
|
||||
从你本地仓库的命令行提示,使用下边的命令安装如下包(如果你没有使用homebrew包管理器安装 `node`,则你可能不得不使用 sudo 权限运行npm):
|
||||
|
||||
```center
|
||||
npm install -g mocha
|
||||
npm install -g grunt-cli
|
||||
node bin/appium-doctor.js --dev
|
||||
./reset.sh --dev
|
||||
```
|
||||
|
||||
前两个命令安装测试和构建工具(如果你已经通过 Homebrew 包管理器安装了 node.js 就不需要 `sudo` 了)。
|
||||
第三个命令验证所有的依赖关系是否设置正确(由于依赖关系构建 Appium 不同于简单的运行 Appium ),
|
||||
第四个命令安装所有程序依赖关系和构建支持二进制文件和测试应用程序。
|
||||
`reset.sh` 也是建议先从 master 上 pull 下改变后的内容再执行命令。
|
||||
运行 `reset.sh` 加上 `--dev` 标志同时安装 git hooks 以确保代码质量在提交时是被保存过的。
|
||||
此时,你可以启动 Appium 服务:
|
||||
|
||||
```center
|
||||
node .
|
||||
```
|
||||
|
||||
查看完整的服务文档参数列表[the server documentation](/docs/cn/writing-running-appium/server-args.cn.md)
|
||||
|
||||
想要实现任务自动化,请检出[Appium Grunt tasks](/docs/cn/contributing-to-appium/grunt.cn.md)来构建应用程序,安装程序,生成文档,等等。
|
||||
|
||||
|
||||
#### 搭建iOS运行环境
|
||||
|
||||
为了避免启动 iOS apps 时弹出安全警告,你可以通过以下两种方法修改 /etc/authorization 文件:
|
||||
|
||||
1. 手动将 `/etc/authorization` 文件中 `<key>system.privilege.taskport<key/>` 下紧跟 `<allow-root>` 的元素改成 `<true/>`。
|
||||
|
||||
|
||||
2. 运行以下grunt命令来自动修改 `/etc/authorization` 文件:
|
||||
|
||||
```center
|
||||
sudo ./bin/authorize-ios.js
|
||||
```
|
||||
|
||||
然后再运行以下命令:
|
||||
|
||||
```center
|
||||
./reset.sh --ios --dev
|
||||
```
|
||||
|
||||
现在你的 appium 实例已经准备就绪,运行 `node .` 来启动 appium server.
|
||||
|
||||
#### 搭建android运行环境
|
||||
|
||||
Bootstrap 通过运行以下命令来启动 android:
|
||||
|
||||
```center
|
||||
./reset.sh --android --dev
|
||||
```
|
||||
|
||||
如果你想运行[Selendroid](http://github.com/DominikDary/selendroid) 来支持2.3这样的旧的android平台,运行以下命令:
|
||||
|
||||
```center
|
||||
./reset.sh --selendroid --dev
|
||||
```
|
||||
|
||||
确保你有且只有一个 Android 模拟器或者真机在运行,举个例子,在其它的设备上运行此命令(假设 `emulator` 命令已经在你的 path 中了)需执行:
|
||||
|
||||
|
||||
```center
|
||||
emulator -avd <MyAvdName>
|
||||
```
|
||||
|
||||
现在你可以通过 `node .` 启动 Appium server 了。
|
||||
|
||||
#### 确保更新到最新版本
|
||||
|
||||
由于 Appium 使用一些包的开发版本,所以经常安装新的 `npm` 包和升级不同的包是很有必要的。以下命令可以将所有平台上的包进行更新( `--dev` 标志会获取 npm dev 依赖和 Appium 测试套件中用到的应用程序)。当Appium提示版本更新时,你也可以用以下命令来更新:
|
||||
|
||||
|
||||
```center
|
||||
./reset.sh --dev
|
||||
```
|
||||
|
||||
或者你可以只更新指定的平台:
|
||||
|
||||
```center
|
||||
./reset.sh --ios --dev
|
||||
./reset.sh --android --dev
|
||||
./reset.sh --selendroid --dev
|
||||
```
|
||||
|
||||
### 运行测试集
|
||||
首先,看看我们的文档[普通情况下执行测试](/docs/cn/writing-running-appium/running-tests.cn.md) ,
|
||||
然后确保你的环境在对应的平台上已经搭建好了且与你所期望的那样。
|
||||
|
||||
当你的环境搭建好了之后并且你的代码是最新的,你可以通过以下的方式来运行单元测试:
|
||||
|
||||
```center
|
||||
grunt unit
|
||||
```
|
||||
你可以在所支持的平台上运行一些功能测试(确保后 Appium 用 `node .` 在另外一个窗口中运行):
|
||||
|
||||
```center
|
||||
bin/test.sh
|
||||
```
|
||||
|
||||
或者你可以通过运行 `test.sh` 来对指定的平台环境进行测试:
|
||||
|
||||
```center
|
||||
bin/test.sh --android
|
||||
bin/test.sh --ios
|
||||
bin/test.sh --ios7
|
||||
bin/test.sh --ios71
|
||||
```
|
||||
在提交代码时,请运行 `grunt` 执行一些基本的测试和核对代码质量标准的更改,请注意,这可能会自动发生的,
|
||||
如果你已经运行 `reset.sh --dev` ,这于你预先提交代码的操作所关联起来的。
|
||||
|
||||
```center
|
||||
grunt lint
|
||||
> Running "newer:jshint" (newer) task
|
||||
>
|
||||
> Running "newer:jshint:files" (newer) task
|
||||
> No newer files to process.
|
||||
>
|
||||
> Running "newer:jshint:test" (newer) task
|
||||
> No newer files to process.
|
||||
>
|
||||
> Running "newer:jshint:examples" (newer) task
|
||||
> No newer files to process.
|
||||
>
|
||||
> Running "jscs:files" (jscs) task
|
||||
> >> 303 files without code style errors.
|
||||
```
|
||||
|
||||
#### 运行单独的测试
|
||||
如果你有一个 Appium 服务监听,你可以通过 Mocha 来运行单独的测试文件,例如:
|
||||
|
||||
```center
|
||||
DEVICE=ios71 mocha -t 60000 -R spec test/functional/ios/testapp/simple.js
|
||||
```
|
||||
或者单独的测试集(例如,测试名称中的单词 "alert" )
|
||||
|
||||
|
||||
```center
|
||||
DEVICE=ios6 mocha -t 60000 -R spec --grep "alert" test/functional/ios/uicatalog
|
||||
```
|
||||
|
||||
对于 windows 操作系统,你可以用 `set DEVICE=android` 在 cmd 命令行的方式中运行以上所有测试集,例如:
|
||||
|
||||
|
||||
```center
|
||||
set DEVICE=android
|
||||
mocha -t 60000 -R spec test/functional/android/apidemos/alerts-specs.js
|
||||
```
|
||||
|
||||
注意:对于安卓系统,你将需要一个屏幕大小为4.0(400x800)的模拟器/设备(emulator/device),有些测试集在不同的屏幕大小下可能会失败。
|
||||
|
||||
`DEVICE` 必须设置为一个有效的值:`ios71`, `ios6`, `android`, `selendroid`
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
##从源码运行Appium
|
||||
|
||||
你想要从源码运行 Appium 并帮助修复 bug 和添加新的特性么?很好! fork 这个项目,做一点更改,并且发送一个请求吧!
|
||||
另外,在工作之前请先看下我们的[代码风格指南](style-guide.cn.md)。请在发送请求前,确保单元测试与功能测试都测试通过;
|
||||
关于如何运行测试的更多信息,请继续阅读!
|
||||
首先确保你阅读并遵循 README 中的安装说明。
|
||||
|
||||
###从源码配置Appium
|
||||
|
||||
Appium 的安装,包含在你的测试代码与设备/模拟器之间来回发送消息的 Appium 服务端,和一个用任何存在且兼容Appium的语言编写的测试脚本。
|
||||
运行一个 Appium 服务器实例,然后进行你的测试。
|
||||
|
||||
快速开始的方式:
|
||||
|
||||
```center
|
||||
$ git clone https://github.com/appium/appium.git
|
||||
$ cd appium
|
||||
$ ./reset.sh
|
||||
$ sudo ./bin/authorize-ios.js # for ios only
|
||||
$ node .
|
||||
```
|
||||
|
||||
### Appium 开发环境搭建
|
||||
|
||||
确保你安装了 ant,maven,adb 并且将他们加入到了系统环境变量 PATH 中,与此同时你还需要安装 android-16 sdk(Selendroid) 和android-19 sdk。
|
||||
从你本地仓库的命令行提示,使用下边的命令安装如下包(如果你没有使用homebrew包管理器安装 `node`,则你可能不得不使用 sudo 权限运行npm):
|
||||
|
||||
```center
|
||||
npm install -g mocha
|
||||
npm install -g grunt-cli
|
||||
node bin/appium-doctor.js --dev
|
||||
./reset.sh --dev
|
||||
```
|
||||
|
||||
前两个命令安装测试和构建工具(如果你已经通过 Homebrew 包管理器安装了 node.js 就不需要 `sudo` 了)。
|
||||
第三个命令验证所有的依赖关系是否设置正确(由于依赖关系构建 Appium 不同于简单的运行 Appium ),
|
||||
第四个命令安装所有程序依赖关系和构建支持二进制文件和测试应用程序。
|
||||
`reset.sh` 也是建议先从 master 上 pull 下改变后的内容再执行命令。
|
||||
运行 `reset.sh` 加上 `--dev` 标志同时安装 git hooks 以确保代码质量在提交时是被保存过的。
|
||||
此时,你可以启动 Appium 服务:
|
||||
|
||||
```center
|
||||
node .
|
||||
```
|
||||
|
||||
查看完整的服务文档参数列表[the server documentation](/docs/cn/writing-running-appium/server-args.cn.md)
|
||||
|
||||
想要实现任务自动化,请检出[Appium Grunt tasks](/docs/cn/contributing-to-appium/grunt.cn.md)来构建应用程序,安装程序,生成文档,等等。
|
||||
|
||||
|
||||
#### 搭建iOS运行环境
|
||||
|
||||
为了避免启动 iOS apps 时弹出安全警告,你可以通过以下两种方法修改 /etc/authorization 文件:
|
||||
|
||||
1. 手动将 `/etc/authorization` 文件中 `<key>system.privilege.taskport<key/>` 下紧跟 `<allow-root>` 的元素改成 `<true/>`。
|
||||
|
||||
|
||||
2. 运行以下grunt命令来自动修改 `/etc/authorization` 文件:
|
||||
|
||||
```center
|
||||
sudo ./bin/authorize-ios.js
|
||||
```
|
||||
|
||||
然后再运行以下命令:
|
||||
|
||||
```center
|
||||
./reset.sh --ios --dev
|
||||
```
|
||||
|
||||
现在你的 appium 实例已经准备就绪,运行 `node .` 来启动 appium server.
|
||||
|
||||
#### 搭建android运行环境
|
||||
|
||||
Bootstrap 通过运行以下命令来启动 android:
|
||||
|
||||
```center
|
||||
./reset.sh --android --dev
|
||||
```
|
||||
|
||||
如果你想运行[Selendroid](http://github.com/DominikDary/selendroid) 来支持2.3这样的旧的android平台,运行以下命令:
|
||||
|
||||
```center
|
||||
./reset.sh --selendroid --dev
|
||||
```
|
||||
|
||||
确保你有且只有一个 Android 模拟器或者真机在运行,举个例子,在其它的设备上运行此命令(假设 `emulator` 命令已经在你的 path 中了)需执行:
|
||||
|
||||
|
||||
```center
|
||||
emulator -avd <MyAvdName>
|
||||
```
|
||||
|
||||
现在你可以通过 `node .` 启动 Appium server 了。
|
||||
|
||||
#### 确保更新到最新版本
|
||||
|
||||
由于 Appium 使用一些包的开发版本,所以经常安装新的 `npm` 包和升级不同的包是很有必要的。以下命令可以将所有平台上的包进行更新( `--dev` 标志会获取 npm dev 依赖和 Appium 测试套件中用到的应用程序)。当Appium提示版本更新时,你也可以用以下命令来更新:
|
||||
|
||||
|
||||
```center
|
||||
./reset.sh --dev
|
||||
```
|
||||
|
||||
或者你可以只更新指定的平台:
|
||||
|
||||
```center
|
||||
./reset.sh --ios --dev
|
||||
./reset.sh --android --dev
|
||||
./reset.sh --selendroid --dev
|
||||
```
|
||||
|
||||
### 运行测试集
|
||||
首先,看看我们的文档[普通情况下执行测试](/docs/cn/writing-running-appium/running-tests.cn.md) ,
|
||||
然后确保你的环境在对应的平台上已经搭建好了且与你所期望的那样。
|
||||
|
||||
当你的环境搭建好了之后并且你的代码是最新的,你可以通过以下的方式来运行单元测试:
|
||||
|
||||
```center
|
||||
grunt unit
|
||||
```
|
||||
你可以在所支持的平台上运行一些功能测试(确保后 Appium 用 `node .` 在另外一个窗口中运行):
|
||||
|
||||
```center
|
||||
bin/test.sh
|
||||
```
|
||||
|
||||
或者你可以通过运行 `test.sh` 来对指定的平台环境进行测试:
|
||||
|
||||
```center
|
||||
bin/test.sh --android
|
||||
bin/test.sh --ios
|
||||
bin/test.sh --ios7
|
||||
bin/test.sh --ios71
|
||||
```
|
||||
在提交代码时,请运行 `grunt` 执行一些基本的测试和核对代码质量标准的更改,请注意,这可能会自动发生的,
|
||||
如果你已经运行 `reset.sh --dev` ,这于你预先提交代码的操作所关联起来的。
|
||||
|
||||
```center
|
||||
grunt lint
|
||||
> Running "newer:jshint" (newer) task
|
||||
>
|
||||
> Running "newer:jshint:files" (newer) task
|
||||
> No newer files to process.
|
||||
>
|
||||
> Running "newer:jshint:test" (newer) task
|
||||
> No newer files to process.
|
||||
>
|
||||
> Running "newer:jshint:examples" (newer) task
|
||||
> No newer files to process.
|
||||
>
|
||||
> Running "jscs:files" (jscs) task
|
||||
> >> 303 files without code style errors.
|
||||
```
|
||||
|
||||
#### 运行单独的测试
|
||||
如果你有一个 Appium 服务监听,你可以通过 Mocha 来运行单独的测试文件,例如:
|
||||
|
||||
```center
|
||||
DEVICE=ios71 mocha -t 60000 -R spec test/functional/ios/testapp/simple.js
|
||||
```
|
||||
或者单独的测试集(例如,测试名称中的单词 "alert" )
|
||||
|
||||
|
||||
```center
|
||||
DEVICE=ios6 mocha -t 60000 -R spec --grep "alert" test/functional/ios/uicatalog
|
||||
```
|
||||
|
||||
对于 windows 操作系统,你可以用 `set DEVICE=android` 在 cmd 命令行的方式中运行以上所有测试集,例如:
|
||||
|
||||
|
||||
```center
|
||||
set DEVICE=android
|
||||
mocha -t 60000 -R spec test/functional/android/apidemos/alerts-specs.js
|
||||
```
|
||||
|
||||
注意:对于安卓系统,你将需要一个屏幕大小为4.0(400x800)的模拟器/设备(emulator/device),有些测试集在不同的屏幕大小下可能会失败。
|
||||
|
||||
`DEVICE` 必须设置为一个有效的值:`ios71`, `ios6`, `android`, `selendroid`
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# 名单
|
||||
|
||||
### 以下这些项目,鼓舞了我们,成就了 Appium。
|
||||
|
||||
* [Apple UIAutomation](http://developer.apple.com/library/ios/#documentation/DeveloperTools/Reference/UIAutomationRef/_index.html)
|
||||
* [GhostDriver](https://github.com/detro/ghostdriver)
|
||||
* [IOS Auto](https://github.com/penguinho/applecart)
|
||||
* [IOS Driver](https://github.com/ios-driver/ios-driver)
|
||||
* [Mechanic.js](https://github.com/jaykz52/mechanic)
|
||||
* [node-webkit](https://github.com/rogerwang/node-webkit)
|
||||
* [Remote Debug](https://github.com/leftlogic/remote-debug)
|
||||
* [Selenium Project](http://code.google.com/p/selenium/)
|
||||
* [ios-webkit-debug-proxy](https://github.com/google/ios-webkit-debug-proxy)
|
||||
* [instruments-without-delay](https://github.com/facebook/instruments-without-delay)
|
||||
* [deviceconsole](https://github.com/rpetrich/deviceconsole)
|
||||
@@ -0,0 +1,35 @@
|
||||
# Appium grunt 命令
|
||||
|
||||
[Grunt](http://gruntjs.com) 是 Node.js 的 Make! 我们用它来自动化所有的 appium 开发任务。 下面就是你能做的:
|
||||
|
||||
|任务|描述|
|
||||
|----|-----------|
|
||||
|grunt lint|运行 JSLint|
|
||||
|grunt test|运行所有的测试|
|
||||
|grunt functional|运行整个功能测试集|
|
||||
|grunt ios|运行 iOS 功能测试集|
|
||||
|grunt android|运行 Android 功能测试集|
|
||||
|grunt selendroid|运行 selendroid 功能测试集|
|
||||
|grunt firefoxos|运行 firefoxos 功能测试集|
|
||||
|grunt unit|运行所有的单元测试|
|
||||
|grunt getSampleCode|下载示例代码和示例app. 接受`:hardcore` 参数
|
||||
|grunt buildApp:<AppName>:<SDK>|构建一个用于 iPhone 模拟器的 iOS 应用。 我们预计这个应用的路径是 `sample-code/apps/<AppName>/build/Release-iphonesimulator/<AppName>.app`. 默认的 SDK 是 'iphonesimulator7.1'|
|
||||
|grunt signApp:<certName>|使用开发证书的绝对路径,签名测试应用。|
|
||||
|grunt authorize|授权模拟器,使它不需要弹框请求权限。|
|
||||
|grunt log|打印 appium.log (运行测试的时候很有用)|
|
||||
|grunt configAndroidBootstrap|配置使用 ant 构建 Android 的 bootstrap.jar|
|
||||
|grunt buildAndroidBootstrap|使用 ant 构建 bootstrap.jar|
|
||||
|grunt buildSelendroidServer|构建 selendroid 服务器|
|
||||
|grunt configAndroidApp:<AppName>|配置使用 ant 构建 android 测试应用。 我们期待有一个 `sample-code/apps/<AppName>` 的 Android 项目|
|
||||
|grunt buildAndroidApp:<AppName>|使用 ant 构建项目. 会在 `sample-code/apps/<AppName>` 下生成应用。|
|
||||
|grunt installAndroidApp:<AppName>|将安卓应用安装到模拟器和设备中去|
|
||||
|grunt docs|生成文档|
|
||||
|grunt generateAppiumIo|将 README.md 转成 appium.io 的 getting-started.html|
|
||||
|grunt setConfigVer:<device>|将 package.json 里面 appium 的版本号和对应设备写入 `.appiumconfig.json` 文件|
|
||||
|
||||
## 其他
|
||||
|
||||
`grunt buildApp` 默认使用 iPhone 6.1 模拟器的 SDK 来构建应用。你可以传其他的 SDK 给 grunt 命令。
|
||||
(用 `xcodebuild -showsdks` 找出你所有的 sdk):
|
||||
|
||||
> grunt buildApp:UICatalog:iphonesimulator6.0
|
||||
@@ -0,0 +1,58 @@
|
||||
## 如何去写文档
|
||||
|
||||
`##` 被用于写第二级标题。每个文档必须以第二级标题开头。
|
||||
这是为了支持appium.io文档的生成,不要使用下划线`---`的方式来创建标题。
|
||||
不要使用第一级标题或者 `===` 底线方式来创建标题(其中文件夹名字被用于第一级标题)
|
||||
|
||||
### 小标题
|
||||
|
||||
`###` 用于小标题。
|
||||
|
||||
### 普通标题
|
||||
|
||||
`####` 用于不会出现在目录中的标题。
|
||||
不要使用第五级标题 `#####`, 或者第六级标题 `######`。
|
||||
|
||||
### 分隔线
|
||||
|
||||
不要使用分隔线例如 `--` 或者 `---`。 这会使 Slate 混乱。
|
||||
|
||||
### 链接
|
||||
|
||||
链接到 readme:
|
||||
|
||||
`[readme](../../README.md)`
|
||||
|
||||
链接到 contributing:
|
||||
|
||||
`[contributing](../../CONTRIBUTING.md)`
|
||||
|
||||
链接到其他文档:
|
||||
|
||||
`[link text](filename.md)`
|
||||
|
||||
链接到文档的内部, 使用 `#` 来标记 Slate 链接。
|
||||
|
||||
`[go direct to json](filename.md#json-wire-protocol-server-extensions)`
|
||||
|
||||
需要注意的是当标题改变时,哈希链接会损坏。所以链接到文档的开头是最好的( `other.md` 替换 `other.md#something` )。
|
||||
|
||||
### appium.io兼容性
|
||||
|
||||
#### 在appium.io中心对齐代码
|
||||
|
||||
Appium.io中文档使用 [slate](https://github.com/tripit/slate) 来作为文档标准
|
||||
如果在文件中的代码段不是特定语言或如果你想要代码片段保持与文本中心对齐在 appium.io 文档中,请把代码块放在中心位置
|
||||
例子:
|
||||
```中心
|
||||
代码片段放在这里
|
||||
```
|
||||
#### 发布
|
||||
发布文档请在appium.io中查看 [api-docs](https://github.com/appium/api-docs) 和
|
||||
在 [appium.io](https://github.com/appium/appium.io) 中查看。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
# 贡献者的代码风格指南
|
||||
|
||||
感谢你们对 Appium 的贡献! 这些是我们书写 javascript 代码时使用的基本原则。
|
||||
请遵守这些,避免风格的来回修改,以便我们可以合并你的 pull 请求。
|
||||
基本原则就是:*让你的代码看起来和周围的代码一致*。
|
||||
|
||||
## 衍合(Rebasing)
|
||||
|
||||
每个 pull 请求中的提交(commits)必须包括 [logical changes](https://github.com/appium/appium/pull/920#issuecomment-21588553)。
|
||||
如果有多个作者,确认每个作者有自己的提交。最好不要修改作者信息。
|
||||
合并(merge)提交必须从 pull 请求中 rebase 。
|
||||
|
||||
## 检错(Linting)
|
||||
|
||||
所有的代码 (除了 `bootstrap.js` 的代码,它使用了 Apple 的私有方法) 必须通过 JSLint。
|
||||
为了检查你的代码,你可以在 Appium 存储目录下,简单地运行 `grunt lint`。
|
||||
如果你已创建一个新的 .js 文件,请确认它在 `grunt.js` 中被通配符覆盖,或者被专门添加。
|
||||
|
||||
边输入边检错你的代码是容易实现的,使得整个进程更加顺利。
|
||||
我们喜欢 [jshint](http://www.jshint.com), 因为它有与许多源代码编辑器的集成。
|
||||
文件 `.jshintrc` 加入到仓库中,它的内容是:
|
||||
|
||||
```json
|
||||
{
|
||||
"laxcomma": true,
|
||||
"strict": true,
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"trailing": true,
|
||||
"node": true,
|
||||
"es5": true,
|
||||
"white": true,
|
||||
"indent": 2
|
||||
}
|
||||
```
|
||||
|
||||
因为jshint不再执行代码风格,我们也使用 [jscs](https://github.com/mdevils/node-jscs),它其中也存在许多源代码编辑器的集成。配置文件是:
|
||||
|
||||
```json
|
||||
{
|
||||
"excludeFiles": ["submodules/**", "node_modules/**",
|
||||
"./lib/server/static/**", "./lib/devices/firefoxos/atoms/*.js",
|
||||
"./test/harmony/**/*.js", "./sample-code/examples/node/**/*-yiewd.js",
|
||||
"./sample-code/apps/**", "./sample-code/examples/php/vendor/**"],
|
||||
"requireCurlyBraces": ["for", "while", "do", "try", "catch"],
|
||||
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch",
|
||||
"return", "try", "catch", "function"],
|
||||
"disallowMixedSpacesAndTabs": true,
|
||||
"disallowTrailingWhitespace": true,
|
||||
"requireSpacesInFunctionExpression": {
|
||||
"beforeOpeningCurlyBrace": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
你将在你喜欢的编辑器中看到这些在配置文件中定义的警告类型,查看[this page for jshint](http://www.jshint.com/platforms/) 和
|
||||
[this page for jscs](https://github.com/mdevils/node-jscs#friendly-packages),编辑器和平台列表,找到使你的编辑器自动化检错的设置方法。
|
||||
|
||||
## 风格注意点
|
||||
|
||||
* 使用两个空格来缩进, *不要使用 tabs*
|
||||
* 在运算符两边,分别添加一个空格:
|
||||
|
||||
```js
|
||||
var x = 1;
|
||||
```
|
||||
而不是
|
||||
```js
|
||||
var x=1;
|
||||
```
|
||||
|
||||
* 在 lists, objects, function calls 等中,逗号和冒号后面需要添加一个空格:
|
||||
|
||||
```js
|
||||
var x = myFunc("lol", {foo: bar, baz: boo});
|
||||
```
|
||||
而不是
|
||||
```js
|
||||
var x = myFunc("lol",{foo:bar,baz:boo});
|
||||
```
|
||||
|
||||
* 代码语句一般以分号结尾
|
||||
* 以逗号开头:
|
||||
|
||||
```js
|
||||
var x = {
|
||||
foo: 'bar'
|
||||
, baz: 'boo'
|
||||
, wuz: 'foz'
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
* 左花括号应该和 `function`, `if` 等 写在同一行, `else` 被夹在两个花括号中间:
|
||||
|
||||
```js
|
||||
if (foo === bar) {
|
||||
// do something
|
||||
} else {
|
||||
// do something else
|
||||
}
|
||||
```
|
||||
|
||||
* `if`, `for`, 和 `function` 之后需要添加空格:
|
||||
|
||||
```js
|
||||
if (foo === bar) {
|
||||
```
|
||||
```js
|
||||
for (var i = 0; i < 10; i ++) {
|
||||
```
|
||||
```js
|
||||
var lol = function (foo) {
|
||||
```
|
||||
而不是
|
||||
```js
|
||||
if(foo === bar) {
|
||||
```
|
||||
```js
|
||||
for(var i = 0; i < 10; i ++) {
|
||||
```
|
||||
```js
|
||||
var lol = function(foo) {
|
||||
```
|
||||
|
||||
* 只有一行代码时,花括号也应该添加上:
|
||||
|
||||
```js
|
||||
if (foo === bar) {
|
||||
foo++;
|
||||
}
|
||||
```
|
||||
而不是
|
||||
```js
|
||||
if (foo === bar)
|
||||
foo++;
|
||||
```
|
||||
|
||||
* 一般情况下,使用 `===`, 而不是 `==`; 使用 `!==`, 而不是 `!=`
|
||||
* 单行长度不应超过79个字符
|
||||
* 截断长字符串,方法如下:
|
||||
|
||||
```js
|
||||
myFunc("This is a really long string that's longer " +
|
||||
"than 79 characters so I broke it up, woo");
|
||||
```
|
||||
|
||||
* 注释需要和上一行代码左对齐:
|
||||
|
||||
```js
|
||||
if (foo === 5) {
|
||||
myFunc(foo);
|
||||
// foo++;
|
||||
}
|
||||
```
|
||||
而不是
|
||||
```js
|
||||
if (foo === 5) {
|
||||
myFunc(foo);
|
||||
//foo++;
|
||||
}
|
||||
```
|
||||
|
||||
除了出错后直接调用回调函数(callback)处理错误(error)的语句
|
||||
|
||||
```javascript
|
||||
if (err) return cb(err);
|
||||
```
|
||||
|
||||
* 通过拓展原型,来创建子类:
|
||||
|
||||
```js
|
||||
var _ = require('underscore');
|
||||
|
||||
var SuperClass = function () {
|
||||
this.init();
|
||||
};
|
||||
|
||||
SuperClass.prototype.init = function () {
|
||||
// initialize
|
||||
};
|
||||
|
||||
// Create a subclass
|
||||
|
||||
var SubClass = function () {
|
||||
this.init();
|
||||
};
|
||||
|
||||
_.extend(SubClass.prototype, SuperClass.prototype);
|
||||
```
|
||||
|
||||
* 函数定义中,最后使用回调函数:
|
||||
|
||||
```js
|
||||
var foo = function (arg1, arg2, cb) {
|
||||
...
|
||||
};
|
||||
```
|
||||
|
||||
* 使用变量来定义函数:
|
||||
|
||||
```js
|
||||
var myFunc = function (a, b, c) {};
|
||||
```
|
||||
而不是
|
||||
```js
|
||||
function myFunc (a, b, c) {}
|
||||
```
|
||||
|
||||
* 变量名应该是驼峰式大小写风格:
|
||||
|
||||
```js
|
||||
var myVariable = 42;
|
||||
```
|
||||
而不是
|
||||
```js
|
||||
var my_variable = 42;
|
||||
```
|
||||
|
||||
* 检查是否有未定义的变量:
|
||||
|
||||
```js
|
||||
typeof myVariable === "undefined"
|
||||
```
|
||||
而不是
|
||||
```js
|
||||
myVariable === undefined
|
||||
```
|
||||
|
||||
## 试验风格:
|
||||
|
||||
在代码语义通顺和长度许可下,可以保持在同一行:
|
||||
|
||||
样例:
|
||||
|
||||
```js
|
||||
driver.elementByTagName('el1').should.become("123")
|
||||
.nodeify(done);
|
||||
|
||||
driver
|
||||
.elementsByTagName('el1').should.eventually.have.length(0)
|
||||
.nodeify(done);
|
||||
```
|
||||
|
||||
或者使用缩进来提高代码的可读性:
|
||||
|
||||
```js
|
||||
h.driver
|
||||
.elementById('comments')
|
||||
.clear()
|
||||
.click()
|
||||
.keys("hello world")
|
||||
.getValue()
|
||||
.should.become("hello world")
|
||||
.elementById('comments')
|
||||
.getValue().should.become("hello world")
|
||||
.nodeify(done);
|
||||
|
||||
h.driver
|
||||
.execute("'nan'--")
|
||||
.should.be.rejectedWith("status: 13")
|
||||
.nodeify(done);
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,85 @@
|
||||
## Appium 服务关键字
|
||||
|
||||
<expand_table>
|
||||
|
||||
|关键字|描述|实例|
|
||||
|----|-----------|-------|
|
||||
|`automationName`|你想使用的自动化测试引擎|`Appium` (默认) 或 `Selendroid`|
|
||||
|`platformName`|你要测试的手机操作系统|`iOS`, `Android`, 或 `FirefoxOS`|
|
||||
|`platformVersion`|手机操作系统版本|例如: `7.1`, `4.4`|
|
||||
|`deviceName`|使用的手机类型或模拟器类型|`iPhone Simulator`, `iPad Simulator`, `iPhone Retina 4-inch`, `Android Emulator`, `Galaxy S4`, 等。在 iOS 上,这个关键字的值必须是使用 `instruments -s devices` 得到的可使用的设备名称之一。在 Android 上,这个关键字目前不起作用。|
|
||||
|`app`|`.ipa` or `.apk`文件所在的本地绝对路径或者远程路径,也可以是一个包括两者之一的`.zip`。 Appium会先尝试安装路径对应的应用在适当的真机或模拟器上。针对Android系统,如果你指定`app-package`和`app-activity`(具体见下面)的话,那么就可以不指定`app`。 **会与 `browserName` 冲突** |比如`/abs/path/to/my.apk`或`http://myapp.com/app.ipa`|
|
||||
|`browserName`|需要进行自动化测试的手机 web 浏览器名称。如果是对应用进行自动化测试,这个关键字的值应为空。|iOS 系统上可以用 'Safari' ,Android 系统上可以用 'Chrome', 'Chromium', 或 'Browser'。|
|
||||
|`newCommandTimeout`|设置命令超时时间,单位:秒。达到超时时间仍未接收到新的命令时 Appium 会假设客户端退出然后自动结束会话。|比如 `60`
|
||||
|`autoLaunch`|Appium是否需要自动安装和启动应用。默认值`true`|`true`, `false`|
|
||||
|`language`| (Sim/Emu-only) 设定模拟器 ( simulator / emulator ) 的语言。|如: `fr`|
|
||||
|`locale`| (Sim/Emu-only) 设定模拟器 ( simulator / emulator ) 的区域设置。|如: `fr_CA`|
|
||||
|`udid`| 连接的物理设备的唯一设备标识|如: `1ae203187fc012g`|
|
||||
|`orientation`| (Sim/Emu-only) 在一个设定的方向模式中开始测试|`LANDSCAPE` (横向) 或 `PORTRAIT` (纵向) |
|
||||
|`autoWebview`| 直接转换到 WebView 上下文。 默认值 `false`、|`true`, `false`|
|
||||
|`noReset`|不要在会话前重置应用状态。默认值`false`。|`true`, `false`|
|
||||
|`fullReset`|(iOS) 删除整个模拟器目录。(Android) 通过卸载——而不是清空数据——来重置应用状态。在 Android 上,这也会在会话结束后自动清除被测应用。默认值 `false`|`true`, `false`|
|
||||
|
||||
### Android特有
|
||||
|
||||
<expand_table>
|
||||
|
||||
|关键字|描述|实例|
|
||||
|----|-----------|-------|
|
||||
|`appActivity`| 你要从你的应用包中启动的 Android Activity 名称。它通常需要在前面添加 `.` (如:使用`.MainActivity` 而不是 `MainActivity`) |`MainActivity`, `.Settings`|
|
||||
|`appPackage`| 你想运行的Android应用的包名|比如`com.example.android.myApp`, `com.android.settings`|
|
||||
|`appWaitActivity`| 你想要等待启动的 Android Activity 名称|`SplashActivity`|
|
||||
|`deviceReadyTimeout`| 设置等待一个模拟器或真机准备就绪的超时时间|`5`|
|
||||
|`androidCoverage`| 用于执行测试的 instrumentation 类。作为命令 `adb shell am instrument -e coverage true -w` 的 `-w` 参数。| `com.my.Pkg/com.my.Pkg.instrumentation.MyInstrumentation`|
|
||||
|`enablePerformanceLogging`| (仅适用于 Chrome 和 webview) 开启 Chromedriver 的性能日志。 (默认 `false`) | `true`, `false`|
|
||||
|`androidDeviceReadyTimeout`|等待设备在启动应用后准备就绪的超时时间。以秒为单位。|如 `30`|
|
||||
|`androidDeviceSocket`|开发工具的 socket 名称。只有在被测应用是一个使用 Chromium 内核的浏览器时需要。 socket 会被浏览器打开,然后 Chromedriver 把它作为开发者工具来进行连接。|如 `chrome_devtools_remote`|
|
||||
|`avd`| 需要启动的 AVD (安卓虚拟设备) 名称。|如 `api19`|
|
||||
|`avdLaunchTimeout`| 以毫秒为单位,等待 AVD 启动并连接到 ADB 的超时时间。(默认值 `120000`)| `300000`|
|
||||
|`avdReadyTimeout`| 以毫秒为单位,等待 AVD 完成启动动画的超时时间。(默认值 `120000`)| `300000`|
|
||||
|`avdArgs`| 启动 AVD 时需要加入的额外的参数。|如 `-netfast`|
|
||||
|`useKeystore`| 使用一个自定义的 keystore 来对 apk 进行重签名。默认值 `false`|`true` or `false`|
|
||||
|`keystorePath`| 自定义 keystore 的路径。默认: ~/.android/debug.keystore|如 `/path/to.keystore`|
|
||||
|`keystorePassword`| 自定义 keystore 的密码。|如 `foo`|
|
||||
|`keyAlias`| key 的别名 |如 `androiddebugkey`|
|
||||
|`keyPassword`| key 的密码 |如 `foo`|
|
||||
|`chromedriverExecutable`| webdriver 可执行文件的绝对路径 (如果 Chromium 核心提供了对应的 webdriver, 应该用它代替 Appium 自带的 webdriver) |`/abs/path/to/webdriver`|
|
||||
|`autoWebviewTimeout`| 以毫秒为单位,等待 Webview 上下文激活的时间。默认值 `2000`| 如 `4`|
|
||||
|`intentAction`| 用于启动 activity 的 intent action。 (默认值 `android.intent.action.MAIN`)| 如 `android.intent.action.MAIN`, `android.intent.action.VIEW`|
|
||||
|`intentCategory`| 用于启动 activity 的 intent category。 (默认值 `android.intent.category.LAUNCHER`) | 如 `android.intent.category.LAUNCHER`, `android.intent.category.APP_CONTACTS`
|
||||
|`intentFlags`| 用于启动 activity 的标识 ( flags ) (默认值 `0x10200000`) | 如 `0x10200000`
|
||||
|`optionalIntentArguments`| 用于启动 activity 的额外 intent 参数。请查看 [Intent 参数](http://developer.android.com/tools/help/adb.html#IntentSpec) | 如 `--esn <EXTRA_KEY>`, `--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE>`
|
||||
|`stopAppOnReset`| 在使用 adb 启动应用前停止被测应用的进程 ( process ) 。如果被测应用是被另一个应用创建的,当这个参数被设定为 false 时,允许另一个应用的进程在使用 adb 启动被测应用时继续存活。默认值 `true`| `true` 或 `false`|
|
||||
|`unicodeKeyboard`| 使用 Unicode 输入法。默认值 `false`| `true` 或 `false`|
|
||||
|`resetKeyboard`| 在设定了 `unicodeKeyboard` 关键字的 Unicode 测试结束后,重置输入法到原有状态。如果单独使用,将会被忽略。默认值 `false`| `true` 或 `false`|
|
||||
|`noSign`| 跳过检查和对应用进行 debug 签名的步骤。只能在使用 UiAutomator 时使用,使用 selendroid 是不行。默认值 `false` | `true` 或 `false`|
|
||||
|`ignoreUnimportantViews`| 调用 uiautomator 的函数 `setCompressedLayoutHierarchy()`。由于 Accessibility 命令在忽略部分元素的情况下执行速度会加快,这个关键字能加快测试执行的速度。被忽略的元素将不能够被找到,因此这个关键字同时也被实现成可以随时改变的 *设置 ( settings ) * 。默认值 `false` | `true` 或 `false`
|
||||
|
||||
### iOS特有
|
||||
|
||||
<expand_table>
|
||||
|
||||
|关键字|描述|实例|
|
||||
|----|-----------|-------|
|
||||
|`calendarFormat`| (Sim-only) 为iOS的模拟器设置日历格式|如 `gregorian` (公历) |
|
||||
|`bundleId`| 被测应用的 bundle ID 。用于在真实设备中启动测试,也用于使用其他需要 bundle ID 的关键字启动测试。在使用 bundle ID 在真实设备上执行测试时,你可以不提供 `app` 关键字,但你必须提供 `udid` 。|如 `io.appium.TestApp`|
|
||||
|`udid`| 连接的真实设备的唯一设备编号 ( Unique device identifier ) |如 `1ae203187fc012g`|
|
||||
|`launchTimeout`| 以毫秒为单位,在 Appium 运行失败之前设置一个等待 instruments 的时间 |比如: `20000`|
|
||||
|`locationServicesEnabled`| (Sim-only) 强制打开或关闭定位服务。默认值是保持当前模拟器的设定|`true` 或 `false`|
|
||||
|`locationServicesAuthorized`| (Sim-only) 通过修改 plist 文件设定是否允许应用使用定位服务,从而避免定位服务的警告出现。默认值是保持当前模拟器的设定。请注意在使用这个关键字时,你同时需要使用 `bundleId` 关键字来发送你的应用的 bundle ID。|`true` 或者 `false`|
|
||||
|`autoAcceptAlerts`| 当 iOS 的个人信息访问警告 (如 位置、联系人、图片) 出现时,自动选择接受( Accept )。默认值 `false`。|`true` 或者 `false`|
|
||||
|`autoDismissAlerts`| 当 iOS 的个人信息访问警告 (如 位置、联系人、图片) 出现时,自动选择不接受( Dismiss )。默认值 `false`。|`true` 或者 `false`|
|
||||
|`nativeInstrumentsLib`| 使用原生 intruments 库 (即关闭 instruments-without-delay ) |`true` 或者 `false`|
|
||||
|`nativeWebTap`| (Sim-only) 在Safari中允许"真实的",非基于 javascript 的 web 点击 (tap) 。 默认值: `false`。注意:取决于 viewport 大小/比例, 点击操作不一定能精确地点中对应的元素。|`true` 或者 `false`|
|
||||
|`safariInitialUrl`| (Sim-only) (>= 8.1) 初始化 safari 的时使用的地址。默认是一个本地的欢迎页面 | 如 `https://www.github.com` |
|
||||
|`safariAllowPopups`| (Sim-only) 允许 javascript 在 Safari 中创建新窗口。默认保持模拟器当前设置。|`true` 或者 `false`|
|
||||
|`safariIgnoreFraudWarning`| (Sim-only) 阻止 Safari 显示此网站可能存在风险的警告。默认保持浏览器当前设置。|`true` 或者 `false`|
|
||||
|`safariOpenLinksInBackground`| (Sim-only) Safari 是否允许链接在新窗口打开。默认保持浏览器当前设置。|`true` 或者 `false`|
|
||||
|`keepKeyChains`| (Sim-only) 当 Appium 会话开始/结束时是否保留存放密码存放记录 (keychains) (库(Library)/钥匙串(Keychains)) |`true` 或者 `false`|
|
||||
|`localizableStringsDir`| 从哪里查找本地化字符串。默认值 `en.lproj`|`en.lproj`|
|
||||
|`processArguments`| 通过 instruments 传递到 AUT 的参数 |如 `-myflag`|
|
||||
|`interKeyDelay`| 以毫秒为单位,按下每一个按键之间的延迟时间。|如 `100`|
|
||||
|`showIOSLog`| 是否在 Appium 的日志中显示设备的日志。默认值 `false`|`true` 或者 `false`|
|
||||
|`sendKeyStrategy`| 输入文字到文字框的策略。模拟器默认值:`oneByOne` (一个接着一个) 。真实设备默认值:`grouped` (分组输入) |`oneByOne`, `grouped` 或 `setValue`|
|
||||
|`screenshotWaitTimeout`| 以秒为单位,生成屏幕截图的最长等待时间。默认值: 10。 |如 `5`|
|
||||
|`waitForAppScript`| 用于判断 "应用是否被启动” 的 iOS 自动化脚本代码。默认情况下系统等待直到页面内容非空。结果必须是布尔类型。 |例如 `true;`, `target.elements().length > 0;`, `$.delay(5000); true;` |
|
||||
@@ -0,0 +1,39 @@
|
||||
## 元素定位与交互
|
||||
|
||||
Appium支持webdriver定位策略的子集
|
||||
|
||||
* 根据"class"定位(例如, UI组件类型)
|
||||
* 根据"xpath"定位 (例如,具有一定约束的路径抽象标示, 基于XPath方式)
|
||||
|
||||
另外, Appium 还支持部分 [Mobile JSON 连接协议](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md) 的定位策略
|
||||
|
||||
* `ios uiautomation`: 一个递归地、对应使用 [UIAutomation library](ios_predicate.cn.md) 搜索元素的字符串(iOS-only)
|
||||
* `android uiautomator`: 一个递归地、对应使用 [UiAutomator Api](uiautomator_uiselector.cn.md)搜索元素的字符串 (Android-only)
|
||||
* `accessibility id`: 一个递归地、使用本地Accessibility选项实现的Id/Name进行元素搜索的字符串。
|
||||
|
||||
### 存在的问题
|
||||
|
||||
如果遇到定位元素变得无效请联系并告知我们。我们将会努力修复
|
||||
|
||||
### 使用Appium Inspector来定位元素
|
||||
|
||||
(翻译备注: 这个工具目前只有Mac版本, 如果你使用的是windows, 可以使用android sdk自带的 uiautomatorviewer 工具来获得元素的位置)
|
||||
|
||||
Appium提供了一个灵活的工具Appium Inspector, 允许你在app运行的时候, 直接定位你正在关注的元素. 通过Appium Inspector(靠近start test按钮的小"i"按钮), 你可以通过点击预览窗口上的控件来获得它的name属性, 或者直接在UI导航窗口中定位
|
||||
|
||||
#### 概述
|
||||
|
||||
Appium Inspector有一个简单的布局, 全部由如下窗口组成.
|
||||
UI导航器, 预览, 录制与刷新按钮, 和交互工具
|
||||
|
||||

|
||||
|
||||
#### 例子
|
||||
|
||||
启动Appium Inspector后(通过点击app右上的小"i"按钮), 你可以定位任何预览窗口中的元素. 作为测试, 我正在查找id为"show alert"的按钮
|
||||
|
||||

|
||||
|
||||
要找到这个按钮的id, 在定位预览窗口中我点击了"show alert"按钮, Appium Inspector在UI导航窗口中高亮显示了这个元素, 然后展示了刚被点击按钮的id和元素类型
|
||||
|
||||

|
||||
@@ -0,0 +1,246 @@
|
||||
## iOS 谓词(Predicate)
|
||||
|
||||
在查看 *'-ios uiautomation'* 搜索策略时了解 **谓词(Predicate)** 十分必要。 [UIAutomation JavaScript API](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/)有下列几种非常有用的方法:
|
||||
|
||||
```center
|
||||
(UIAElement) UIAElementArray.firstWithPredicate(PredicateString predicateString)
|
||||
(UIAElementArray) UIAElementArray.withPredicate(PredicateString predicateString)
|
||||
```
|
||||
|
||||
原生的JS搜索策略(由Apple提供)提供了更大的灵活性,并且和XPath很像。
|
||||
**[谓词(Predicate)](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/predicates.html)** 可以通过使用多个匹配条件来准确定位某一个或某一组元素(相当于只有搜索条件与元素的计算结果为 true 时这些元素才会被认为是匹配的)。
|
||||
|
||||
(翻译备注:XPath 是一门用来定位 xml 文档中的元素的语言,能提供基于路径、元素属性等条件的定位策略)
|
||||
|
||||
例如:
|
||||
|
||||
```java
|
||||
// java
|
||||
appiumDriver.findElementsByIosUIAutomation("collectionViews()[0].cells().withPredicate(\"ANY staticTexts.isVisible == TRUE\")")
|
||||
```
|
||||
|
||||
\- 将只选择那些在主视图第一个 ```UIACollectionView``` 元素下的、拥有可见子元素 ```UIAStaticText``` 的 ```UIACollectionCell``` 元素。在这里, ```staticTexts()``` 和 ```isVisible()``` 分别是```UIAElementArray``` 和 ```UIAElement``` 的子方法。 **注意: ```UIAElementArray``` 序列编号从 ```0``` 开始,而不是像 Xpath 那样从 ```1```开始**
|
||||
|
||||
以下是所有可用的谓词(Predicate)的列表(主要取自 [谓词(Predicate) 编程指南](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/predicates.html))
|
||||
|
||||
### 基本比较
|
||||
|
||||
= , ==
|
||||
- 左边表达式等于右边表达式:
|
||||
```javascript
|
||||
tableViews()[1].cells().firstWithPredicate("label == 'Olivia' ")
|
||||
|
||||
same in Xpath: /UIATableView[2]/UIATableCell[@label = 'Olivia'][1]
|
||||
```
|
||||
|
||||
\>= , =\>
|
||||
- 左边表达式大于或等于右边表达式。
|
||||
|
||||
<= , =<
|
||||
- 左边表达式小于或等于右边表达式。
|
||||
|
||||
\>
|
||||
- 左边表达式大于右边表达式。
|
||||
|
||||
<
|
||||
- 左边表达式小于右边表达式。
|
||||
|
||||
!= , <\>
|
||||
- 左边表达式不等于右边表达式。
|
||||
|
||||
BETWEEN
|
||||
- 左边表达式的值在右边表达式的两个边界值之间或等于其中一个边界值。右边表达式为一个有两个值的数组,数组的第一个值是上限,第二个值是下限(这个顺序是固定的) ,例如 ```1 BETWEEN { 0 , 33 }```, 或者 ```$INPUT BETWEEN { $LOWER, $UPPER }```。
|
||||
在 Objective-C, 你可以创建一个自定义的 BETWEEN 谓词(Predicate),如下面的示例所示:
|
||||
|
||||
```center
|
||||
NSPredicate *betweenPredicate =
|
||||
[NSPredicate predicateWithFormat: @"attributeName BETWEEN %@", @[@1, @10]];
|
||||
```
|
||||
|
||||
这创建了一个等价于 ```( ( 1 <= attributeValue ) && ( attributeValue <= 10 ) )``` 的谓词
|
||||
|
||||
### 布尔值谓词
|
||||
|
||||
TRUEPREDICATE
|
||||
- 计算结果恒等于 ```TRUE``` 。
|
||||
|
||||
FALSEPREDICATE
|
||||
- 计算结果恒等于 ```FALSE```。
|
||||
|
||||
### 基本的复合谓词
|
||||
|
||||
AND , &&
|
||||
- 逻辑与。
|
||||
|
||||
OR , ||
|
||||
- 逻辑或。
|
||||
|
||||
NOT , !
|
||||
- 逻辑非。
|
||||
|
||||
### 字符串比较
|
||||
|
||||
在默认情况下,字符串比较是区分大小写和音调( diacritic )的,你可以在方括号中用关键字符 ```c``` 和 ```d``` 来修改操作符以相应的指定不区分大小写和变音符号。例如 名字的开头 ```firstName BEGINSWITH[cd] $FIRST_NAME```
|
||||
|
||||
(翻译备注:这里的音调是指英文字母的音调,如 `"náive"` 和 `"naive"`。如果不加关键字 `d`,这两个字符串会认为是不等价的。)
|
||||
|
||||
BEGINSWITH
|
||||
- 左边的表达式以右边的表达式作为开始。
|
||||
|
||||
```center
|
||||
scrollViews()[3].buttons().firstWithPredicate("name BEGINSWITH 'results toggle' ")
|
||||
|
||||
same in Xpath: /UIAScrollView[4]/UIAButton[starts-with(@name, 'results toggle')][1]
|
||||
```
|
||||
|
||||
CONTAINS
|
||||
- 左边的表达式包含右边的表达式。
|
||||
|
||||
```center
|
||||
tableViews()[1].cells().withPredicate("ANY collectionViews[0].buttons.name CONTAINS 'opera'")
|
||||
|
||||
same in Xpath: /UIATableView[2]/UIATableCell[UIACollectionView[1]/UIAButton[contains(@name, 'opera')]]
|
||||
```
|
||||
|
||||
ENDSWITH
|
||||
- 左边的表达式以右边的表达式作为结束。
|
||||
|
||||
LIKE
|
||||
- 左边表达式等于右边表达式: ? 和 *可作为通配符, 其中 ? 匹配 1 个字符, * 匹配 0 个或者多个字符。 在 Mac OS X v10.4, 通配符不能匹配换行符。
|
||||
|
||||
```center
|
||||
tableViews()[0].cells().firstWithPredicate("name LIKE '*Total: $*' ")
|
||||
|
||||
same in Xpath: /UIATableView[1]/UIATableCell[matches(@name, '.*Total: \$.*')][1]
|
||||
```
|
||||
|
||||
MATCHES
|
||||
- 左边表达式根据ICU v3的正则表达式风格比较,等于右边表达式 (详情请看ICU用户指南中的 [正则表达式](http://userguide.icu-project.org/strings/regexp))。
|
||||
|
||||
```center
|
||||
tableViews().firstWithPredicate("value MATCHES '.*of 7' ")
|
||||
|
||||
same in Xpath: /UIATableView[matches(@value, '.*of 7')][1]
|
||||
```
|
||||
|
||||
### 聚合操作
|
||||
|
||||
ANY , SOME
|
||||
- 指定匹配后续表达式的任意元素。例如 ```ANY children.age < 18``` 。
|
||||
|
||||
```center
|
||||
tableViews()[0].cells().firstWithPredicate("SOME staticTexts.name = 'red'").staticTexts().withName('red')
|
||||
|
||||
same in Xpath: /UIATableView[1]/UIATableCell[UIAStaticText/@name = 'red'][1]/UIAStaticText[@name = 'red']
|
||||
```
|
||||
|
||||
ALL
|
||||
- 指定匹配后续表达式的所有元素。例如 ```ALL children.age < 18``` 。
|
||||
|
||||
NONE
|
||||
- 指定不匹配后续表达式的元素。例如 ```NONE children.age < 18``` 。 逻辑上等价于 ```NOT (ANY ...)``` 。
|
||||
|
||||
IN
|
||||
- 等价于 SQL 的 IN 操作,左边的表达必须出现在右边指定的集合中。例如 ```name IN { 'Ben', 'Melissa', 'Matthew' }``` 。 这个集合可以是一个数组( array ),一个列表( set ), 或者一个字典( dictionary )。当这个集合是字典时,这里使用的是它的值( value )。
|
||||
|
||||
array[index]
|
||||
- 指定数组中特定索引处的元素。
|
||||
|
||||
array[FIRST]
|
||||
- 指定数组中的第一个元素。
|
||||
|
||||
array[LAST]
|
||||
- 指定数组中的最后一个元素。
|
||||
|
||||
array[SIZE]
|
||||
- 指定数组的大小
|
||||
```center
|
||||
elements()[0].tableViews()[0].cells().withPredicate("staticTexts[SIZE] > 2")
|
||||
|
||||
same in Xpath: /*[1]/UIATableView[1]/UIATableCell[count(UIAStaticText) > 2]
|
||||
```
|
||||
|
||||
### 标识符
|
||||
|
||||
**C语言标识符**
|
||||
- 任何C语言的标识符都不是保留字。
|
||||
|
||||
**\#symbol**
|
||||
- 用来把一个保留字转义为用户标识符。
|
||||
|
||||
**[\\]{octaldigit}{3}**
|
||||
- 用来表示一个八进制数 ( ```\```后面加上3位八进制数字)。
|
||||
|
||||
**[\\][xX]{hexdigit}{2}**
|
||||
- 用于表示十六进制数 ( ```\x``` 或 ```\X``` 后面加上2个十六进制数字)。
|
||||
|
||||
**[\\][uU]{hexdigit}{4}**
|
||||
- 用于表示 Unicode 编码 ( ```\u``` 或 ```\U``` 后面加上4个十六进制数字)。
|
||||
|
||||
### 文字 (Literals)
|
||||
|
||||
(翻译备注:Literals 在编程语言领域的意思是在代码中可以看得到的(或说可视的)那些值。例如字符串 `"a"`,数组 `[1, 2]`,你可以在代码中一眼看出这是一个字符串,数组还是别的数据类型并知道它的值。这一节说的就是这些值的写法)
|
||||
|
||||
单引号和双引号都能产生相同的结果,但他们不会匹配对方(单引号不会匹配双引号)。例如:```"abc"``` and ```'abc'``` 都是可识别的 ,但是 ```"a'b'c"``` 等价于```a, 'b', c```。
|
||||
|
||||
FALSE , NO
|
||||
- 表示逻辑上的 false。
|
||||
|
||||
TRUE , YES
|
||||
- 表示逻辑上的 true。
|
||||
|
||||
NULL , NIL
|
||||
- 空值。
|
||||
|
||||
SELF
|
||||
- 代表被使用的对象本身。
|
||||
|
||||
"text"
|
||||
- 一个字符串。
|
||||
|
||||
'text'
|
||||
- 同上,也是一个字符串。
|
||||
|
||||
**以逗号分隔的文本数组**
|
||||
- 举个例子 ```{ 'comma', 'separated', 'literal', 'array' }``` 。
|
||||
|
||||
**标准的整数和小数**
|
||||
- 举个例子 ```1 , 27 , 2.71828 , 19.75``` 。
|
||||
|
||||
**带有幂指数的小数**
|
||||
- 举个例子 ```9.2e-5``` 。
|
||||
|
||||
0x
|
||||
- 十六进制数的前缀, 如`0x11`表示十六进制数11,等同于十进制的17。
|
||||
|
||||
0o
|
||||
- 八进制数的前缀。
|
||||
|
||||
0b
|
||||
- 二进制数的前缀。
|
||||
|
||||
### 保留字
|
||||
|
||||
下面的都是保留字:
|
||||
|
||||
`AND, OR, IN, NOT, ALL, ANY, SOME, NONE, LIKE, CASEINSENSITIVE, CI, MATCHES, CONTAINS, BEGINSWITH, ENDSWITH, BETWEEN, NULL, NIL, SELF, TRUE, YES, FALSE, NO, FIRST, LAST, SIZE, ANYKEY, SUBQUERY, CAST, TRUEPREDICATE, FALSEPREDICATE`
|
||||
|
||||
### Appium 谓词(predicate)帮助文档
|
||||
|
||||
Appium 在app.js中有 [专门的谓词(predicate)使用帮助文档](https://github.com/appium/appium-uiauto/blob/3052dace828db2ab3d722281fb7853cbcbc3252f/uiauto/appium/app.js#L68) :
|
||||
|
||||
- `getFirstWithPredicate`
|
||||
- `getFirstWithPredicateWeighted`
|
||||
- `getAllWithPredicate`
|
||||
- `getNameContains`
|
||||
|
||||
如下是个Ruby的例子
|
||||
|
||||
```ruby
|
||||
# Ruby example
|
||||
text = 'Various uses'
|
||||
predicate = "name contains[c] '#{text}' || label contains[c] '#{text}' || value contains[c] '#{text}'"
|
||||
element = execute_script(%Q(au.mainApp().getFirstWithPredicate("#{predicate}");))
|
||||
|
||||
puts element.name # Buttons, Various uses of UIButton
|
||||
```
|
||||
@@ -0,0 +1,243 @@
|
||||
## 自动化手机网页应用
|
||||
|
||||
如果你正对于如何在iOS的Safari或Android上的Chrome做网页应用的自动化感兴趣,
|
||||
那么Appium能够帮助你。基本上,你可以正常的写webdriver测试,只需要把Appium当
|
||||
成一个有特殊设置的selenium Server。
|
||||
|
||||
### iOS模拟器上的Safari浏览器
|
||||
|
||||
首先,要确保你的Safari浏览器参数中开启了开发者模式,这样Safari的远程调试端口也会被同时打开。
|
||||
|
||||
不管你使用模拟器还是真机,你必须使用Appium开始之前先开启Safari。
|
||||
|
||||
然后设置如下显示的这些信息以便于在设备中的Safari执行测试:
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
{
|
||||
platformName: 'iOS'
|
||||
, platformVersion: '7.1'
|
||||
, browserName: 'Safari'
|
||||
, deviceName: 'iPhone Simulator'
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
# python
|
||||
{
|
||||
'platformName': 'iOS',
|
||||
'platformVersion': '7.1',
|
||||
'browserName': 'Safari',
|
||||
'deviceName': 'iPhone Simulator'
|
||||
}
|
||||
```
|
||||
|
||||
```php
|
||||
// php
|
||||
public static $browsers = array(
|
||||
array(
|
||||
'desiredCapabilities' => array(
|
||||
'platformName' => 'iOS',
|
||||
'platformVersion' => '7.1',
|
||||
'browserName' => 'Safari',
|
||||
'deviceName' => 'iPhone Simulator'
|
||||
)
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
```java
|
||||
// java
|
||||
DesiredCapabilities capabilities = new DesiredCapabilities();
|
||||
capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "iOS");
|
||||
capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "7.1");
|
||||
capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "Safari");
|
||||
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone Simulator");
|
||||
```
|
||||
|
||||
### iOS真机上的Safari浏览器
|
||||
|
||||
为了能够在真机上的Safari执行测试,我们使用了[SafariLauncher App](https://github.com/snevesbarros/SafariLauncher)来启动Safari。
|
||||
一旦Safari被启动,则使用[ios-webkit-webkit-proxy](https://github.com/google/ios-webkit-debug-proxy)来自动启动Safari的远程调试功能。
|
||||
|
||||
**提示:** 目前在ios-webkit-debug-proxy中有一个[问题](https://github.com/google/ios-webkit-debug-proxy/issues/38)。
|
||||
你必须添加信任才能开始运行ios-webkit-debug-proxy。
|
||||
|
||||
### 前期设置
|
||||
|
||||
当你要在真机上的Safari中执行你的测试脚本之前你需要先注意以下几点:
|
||||
|
||||
* 安装并运行 **ios-webkit-debug-proxy**,并监听27753端口 (具体可以参考([hybrid docs](../advanced-concepts/hybrid.cn.md))
|
||||
* 打开iOS真机中的 **web inspector**,可以在iOS6.0或更高版本中的 **设置 > safari > 高级**找到。
|
||||
* 创建一个 **provisioning profile** 能够帮助你配置safariLauncher。
|
||||
|
||||
你可以前往 **Apple Developers Member Center** 创建一个launcher profile:
|
||||
* **第一步:** 创建一个 **新的App Id** 同时设置WildCard App ID这个选项置为"*"
|
||||
* **第二步:** 为步骤1的App Id创建一个 **new Development Profile** 。
|
||||
* **第三步:** 选择你的 **certificate(s) and device(s)** 并选择下一步。
|
||||
* **第四步:** 设置profile的名称以及 **generate the profile**。
|
||||
* **第五步:** 下载profile并使用文本编辑器打开。
|
||||
* **第六步:** 寻找并牢记你的 **UUID**
|
||||
|
||||
现在你有了自己的profile文件,可以在终端中输入如下的命令:
|
||||
|
||||
```center
|
||||
$ git clone https://github.com/appium/appium.git
|
||||
$ cd appium
|
||||
|
||||
# 选项1:你可以不设置任何的参数。appium会把签名 (code signing identity) 设为'iPhone Developer'
|
||||
$ ./reset.sh --ios --real-safari
|
||||
|
||||
# 选项2:你需要定义code signing identity并且允许xcode选择profile identity code
|
||||
$ ./reset.sh --ios --real-safari --code-sign '<code signing idendity>'
|
||||
|
||||
# 选项3:你需要设置<code signing idendity>和<profile identity code>
|
||||
$ ./reset.sh --ios --real-safari --code-sign '<code signing idendity>' --profile '<retrieved profile identity code>'
|
||||
|
||||
# 设置成功之后,就可以像往常一样启动服务
|
||||
$ node /lib/server/main.js -U <UDID>
|
||||
```
|
||||
|
||||
### 执行测试
|
||||
如果要在safari下的运行你的测试, 只需要简单的配置**"browserName"**为safari即可
|
||||
|
||||
|
||||
### Java 范例
|
||||
|
||||
```java
|
||||
// java
|
||||
// 配置web driver并启动webview应用
|
||||
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
|
||||
desiredCapabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "Safari");
|
||||
URL url = new URL("http://127.0.0.1:4723/wd/hub");
|
||||
AppiumDriver driver = new AppiumDriver(url, desiredCapabilities);
|
||||
|
||||
// 跳转到指定页面并在该页面所以用元素id进行交互
|
||||
driver.get("http://saucelabs.com/test/guinea-pig");
|
||||
WebElement div = driver.findElement(By.id("i_am_an_id"));
|
||||
Assert.assertEquals("I am a div", div.getText()); //跳转到指定页面并在该页面所以用元素id进行交互
|
||||
driver.findElement(By.id("comments")).sendKeys("My comment"); //通过id查找评论框并输入
|
||||
|
||||
// 关闭应用
|
||||
driver.quit();
|
||||
```
|
||||
|
||||
### Python 范例
|
||||
|
||||
```python
|
||||
# python
|
||||
# 配置web driver并启动webview应用
|
||||
capabilities = { 'browserName': 'Safari' }
|
||||
driver = webdriver.Remote('http://localhost:4723/wd/hub', capabilities)
|
||||
|
||||
# 跳转到指定页面并在该页面所以用元素id进行交互
|
||||
driver.get('http://saucelabs.com/test/guinea-pig');
|
||||
div = driver.find_element_by_id('i_am_an_id')
|
||||
# 检查文本是否符合预期
|
||||
assertEqual('I am a div', div.text)
|
||||
|
||||
# 通过id查找评论框并输入
|
||||
driver.find_element_by_id('comments').send_keys('My comment')
|
||||
|
||||
# 关闭应用
|
||||
driver.quit()
|
||||
```
|
||||
|
||||
```php
|
||||
// php
|
||||
class ContextTests extends PHPUnit_Extensions_AppiumTestCase
|
||||
{
|
||||
public static $browsers = array(
|
||||
array(
|
||||
'desiredCapabilities' => array(
|
||||
'platformName' => 'iOS',
|
||||
'platformVersion' => '7.1',
|
||||
'browserName' => 'Safari',
|
||||
'deviceName' => 'iPhone Simulator'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
public function testThings()
|
||||
{
|
||||
$this->get('http://saucelabs.com/test/guinea-pig');
|
||||
|
||||
$div = $this->byId('i_am_an_id');
|
||||
$this->assertEquals('I am a div', $div->text());
|
||||
|
||||
$this->byId('comments')->sendKeys('My comment');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 在真机或模拟器上的Chrome执行测试
|
||||
|
||||
需要做的准备:
|
||||
|
||||
* 确认Chrome已经安装在了你的真机或模拟器上 (应用的包名是`com.android.chrome`) 。在不编译Chromium的情况下, 不可能得到模拟器上的x86版本的chrome,你可以运行一个ARM的模拟器然后从真机上获取一个Chrome的APK安装在模拟器上。
|
||||
* 如果你是使用[NPM](https://www.npmjs.org/package/appium)下载的,
|
||||
或者是在[.app](https://github.com/appium/appium-dot-app)运行的话,那你不需要其他额外的工作。如果你是使用源码运行,`reset`会下载ChromeDriver并放在`build`。
|
||||
使用 `--chromedriver-version` 选项可以指定chromedriver的版本 (例如 `./reset.sh --android --chromedriver-version 2.8`),
|
||||
否则使用最新版。
|
||||
|
||||
接着,像这样设置就可以在Chrome上执行测试了:
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
{
|
||||
platformName: 'Android'
|
||||
, platformVersion: '4.4'
|
||||
, deviceName: 'Android Emulator'
|
||||
, browserName: 'Chrome'
|
||||
};
|
||||
```
|
||||
|
||||
```python
|
||||
# python
|
||||
{
|
||||
'platformName': 'Android',
|
||||
'platformVersion': '4.4',
|
||||
'deviceName': 'Android Emulator',
|
||||
'browserName': 'Chrome'
|
||||
}
|
||||
```
|
||||
|
||||
```php
|
||||
// php
|
||||
public static $browsers = array(
|
||||
array(
|
||||
'desiredCapabilities' => array(
|
||||
'platformName' => 'Android',
|
||||
'platformVersion' => '4.4',
|
||||
'browserName' => 'Chrome',
|
||||
'deviceName' => 'Android Emulator'
|
||||
)
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
```java
|
||||
// java
|
||||
DesiredCapabilities capabilities = new DesiredCapabilities();
|
||||
capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
|
||||
capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "4.4");
|
||||
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
|
||||
capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "Chrome");
|
||||
```
|
||||
|
||||
在4.4以上的版本,你也可以用'Browser' `browserName` 来对内置浏览器进行自动化。
|
||||
在所有版本你都可以用'Chromium' `browserName`来对Chromium进行自动化。
|
||||
|
||||
|
||||
#### chromedriver故障排查
|
||||
|
||||
从Chrome 33开始,不再必须将设备root。在之前的版本,设备必须按要求进行root (ChromeDriver需要写 /data/local 目录来设定Chrome的命令行参数) 。
|
||||
|
||||
如果在版本33之前在Chrome上测试app,确保adb shell拥有设备中/data/local目录的读写权限:
|
||||
|
||||
```center
|
||||
$ adb shell su -c chmod 777 /data/local
|
||||
```
|
||||
|
||||
更多关于chromedriver的文档详见[ChromeDriver documentation](https://sites.google.com/a/chromium.org/chromedriver/getting-started/getting-started---android)。
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
## 调整网络设置
|
||||
|
||||
Selenium 的 [Mobile JSON Wire Protocol Specification](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md) 支持一个获取和设置设备网络连接的 [API](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md#104) 。这个 API 通过位掩码(bitmask)工作,把所有可能的状态用一个整型数据表示:
|
||||
|
||||
| 值 (别名) | 数据连接 | Wifi 连接 | 飞行模式 |
|
||||
| ------------------ | ---- | ---- | ------------- |
|
||||
| 0 (什么都没有) | 0 | 0 | 0 |
|
||||
| 1 (飞行模式) | 0 | 0 | 1 |
|
||||
| 2 (只有Wifi) | 0 | 1 | 0 |
|
||||
| 4 (只有数据连接) | 1 | 0 | 0 |
|
||||
| 6 (开启所有网络) | 1 | 1 | 0 |
|
||||
|
||||
翻译备注:数据链接即2g, 3g, 4g的网络连接。
|
||||
|
||||
### iOS
|
||||
|
||||
很不幸,目前 Appium 在 iOS 下不支持 Selenium 的网络连接 API。
|
||||
|
||||
### Android
|
||||
|
||||
选择你想使用的设置,然后根据上面的表格发送正确的位掩码(bitmask)。
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
// 设置网络连接为飞行模式
|
||||
driver.setNetworkConnection(1)
|
||||
|
||||
// 设置网络连接为仅启用Wifi
|
||||
driver.setNetworkConnection(2)
|
||||
|
||||
// 设置网络连接为仅启用数据连接
|
||||
driver.setNetworkConnection(4)
|
||||
|
||||
// 设置网络连接为启用数据连接和Wifi
|
||||
driver.setNetworkConnection(6)
|
||||
```
|
||||
|
||||
获取网络连接设置会返回基于同样规则的位掩码,你可以将其解码来获得网络设置。
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
driver.getNetworkConnection().then(function (connectionType) {
|
||||
switch (connectionType) {
|
||||
case 0:
|
||||
// 无网络
|
||||
break;
|
||||
case 1:
|
||||
// 飞行模式
|
||||
break;
|
||||
case 2:
|
||||
// wifi
|
||||
break;
|
||||
case 4:
|
||||
// 数据连接
|
||||
break;
|
||||
case 6:
|
||||
// wifi和数据连接
|
||||
break;
|
||||
}
|
||||
});
|
||||
```
|
||||
@@ -0,0 +1,246 @@
|
||||
# 执行测试
|
||||
|
||||
## 准备被测应用 (iOS)
|
||||
|
||||
在模拟器上测试apps必须要用模拟器专用的编译器,例如使用下列的命令来编译Xcode项目:
|
||||
|
||||
```
|
||||
> xcodebuild -sdk iphonesimulator6.0
|
||||
```
|
||||
|
||||
这行指令在Xcode项目底下创建了一个`build/Release-iphonesimulator`目录,并且生成一个可以透过Appium服务器来通讯的的`.app`封包。
|
||||
|
||||
如果需要,你可以把.app 目录压缩成一个zip压缩档! Appium 会自行解压缩。让你能方便在非本地运行Appium。
|
||||
|
||||
## 准备被测应用 (Android)
|
||||
|
||||
用Appium去执行你的.apk档其实没什么特别需要注意的事项。如果需要,你可以把它压缩成zip压缩档。
|
||||
|
||||
## 用Appium测试你的app (iOS)
|
||||
|
||||
想知道如何编写测试脚本,请参照测试范例:
|
||||
|
||||
[Node.js](https://github.com/appium/sample-code/tree/master/sample-code/examples/node) | [Python](https://github.com/appium/sample-code /tree/master/sample-code/examples/python) | [PHP](https://github.com/appium/sample-code/tree/master/sample-code/examples/php) | [Ruby](https://github.com/appium/sample-code/tree/master/sample-code/examples/ruby) | [Java](https://github.com/appium/sample-code/tree/master/sample-code/examples/java)
|
||||
|
||||
基本上来说,首先先确定你启动了Appium:
|
||||
|
||||
```
|
||||
node .
|
||||
```
|
||||
|
||||
然后执行你的WebDriver测试脚本,脚本必须包含下列的环境参数:
|
||||
```javascript
|
||||
// javascript
|
||||
{
|
||||
platformName: 'iOS',
|
||||
platformVersion: '7.1',
|
||||
deviceName: 'iPhone Simulator',
|
||||
app: myApp
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
# python
|
||||
{
|
||||
'platformName': 'iOS',
|
||||
'platformVersion': '7.1',
|
||||
'deviceName': 'iPhone Simulator',
|
||||
'app': myApp
|
||||
}
|
||||
```
|
||||
|
||||
```php
|
||||
// php
|
||||
public static $browsers = array(
|
||||
array(
|
||||
'desiredCapabilities' => array(
|
||||
'platformName' => 'iOS',
|
||||
'platformVersion' => '7.1',
|
||||
'deviceName' => 'iPhone Simulator',
|
||||
'app' => $myApp
|
||||
)
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
```java
|
||||
// java
|
||||
DesiredCapabilities capabilities = new DesiredCapabilities();
|
||||
capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "iOS");
|
||||
capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "7.1");
|
||||
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone Simulator");
|
||||
capabilities.setCapability(MobileCapabilityType.APP, myApp);
|
||||
```
|
||||
|
||||
在这个脚本集里,`myApp`必须是下列其中之一:
|
||||
|
||||
* 一个模拟器编译过的.app 目录或者.zip 文件的本地绝对路径
|
||||
* 一个包含着你的.app封包的zip档的url
|
||||
* appium安装根目录下的一个示例app的相对路径
|
||||
|
||||
在你选择的WebDriver库里,设定remote session使用上述的环境参数然后使用端口4723来连接本地服务器(或者使用你在Appium启动时所设定的端口)。现在你已经完成设置了!
|
||||
|
||||
## 用Appium测试你的app (Android)
|
||||
|
||||
首先,先确定你有一个而且必须是只能一个Android模拟器或者设备连接着。如果你输入`adb devices`,你应该只看到一个设备连接着。这将是Appium所用来测试的设备。当然,要连接一个设备,你需要准备好一个Android AVD (参考([Windows](../appium-setup/running-on-windows.cn.md),[Mac](../appium-setup/running-on-osx.cn.md),或者[Linux](../appium-setup/running-on-linux.cn.md))以了解更多)。 如果Android SDK工具在你的环境变量path下,你可以简单的执行:
|
||||
|
||||
```
|
||||
emulator -avd <我的Avd名称>
|
||||
```
|
||||
|
||||
然后等android模拟器启动。有时候,因为某些原因,`adb`会卡住。如果它没有显示任何的设备或其他故障,你可以使用下列指令来重启:
|
||||
|
||||
```
|
||||
adb kill-server && adb devices
|
||||
```
|
||||
|
||||
现在,确认Appium已经启动:
|
||||
|
||||
```
|
||||
node .
|
||||
```
|
||||
|
||||
有几种方法来启动一个Appium程序(效果和通过adb启动一模一样):
|
||||
|
||||
- 只有apk或者zip,默认activity将会被启动。 (只设置了'app'环境参数)
|
||||
- apk + activity ('app' + 'appActivity' 环境参数)
|
||||
- apk + activity + intent ('app' + 'appActivity' + 'appIntent' 环境参数)
|
||||
- ...
|
||||
|
||||
Activities 可以通过以下方式来指定:
|
||||
|
||||
- 名称 (如 appActivity: 'com.helloworld.SayHello')。
|
||||
- 相对于 appPackage的路径 (如 appPackage: 'com.helloworld', appActivity='.SayHello')
|
||||
|
||||
如果“appWaitPackage'和'appWaitActivity”被指定,Appium
|
||||
将自动等待,直到这些活动的被启动。你可以为实例指定多个等待的activity:
|
||||
|
||||
- appActivity: 'com.splash.SplashScreen'
|
||||
- appPackage: 'com.splash' appActivity: '.SplashScreen'
|
||||
- appPackage: 'com.splash' appActivity: '.SplashScreen,.LandingPage,com.why.GoThere'
|
||||
|
||||
如果你不是很清楚在apk中有哪些activity,你可以通过以下方式来查看:
|
||||
|
||||
- Mac/Linux: 'adb shell dumpsys window windows | grep mFocusedApp'
|
||||
- 在 Ruby 控制台运行: 'adb shell dumpsys window windows\`.each_line.grep(/mFocusedApp/).first.strip'
|
||||
- 在 Windows 终端运行 'adb shell dumpsys window windows' 然后去看mFocusedApp这一行的内容。
|
||||
|
||||
然后执行你的WebDriver测试脚本,脚本必须包含下列的环境参数:
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
{
|
||||
platformName: 'Android',
|
||||
platformVersion: '4.4',
|
||||
deviceName: 'Android Emulator',
|
||||
app: myApp
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
# python
|
||||
{
|
||||
'platformName': 'Android',
|
||||
'platformVersion': '4.4',
|
||||
'deviceName': 'Android Emulator',
|
||||
'app': myApp
|
||||
}
|
||||
```
|
||||
|
||||
```php
|
||||
// php
|
||||
public static $browsers = array(
|
||||
array(
|
||||
'desiredCapabilities' => array(
|
||||
'platformName' => 'Android',
|
||||
'platformVersion' => '4.4',
|
||||
'deviceName' => 'Android Emulator',
|
||||
'app' => $myApp
|
||||
)
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
```java
|
||||
// java
|
||||
DesiredCapabilities capabilities = new DesiredCapabilities();
|
||||
capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
|
||||
capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "4.4");
|
||||
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
|
||||
capabilities.setCapability(MobileCapabilityType.APP, myApp);
|
||||
```
|
||||
|
||||
在这个脚本集里,`myApp`必须是下列其中之一:
|
||||
|
||||
* 一个.apk 或者.zip 档的本地绝对路径
|
||||
* 一个包含着你的.apk档的zip压缩档的url
|
||||
* appium安装根目录下的一个示例app的路径
|
||||
|
||||
`myAppPackage` 必须是你的应用的java package,例如, `com.example.android.myApp`。
|
||||
|
||||
`myAppActivity` 必须是你的希望测试的Android activity, 例如, `MainActivity`。
|
||||
|
||||
在你选择的WebDriver库里,设定remote session使用上述的环境参数然后使用端口4723来连接本地服务器(或者是使用你在Appium启动时所设定的任意端口)。现在你已经设置完成了!
|
||||
|
||||
## 用Appium测试你的app (Android 设备 < 4.2, 以及混合app测试)
|
||||
|
||||
低于4.2版本的Android设备(API Level 17) 没有安装 Google 的[UiAutomator framework](http://developer.android.com/tools/help/uiautomator/index.html).下面的范例是早期Appium在这些设备上的测试方法。对于早期的设备以及使用混合模式(webview-based)制作的apps, Appium 包含了另一种自动化测试工具[Selendroid](http://selendroid.io/)。
|
||||
|
||||
要使用Selendroid, 只需要在之前提到的环境参数上稍作修改即可,添加 `automationName` 参数并指定Seledroid作为测试工具。通常你还需要在你的activity名称前加上`.` (如:在`appActivity`参数中使用`.MainActivity` 而不是 `MainActivity`) :
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
{
|
||||
automationName: 'Selendroid',
|
||||
platformName: 'Android',
|
||||
platformVersion: '2.3',
|
||||
deviceName: 'Android Emulator',
|
||||
app: myApp,
|
||||
appPackage: 'com.mycompany.package',
|
||||
appActivity: '.MainActivity'
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
# python
|
||||
{
|
||||
'automationName': 'Selendroid',
|
||||
'platformName': 'Android',
|
||||
'platformVersion': '2.3',
|
||||
'deviceName': 'Android Emulator',
|
||||
'app': myApp,
|
||||
'appPackage': 'com.mycompany.package',
|
||||
'appActivity': '.MainActivity'
|
||||
}
|
||||
```
|
||||
|
||||
```php
|
||||
// php
|
||||
public static $browsers = array(
|
||||
array(
|
||||
'desiredCapabilities' => array(
|
||||
'automationName' => 'Selendroid',
|
||||
'platformName' => 'Android',
|
||||
'platformVersion' => '2.3',
|
||||
'deviceName' => 'Android Emulator',
|
||||
'app' => $myApp,
|
||||
'appPackage' => 'com.mycompany.package',
|
||||
'appActivity'=> '.MainActivity'
|
||||
)
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
```java
|
||||
// java
|
||||
DesiredCapabilities capabilities = new DesiredCapabilities();
|
||||
capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "Selendroid");
|
||||
capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
|
||||
capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "2.3");
|
||||
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
|
||||
capabilities.setCapability(MobileCapabilityType.APP, myApp);
|
||||
capabilities.setCapability(MobileCapabilityType.APP_PACKAGE: "com.mycompany.package");
|
||||
capabilities.setCapability(MobileCapabilityType.APP_ACTIVITY: ".MainActivity");
|
||||
```
|
||||
|
||||
这样Appium就会启动 Selendroid 测试会话取代默认的测试会话。使用Selendroid的缺点是有时候它的API跟Appium非常不同。所以我们建议你在为你的旧设备或者混合app写测试脚本之前先仔细的阅读[Selendroid的说明文档](http://selendroid.io/native.html)。
|
||||
@@ -0,0 +1,85 @@
|
||||
# Appium 服务器参数
|
||||
|
||||
使用方法: `node . [标志]`
|
||||
|
||||
## 服务器标志
|
||||
所有的标志都是可选的,但是有一些标志需要组合在一起才能生效。
|
||||
|
||||
|
||||
|
||||
<expand_table>
|
||||
|
||||
|标志|默认值|描述|例子|
|
||||
|----|-------|-----------|-------|
|
||||
|`--shell`|null|进入 REPL 模式||
|
||||
|`--localizable-strings-dir`|en.lproj|IOS only: 定位 .strings所在目录的相对路径 |`--localizable-strings-dir en.lproj`|
|
||||
|`--app`|null|iOS: 基于模拟器编译的 app 的绝对路径或者设备目标的 bundle_id; Android: apk 文件的绝对路径`--app /abs/path/to/my.app`|
|
||||
|`--ipa`|null|(IOS-only) .ipa 文件的绝对路径|`--ipa /abs/path/to/my.ipa`|
|
||||
|`-U`, `--udid`|null|连接物理设备的唯一设备标识符|`--udid 1adsf-sdfas-asdf-123sdf`|
|
||||
|`-a`, `--address`|0.0.0.0|监听的 ip 地址|`--address 0.0.0.0`|
|
||||
|`-p`, `--port`|4723|监听的端口|`--port 4723`|
|
||||
|`-ca`, `--callback-address`|null|回调IP地址 (默认: 相同的IP地址)|`--callback-address 127.0.0.1`|
|
||||
|`-cp`, `--callback-port`|null|回调端口号 (默认: 相同的端口号)|`--callback-port 4723`|
|
||||
|`-bp`, `--bootstrap-port`|4724|(Android-only) 连接设备的端口号|`--bootstrap-port 4724`|
|
||||
|`-k`, `--keep-artifacts`|false|弃用,无效。trace信息现在保留tmp目录下,每次运行前会清除该目录中的信息。 也可以参考 --trace-dir 。||
|
||||
|`-r`, `--backend-retries`|3|(iOS-only) 遇到 crash 或者 超时,Instrument 重新启动的次数。|`--backend-retries 3`|
|
||||
|`--session-override`|false|允许 session 被覆盖 (冲突的话)||
|
||||
|`--full-reset`|false|(iOS) 删除整个模拟器目录。 (Android) 通过卸载应用(而不是清除数据)重置应用状态。在 Android 上,session 完成后也会删除应用。||
|
||||
|`--no-reset`|false|session 之间不重置应用状态 (iOS: 不删除应用的 plist 文件; Android: 在创建一个新的 session 前不删除应用。)||
|
||||
|`-l`, `--pre-launch`|false|在第一个 session 前,预启动应用 (iOS 需要 --app 参数,Android 需要 --app-pkg 和 --app-activity)||
|
||||
|`-lt`, `--launch-timeout`|90000|(iOS-only) 等待 Instruments 启动的时间||
|
||||
|`-g`, `--log`|null|将日志输出到指定文件|`--log /path/to/appium.log`|
|
||||
|`--log-level`|debug|日志级别; 默认 (console[:file]): debug[:debug]|`--log-level debug`|
|
||||
|`--log-timestamp`|false|在终端输出里显示时间戳||
|
||||
|`--local-timezone`|false|使用本地时间戳||
|
||||
|`--log-no-colors`|false|不在终端输出中显示颜色||
|
||||
|`-G`, `--webhook`|null|同时发送日志到 HTTP 监听器|`--webhook localhost:9876`|
|
||||
|`--native-instruments-lib`|false|(IOS-only) iOS 内建了一个怪异的不可能避免的延迟。我们在 Appium 里修复了它。如果你想用原来的,你可以使用这个参数。||
|
||||
|`--app-pkg`|null|(Android-only) 你要运行的apk的java包。 (例如, com.example.android.myApp)|`--app-pkg com.example.android.myApp`|
|
||||
|`--app-activity`|null|(Android-only) 打开应用时,启动的 Activity 的名字(比如, MainActivity)|`--app-activity MainActivity`|
|
||||
|`--app-wait-package`|false|(Android-only) 你想等待的 Activity 的包名。(比如, com.example.android.myApp)|`--app-wait-package com.example.android.myApp`|
|
||||
|`--app-wait-activity`|false|(Android-only) 你想等待的 Activity 名字(比如, SplashActivity)|`--app-wait-activity SplashActivity`|
|
||||
|`--android-coverage`|false|(Android-only) 完全符合条件的 instrumentation 类。 作为命令 adb shell am instrument -e coverage true -w 的 -w 的参数 |`--android-coverage com.my.Pkg/com.my.Pkg.instrumentation.MyInstrumentation`|
|
||||
|`--avd`|null|(Android-only) 要启动的 avd 的名字||`--avd @default`|
|
||||
|`--avd-args`|null|(Android-only) 添加额外的参数给要启动avd|`--avd-args -no-snapshot-load`|
|
||||
|`--device-ready-timeout`|5|(Android-only) 等待设备准备好的时间,以秒为单位|`--device-ready-timeout 5`|
|
||||
|`--safari`|false|(IOS-Only) 使用 Safari 应用||
|
||||
|`--device-name`|null|待使用的移动设备名字|`--device-name iPhone Retina (4-inch), Android Emulator`|
|
||||
|`--platform-name`|null|移动平台的名称: iOS, Android, or FirefoxOS|`--platform-name iOS`|
|
||||
|`--platform-version`|null|移动平台的版本|`--platform-version 7.1`|
|
||||
|`--automation-name`|null|自动化工具的名称: Appium or Selendroid|`--automation-name Appium`|
|
||||
|`--browser-name`|null|移动浏览器的名称: Safari or Chrome|`--browser-name Safari`|
|
||||
|`--default-device`, `-dd`|false|(IOS-Simulator-only) 使用instruments自己启动的默认模拟器||
|
||||
|`--force-iphone`|false|(IOS-only) 无论应用要用什么模拟器,强制使用 iPhone 模拟器||
|
||||
|`--force-ipad`|false|(IOS-only) 无论应用要用什么模拟器,强制使用 iPad 模拟器||
|
||||
|`--language`|null|iOS / Android 模拟器的语言|`--language en`|
|
||||
|`--locale`|null|Locale for the iOS simulator / Android Emulator|`--locale en_US`|
|
||||
|`--calendar-format`|null|(IOS-only) iOS 模拟器的日历格式|`--calendar-format gregorian`|
|
||||
|`--orientation`|null|(IOS-only) 初始化请求时,使用 LANDSCAPE (横屏) 或者 PORTRAIT (竖屏)|`--orientation LANDSCAPE`|
|
||||
|`--tracetemplate`|null|(IOS-only) 指定 Instruments 使用的 tracetemplate 文件|`--tracetemplate /Users/me/Automation.tracetemplate`|
|
||||
|`--show-sim-log`|false|(IOS-only) 如果设置了, iOS 模拟器的日志会写到终端上来||
|
||||
|`--show-ios-log`|false|(IOS-only) 如果设置了, iOS 系统的日志会写到终端上来||
|
||||
|`--nodeconfig`|null|指定 JSON 格式的配置文件 ,用来在 selenium grid 里注册 appiumd|`--nodeconfig /abs/path/to/nodeconfig.json`|
|
||||
|`-ra`, `--robot-address`|0.0.0.0|robot 的 ip 地址|`--robot-address 0.0.0.0`|
|
||||
|`-rp`, `--robot-port`|-1|robot 的端口地址|`--robot-port 4242`|
|
||||
|`--selendroid-port`|8080|用来和 Selendroid 交互的本地端口|`--selendroid-port 8080`|
|
||||
|`--chromedriver-port`|9515|ChromeDriver运行的端口|`--chromedriver-port 9515`|
|
||||
|`--chromedriver-executable`|null|ChromeDriver 可执行文件的完整路径||
|
||||
|`--use-keystore`|false|(Android-only) 设置签名 apk 的 keystore||
|
||||
|`--keystore-path`|(Android-only) keystore 的路径||
|
||||
|`--keystore-password`|android|(Android-only) keystore 的密码||
|
||||
|`--key-alias`|androiddebugkey|(Android-only) Key 的别名||
|
||||
|`--key-password`|android|(Android-only) Key 的密码||
|
||||
|`--show-config`|false|打印 Appium 服务器的配置信息,然后退出||
|
||||
|`--no-perms-check`|false|跳过Appium对是否可以读/写必要文件的检查||
|
||||
|`--command-timeout`|60|默认所有会话的接收命令超时时间 (在超时时间内没有接收到新命令,自动关闭会话)。 会被新的超时时间覆盖||
|
||||
|`--keep-keychains`|false|(iOS) 当 Appium 启动或者关闭的时候,是否保留 keychains (Library/Keychains)||
|
||||
|`--strict-caps`|false|如果所选设备是appium不承认的有效设备,会导致会话失败||
|
||||
|`--isolate-sim-device`|false|Xcode 6存在一个bug,那就是一些平台上如果其他模拟器设备先被删除时某个特定的模拟器只能在没有任何错误的情况下被建立。这个选项导致了Appium不得不删除除了正在使用设备以外其他所有的设备。请注意这是永久性删除,你可以使用simctl或xcode管理被Appium使用的设备类别。||
|
||||
|`--tmp`|null|可以被Appium用来管理临时文件的目录(绝对路径),比如存放需要移动的内置iOS应用程序。 默认的变量为 `APPIUM_TMP_DIR` ,在 *nix/Mac 为 `/tmp` 在windows上使用环境便令 `TEMP` 设定的目录。||
|
||||
|`--trace-dir`|null|用于保存iOS instruments trace的 appium 目录,是绝对路径, 默认为 <tmp dir>/appium-instruments||
|
||||
|`--intent-action`|android.intent.action.MAIN|(Android-only) 用于启动 activity 的intent action|`--intent-action android.intent.action.MAIN`|
|
||||
|`--intent-category`|android.intent.category.LAUNCHER|(Android-only) 用于启动 activity 的intent category|`--intent-category android.intent.category.APP_CONTACTS`|
|
||||
|`--intent-flags`|0x10200000|(Android-only) 启动 activity 的标志|`--intent-flags 0x10200000`|
|
||||
|`--intent-args`|null|(Android-only) 启动 activity 时附带额外的 intent 参数|`--intent-args 0x10200000`|
|
||||
|`--suppress-adb-kill-server`|false|(Android-only) 如果被设定,阻止Appium杀掉adb实例。||
|
||||
@@ -0,0 +1,125 @@
|
||||
## 移动手势的自动化
|
||||
|
||||
虽然Selenium WebDriver的规范支持数种手机交互的方式,但它的参数并不能简单地映射到底层设备使用的自动化函数 (像在iOS上的UIAutomation) 。为此,Appium在规范的最新版本中定义了新的触摸操作/多点触控 API
|
||||
([https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html#multiactions-1](https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html#multiactions-1))。
|
||||
注意,这跟在早期版本中使用原始JSON Wire Protocol 的触摸操作 API不同。
|
||||
|
||||
这些API可以让你使用多个驱动来建立任意手势。请参阅对应语言的Appium客户端文档,就可以找到使用这些API的例子。
|
||||
|
||||
|
||||
### 触摸操作/多点触控 API的概述
|
||||
|
||||
### 触摸操作 (TouchAction)
|
||||
|
||||
*TouchAction* 对象包含一连串的事件。
|
||||
|
||||
在所有的appium客户端库中,触摸对象创建并给出一连串的事件。
|
||||
|
||||
规范中的可用事件有:
|
||||
* 短按 (press)
|
||||
* 释放 (release)
|
||||
* 移动到 (moveTo)
|
||||
* 点击 (tap)
|
||||
* 等待 (wait)
|
||||
* 长按 (longPress)
|
||||
* 取消 (cancel)
|
||||
* 执行 (perform)
|
||||
|
||||
这里有一个通过伪代码创建动作的例子:
|
||||
|
||||
```center
|
||||
TouchAction().press(el0).moveTo(el1).release()
|
||||
```
|
||||
|
||||
上述模拟用户按下一个元素,滑动他的手指到另一个位置,然后从屏幕上释放其手指。
|
||||
|
||||
Appium按顺序执行这些事件。你可以添加一个 `wait` 事件来控制相应手势的时间。
|
||||
|
||||
appium客户端库有不同的方式来实现上述例子,比如:你可以传递一个坐标值或一个元素给 `moveTo` 事件。同时传递坐标和元素,会将坐标和元素对应起来,但这不是绝对的。
|
||||
|
||||
|
||||
调用 `perform` 事件发送整个事件序列给appium,从而使触摸手势在设备上运行。
|
||||
|
||||
Appium客户端还允许人们直接通过驱动程序对象执行触摸操作, 而不是调用触摸操作对象的`perform`事件。
|
||||
|
||||
|
||||
在伪代码中,以下两个是等价的:
|
||||
|
||||
```center
|
||||
TouchAction().tap(el).perform()
|
||||
|
||||
driver.perform(TouchAction().tap(el))
|
||||
```
|
||||
|
||||
### 多点触控 (MultiTouch)
|
||||
|
||||
*MultiTouch* 对象是触摸操作的集合。
|
||||
|
||||
多点触控手势只有两个方法,添加 (`add`) 和执行 (`perform`) 。
|
||||
|
||||
`add` 用于将不同的触摸操作添加到一个多点触控中。
|
||||
|
||||
当 `perform` 被调用的时候,所有被添加到多点触摸中的触摸事件会被发送到appium并且被执行,就像它们同时发生一样。Appium会执行“触摸事件”中的第一个事件,然后第二个,以此类推。
|
||||
|
||||
|
||||
用两只手指点击的代码示例:
|
||||
|
||||
```center
|
||||
action0 = TouchAction().tap(el)
|
||||
action1 = TouchAction().tap(el)
|
||||
MultiAction().add(action0).add(action1).perform()
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 缺陷和解决方法
|
||||
|
||||
不幸的是有一个缺陷存在于iOS的7.x的模拟器上,ScrollViews无法识别由UIAutomation创建的手势 (在iOS上Appium使用的是UIAutomation) 。 为了实现此功能,我们已经提供了新的函数, `scroll`, 在大部分情况下可以让你实现跟ScrollView一样的功能!
|
||||
|
||||
|
||||
|
||||
**滚动**
|
||||
|
||||
|
||||
要使用这特殊的功能,我们重写了driver中的 `execute` 和
|
||||
`executeScript` 方法。 可以通过在命令前加 `mobile: ` 的前缀来使用滚动。
|
||||
请参见下面的例子:
|
||||
|
||||
* **WD.js:**
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
// 把视图往下滑动
|
||||
driver.execute("mobile: scroll", [{direction: 'down'}])
|
||||
// 继续测试
|
||||
```
|
||||
|
||||
* **Java:**
|
||||
|
||||
```java
|
||||
// java
|
||||
JavascriptExecutor js = (JavascriptExecutor) driver;
|
||||
HashMap<String, String> scrollObject = new HashMap<String, String>();
|
||||
scrollObject.put("direction", "down");
|
||||
scrollObject.put("element", ((RemoteWebElement) element).getId());
|
||||
js.executeScript("mobile: scroll", scrollObject);
|
||||
```
|
||||
|
||||
**滑块的自动化**
|
||||
|
||||
|
||||
**iOS**
|
||||
|
||||
* **Java**
|
||||
|
||||
```java
|
||||
// java
|
||||
// 滑动值使用0到1之间的数字以字符串的形式表示
|
||||
// 例如,“0.1”代表10%,“1.0”代表100%
|
||||
WebElement slider = driver.findElement(By.xpath("//window[1]/slider[1]"));
|
||||
slider.sendKeys("0.1");
|
||||
```
|
||||
|
||||
**Android**
|
||||
|
||||
与Android上的滑块进行交互的最佳方式是用触摸操作 (TouchActions) 。
|
||||
@@ -0,0 +1,44 @@
|
||||
## uiautomator UiSelector
|
||||
|
||||
Appium可以使用 [UiSelectors](http://developer.android.com/tools/help/uiautomator/UiSelector.html)
|
||||
进行元素查找,同时也支持[UiScrollable](http://developer.android.com/tools/help/uiautomator/UiScrollable.html)
|
||||
.
|
||||
|
||||
注意:根据索引 (index) 进行查找并不可靠,请使用实例 (instance) 代替. 下面的示范是用Ruby语言编写的、针对 api demo (这是一个 appium 测试用的应用) 的实例。
|
||||
|
||||
翻译者备注:UiSelectors 和 UiScrollable 均是 Android UiAutomator 中的对象,因此以下用法仅适用于 Android 。
|
||||
|
||||
|
||||
找到第一个文本控件 (TextView) 。
|
||||
|
||||
```ruby
|
||||
# ruby
|
||||
first_textview = find_element(:uiautomator, 'new UiSelector().className("android.widget.TextView").instance(0)');
|
||||
```
|
||||
|
||||
根据文本 (text) 找到第一个元素。
|
||||
|
||||
|
||||
```ruby
|
||||
# ruby
|
||||
first_text = find_element(:uiautomator, 'new UiSelector().text("Animation")')
|
||||
first_text.text # "Animation"
|
||||
```
|
||||
|
||||
找到第一个可滚动的元素, 然后找到文本是 "Tabs" 的文本控件。
|
||||
"Tabs" 元素就是将要滚动到的控件。
|
||||
|
||||
```ruby
|
||||
# ruby
|
||||
element = find_element(:uiautomator, 'new UiScrollable(new UiSelector().scrollable(true).instance(0)).getChildByText(new UiSelector().className("android.widget.TextView"), "Tabs")')
|
||||
```
|
||||
|
||||
scrollIntoView 是一个特例,会返回滚动到指定控件的元素。
|
||||
scrollIntoView 对任何的 UiSelector 都可以执行滚动操作。
|
||||
|
||||
```ruby
|
||||
# ruby
|
||||
element = find_element(:uiautomator, 'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("WebView").instance(0));')
|
||||
element.text # "WebView"
|
||||
```
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
## 多语言支持
|
||||
|
||||
程序处理非拉丁字符时存在一个的问题:对于带音标的字符,存在多种编码形式。例如,对于`é`这样的字符,有两种编码方式:一种是单独的字符`é`(Unicode中的`LATIN SMALL LETTER E WITH ACUTE`(带有音标的小写的拉丁字母'E')),另一种是音标在字符后边(`COMBINING ACUTE ACCENT`(字符和音标的组合))。为了解决这个问题,存在一个`normalization` (标准化) 方法,让["每个字符都有一个唯一的二进制表示"](http://www.unicode.org/reports/tr15/)。
|
||||
|
||||
幸运的是,对ASCII字符(例如 不需要进行标准化的字符)进行标准化将不会产生任何变化,并且多次进行标准化
|
||||
操作也不会发生额外的变化。因此,可以对所有字符使用标准化函数而不用担心产生不良影响。
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
var unorm = require('unorm');
|
||||
|
||||
'some ASCII text' === unorm.nfd('some ASCII text');
|
||||
unorm.nfd('Adélaïde Hervé') === unorm.nfd(unorm.nfd('Adélaïde Hervé'));
|
||||
```
|
||||
|
||||
在测试的时候遇到Unicode字符,你需要对字符进行标准化,确保期望的值和接收到的值一致。
|
||||
有很多方法可以用来进行标准化,所以你要确保执行的是同样的方法!
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
var unorm = require('unorm');
|
||||
driver
|
||||
.elementByAccessibilityId('find')
|
||||
.text()
|
||||
.then(function (txt) {
|
||||
unorm.nfd(txt).should.be(unorm.nfd("é Œ ù ḍ"));
|
||||
});
|
||||
```
|
||||
|
||||
一个由不同unicode文本编码导致的问题的标志是断言失败但报告却显示两个看起来一模一样的字符串:
|
||||
|
||||
```shell
|
||||
AssertionError: expected 'François Gérard' to deeply equal 'François Gérard'
|
||||
+ expected - actual
|
||||
|
||||
+"François Gérard"
|
||||
-"François Gérard"
|
||||
```
|
||||
|
||||
当发生只因编码导致的问题时,输出_看上去_一样。从标准的角度,它们的编码应该也和它们看上去那样相同。
|
||||
|
||||
|
||||
### 查找器 (Finder)
|
||||
|
||||
需要被查找的字符也应该需要标准化。比如,你在一个iOS的app上有一个叫做`Найти`的按钮,你也应该在find命令中标准化它。
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
var unorm = require('unorm');
|
||||
driver
|
||||
.findElementByXPath(unorm.nfd("//UIAButton[@name='Найти']"))
|
||||
.should.eventually.exist;
|
||||
```
|
||||
|
||||
否则这个按钮可能无法被找到。
|
||||
|
||||
|
||||
### 文本框 (Text Field)
|
||||
|
||||
默认情况下,iOS和Android的自动化工具都不支持向输入框输入非ASCII字符。
|
||||
|
||||
#### iOS
|
||||
|
||||
Appium 完全绕过键盘直接向iOS设备的输入框发送非ASCII字符。虽然这让这些文本在测试中被成功输入,但必须记住由键盘输入触发的业务逻辑将不会被测试到。
|
||||
|
||||
像上边说的一样,断言收到的文本前应该先标准化它。
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
var unorm = require('unorm');
|
||||
var testText = unorm.nfd("é Œ ù ḍ");
|
||||
driver
|
||||
.elementsByClassName('UIATextField').at(1)
|
||||
.sendKeys(testText)
|
||||
.text()
|
||||
.should.become(testText)
|
||||
.nodeify(done);
|
||||
```
|
||||
|
||||
#### Android
|
||||
|
||||
通过下载并安装一个[特殊键盘](https://github.com/appium/io.appium.android.ime) , Android 可以支持输入 Unicode 字符,这个输入法允许文本通过ASCII在Appium和被测应用之间进行通讯。
|
||||
|
||||
为了使用这个功能,将`unicodeKeyboard`设置为`true`。如果想要键盘设置在测试完成后自动回到原始状态,
|
||||
将`resetKeyboard`设置为`true`。否则Appium测试结束后,Appium的Unicode键盘仍然会被激活。
|
||||
|
||||
翻译备注:这个Unicode键盘并非虚拟键盘,在界面上不会显示出来,所以要进行其他类型的测试必须切换回其他输入法。
|
||||
|
||||
测试时可以通过`send_keys`向输入框输入Unicode字符。
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
var desired = {
|
||||
app: '/path/to/app',
|
||||
deviceName: 'Android Emulator',
|
||||
deviceVersion: '4.4',
|
||||
platformName: 'Android',
|
||||
unicodeKeyboard: true,
|
||||
resetKeyboard: true
|
||||
};
|
||||
var testText = 'é Œ ù ḍ';
|
||||
driver
|
||||
.elementByClassName('android.widget.EditText')
|
||||
.sendKeys(testText)
|
||||
.text()
|
||||
.should.eventually.become(testText)
|
||||
.nodeify(done);
|
||||
```
|
||||
@@ -0,0 +1,18 @@
|
||||
## List of client libraries with Appium server support
|
||||
|
||||
These libraries wrap standard Selenium client libraries to provide all the regular selenium commands dictated by the [JSON Wire protocol](https://w3c.github.io/webdriver/webdriver-spec.html), and add extra commands related to controlling mobile devices, such as **multi-touch gestures** and **screen orientation**.
|
||||
|
||||
Appium client libraries implement the [Mobile JSON Wire Protocol](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md) (an official draft extension to the standard protocol), and elements of the [W3C Webdriver spec](https://dvcs.w3.org/hg/webdriver/raw-file/default/webdriver-spec.html) (a transport-agnostic automation spec; this is where the MultiAction API is defined).
|
||||
|
||||
The Appium server itself defines custom extensions to the official protocols, giving Appium users helpful access to various device behaviors (such as installing/uninstalling apps during the course of a test session). This is why we need Appium-specific clients, not just the 'vanilla' Selenium clients. Of course, Appium client libraries only **add** functionality (in fact, they simply extend the standard Selenium clients), so they can still be used to run regular Selenium sessions.
|
||||
|
||||
Language/Framework | Github Repo and Installation Instructions |
|
||||
----- | ----- |
|
||||
Ruby | [https://github.com/appium/ruby_lib](https://github.com/appium/ruby_lib)
|
||||
Python | [https://github.com/appium/python-client](https://github.com/appium/python-client)
|
||||
Java | [https://github.com/appium/java-client](https://github.com/appium/java-client)
|
||||
JavaScript (Node.js) | [https://github.com/admc/wd](https://github.com/admc/wd)
|
||||
Objective C | [https://github.com/appium/selenium-objective-c](https://github.com/appium/selenium-objective-c)
|
||||
PHP | [https://github.com/appium/php-client](https://github.com/appium/php-client)
|
||||
C# (.NET) | [https://github.com/appium/appium-dotnet-driver](https://github.com/appium/appium-dotnet-driver)
|
||||
RobotFramework | [https://github.com/jollychang/robotframework-appiumlibrary](https://github.com/jollychang/robotframework-appiumlibrary)
|
||||
@@ -0,0 +1,113 @@
|
||||
## Introduction to Appium
|
||||
|
||||
Appium is an open-source tool for automating native,
|
||||
mobile web, and hybrid applications on iOS and Android platforms.
|
||||
**Native apps** are those written using the iOS, Android, or Windows SDKs. **Mobile web apps** are web apps accessed using a mobile browser (Appium supports
|
||||
Safari on iOS and Chrome or the built-in 'Browser' app on Android). **Hybrid apps** have a
|
||||
wrapper around a "webview" -- a native control that enables interaction with
|
||||
web content. Projects like [Phonegap](http://phonegap.com/),
|
||||
make it easy to build apps using web technologies that are then bundled into
|
||||
a native wrapper, creating a hybrid app.
|
||||
|
||||
Importantly, Appium is "cross-platform": it allows you to write tests against
|
||||
multiple platforms (iOS, Android, Windows), using the same API. This enables code reuse between iOS, Android, and Windows testsuites.
|
||||
|
||||
For specific information about what it means for Appium to "support" its
|
||||
platforms, and automation modalities, please see the [platform support doc](/docs/en/appium-setup/platform-support.md).
|
||||
|
||||
### Appium Philosophy
|
||||
|
||||
Appium was designed to meet mobile automation needs according to a philosophy outlined by the following four tenets:
|
||||
|
||||
1. You shouldn't have to recompile your app or modify it in any way in order to automate it.
|
||||
2. You shouldn't be locked into a specific language or framework to write and run your tests.
|
||||
3. A mobile automation framework shouldn't reinvent the wheel when it comes to automation APIs.
|
||||
4. A mobile automation framework should be open source, in spirit and practice as well as in name!
|
||||
|
||||
### Appium Design
|
||||
|
||||
So how does the structure of the Appium project live out this philosophy? We
|
||||
meet requirement #1 by using vendor-provided automation frameworks under the
|
||||
hood. That way, we don't need to compile in any Appium-specific or
|
||||
third-party code or frameworks to your app. This means **you're testing the same app you're shipping**. The vendor-provided frameworks we use are:
|
||||
|
||||
* iOS: Apple's [UIAutomation](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/)
|
||||
* Android 4.2+: Google's [UiAutomator](http://developer.android.com/tools/help/uiautomator/index.html)
|
||||
* Android 2.3+: Google's [Instrumentation](http://developer.android.com/reference/android/app/Instrumentation.html). (Instrumentation support is provided by bundling a separate project, [Selendroid](http://selendroid.io))
|
||||
* Windows: Microsoft's [WinAppDriver](http://github.com/microsoft/winappdriver)
|
||||
|
||||
We meet requirement #2 by wrapping the vendor-provided frameworks in one API,
|
||||
the [WebDriver](http://docs.seleniumhq.org/projects/webdriver/) API.
|
||||
WebDriver (aka "Selenium WebDriver") specifies a client-server protocol
|
||||
(known as the [JSON Wire Protocol](https://w3c.github.io/webdriver/webdriver-spec.html)).
|
||||
Given this client-server architecture, a client written in any language can
|
||||
be used to send the appropriate HTTP requests to the server. There are
|
||||
already [clients written in every popular programming language](http://appium.io/downloads). This also
|
||||
means that you're free to use whatever test runner and test framework you
|
||||
want; the client libraries are simply HTTP clients and can be mixed into your
|
||||
code any way you please. In other words, Appium & WebDriver clients are not
|
||||
technically "test frameworks" -- they are "automation libraries". You can
|
||||
manage your test environment any way you like!
|
||||
|
||||
We meet requirement #3 in the same way: WebDriver has become the de facto
|
||||
standard for automating web browsers, and is a [W3C Working Draft](https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html).
|
||||
Why do something totally different for mobile? Instead we have [extended the protocol](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md)
|
||||
with extra API methods useful for mobile automation.
|
||||
|
||||
It should be obvious that requirement #4 is a given -- you're reading this
|
||||
because [Appium is open source](https://github.com/appium/appium).
|
||||
|
||||
### Appium Concepts
|
||||
|
||||
**Client/Server Architecture**<br/>
|
||||
Appium is at its heart a webserver that exposes a REST API. It receives
|
||||
connections from a client, listens for commands, executes those commands on a
|
||||
mobile device, and responds with an HTTP response representing the result of
|
||||
the command execution. The fact that we have a client/server architecture
|
||||
opens up a lot of possibilities: we can write our test code in any language
|
||||
that has a http client API, but it is easier to use one of the [Appium client
|
||||
libraries](http://appium.io/downloads). We can put the server on a different machine than our
|
||||
tests are running on. We can write test code and rely on a cloud service
|
||||
like [Sauce Labs](https://saucelabs.com/mobile) to receive and interpret the commands.
|
||||
|
||||
**Session**<br/>
|
||||
Automation is always performed in the context of a session. Clients initiate
|
||||
a session with a server in ways specific to each library,
|
||||
but they all end up sending a `POST /session` request to the server,
|
||||
with a JSON object called the 'desired capabilities' object. At this point
|
||||
the server will start up the automation session and respond with a session ID
|
||||
which is used for sending further commands.
|
||||
|
||||
**Desired Capabilities**<br/>
|
||||
Desired capabilities are a set of keys and values (i.e.,
|
||||
a map or hash) sent to the Appium server to tell the server what kind of
|
||||
automation session we're interested in starting up. There are also various
|
||||
capabilities which can modify the behavior of the server during automation.
|
||||
For example, we might set the `platformName` capability to `iOS` to tell
|
||||
Appium that we want an iOS session, rather than an Android or Windows one. Or we might
|
||||
set the `safariAllowPopups` capability to `true` in order to ensure that,
|
||||
during a Safari automation session, we're allowed to use JavaScript to open
|
||||
up new windows. See the [capabilities doc](/docs/en/writing-running-appium/caps.md) for the complete list of capabilities available for Appium.
|
||||
|
||||
**Appium Server**<br/>
|
||||
Appium is a server written in Node.js. It can be built and installed [from source](https://github.com/appium/appium/blob/master/docs/en/contributing-to-appium/appium-from-source.md) or installed directly from NPM:
|
||||
```
|
||||
$ npm install -g appium
|
||||
$ appium
|
||||
```
|
||||
|
||||
**Appium Clients**<br/>
|
||||
There are client libraries (in Java, Ruby, Python, PHP, JavaScript, and C#)
|
||||
which support Appium's extensions to the WebDriver protocol. When using Appium,
|
||||
you want to use these client libraries instead of your regular WebDriver
|
||||
client. You can view the full list of libraries [here](appium-clients.md).
|
||||
|
||||
**[Appium.app](https://github.com/appium/appium-dot-app), [Appium.exe](https://github.com/appium/appium-dot-exe)**<br/>
|
||||
There exist GUI wrappers around the Appium server that can be downloaded.
|
||||
These come bundled with everything required to run the Appium server,
|
||||
so you don't need to worry about Node. They also come with an Inspector,
|
||||
which enables you to check out the hierarchy of your app. This can come in handy when writing tests.
|
||||
|
||||
### Getting Started
|
||||
|
||||
Congratulations! You are now armed with enough knowledge to begin using Appium. Why not head to the [getting started doc](https://github.com/appium/appium/blob/master/README.md) for more detailed requirements and instructions?
|
||||
@@ -0,0 +1,35 @@
|
||||
## Cross-domain iFrame Automation
|
||||
|
||||
[Same-origin policy](https://en.wikipedia.org/wiki/Same-origin_policy) prevents Appium from automating iFrames that have a different domain to the parent.
|
||||
|
||||
### Subdomain workaround
|
||||
If the parent and the iFrame share the same domain (e.g. `site.com` and `shop.site.com`), you can
|
||||
set `document.domain` on both the parent and each iFrame to a common domain. This solves the same-origin policy issue and allows automation. For example:
|
||||
|
||||
Parent:
|
||||
```
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
document.domain = 'site.com';
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="http://shop.site.com" width="200" height="200"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Child iFrame:
|
||||
```
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
document.domain = 'site.com';
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p>This is an iFrame!</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@@ -0,0 +1,59 @@
|
||||
## Selenium Grid
|
||||
|
||||
You are able to register your appium server with a local [Selenium grid](https://code.google.com/p/selenium/wiki/Grid2) ([setup docs](http://docs.seleniumhq.org/docs/07_selenium_grid.jsp)) by using the
|
||||
`--nodeconfig` server parameter.
|
||||
|
||||
```center
|
||||
> appium --nodeconfig /path/to/nodeconfig.json
|
||||
# or, if running from source:
|
||||
> node . --nodeconfig /path/to/nodeconfig.json
|
||||
```
|
||||
|
||||
In the node config file you have to define the `browserName`,
|
||||
`version` and `platform` and based on these parameters the grid
|
||||
will re-direct your test to the right device. You will also need to
|
||||
configure your **host** details and the **selenium grid** details. For
|
||||
a full list of all parameters and descriptions look
|
||||
[here](http://code.google.com/p/selenium/source/browse/java/server/src/org/openqa/grid/common/defaults/GridParameters.properties)
|
||||
|
||||
Once you start the appium server and it registers with the grid,
|
||||
you will see your device on the grid console page:
|
||||
|
||||
"http://**\<grid-ip-adress\>**:**\<grid-port\>**/grid/console"
|
||||
|
||||
### Grid Node Configuration Example json file
|
||||
|
||||
```xml
|
||||
{
|
||||
"capabilities":
|
||||
[
|
||||
{
|
||||
"browserName": "<e.g._iPhone5_or_iPad4>",
|
||||
"version":"<version_of_iOS_e.g._7.1>",
|
||||
"maxInstances": 1,
|
||||
"platform":"<platform_e.g._MAC_or_ANDROID>"
|
||||
}
|
||||
],
|
||||
"configuration":
|
||||
{
|
||||
"cleanUpCycle":2000,
|
||||
"timeout":30000,
|
||||
"proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
|
||||
"url":"http://<host_name_appium_server_or_ip-address_appium_server>:<appium_port>/wd/hub",
|
||||
"host": <host_name_appium_server_or_ip-address_appium_server>,
|
||||
"port": <appium_port>,
|
||||
"maxSession": 1,
|
||||
"register": true,
|
||||
"registerCycle": 5000,
|
||||
"hubPort": <grid_port>,
|
||||
"hubHost": "<Grid_host_name_or_grid_ip-address>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Valid platforms are listed [here](http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/Platform.html)
|
||||
|
||||
If `url`, `host`, and `port` are not given, the config will be auto updated
|
||||
to point to localhost:whatever-port-Appium-started-on.
|
||||
|
||||
If your Appium server is running on a different machine to your Selenium Grid server, make sure you use an external name/IP address in your `host` & `url` docs; `localhost` and `127.0.0.1` will prevent Selenium Grid from connecting correctly.
|
||||
@@ -0,0 +1,168 @@
|
||||
## Automating hybrid apps
|
||||
|
||||
One of the core principles of Appium is that you shouldn't have to change
|
||||
your app to test it. In line with that methodology, it is possible to test
|
||||
hybrid web apps (e.g., the [UIAWebView](https://developer.apple.com/library/ios/documentation/ToolsLanguages/Reference/UIAWebViewClassReference/)
|
||||
elements in an iOS app) the same way
|
||||
you can with Selenium for web apps. There is a bit of technical complexity
|
||||
required so that Appium knows whether you want to automate the native aspects
|
||||
of the app or the web views, but thankfully, we can stay within the
|
||||
WebDriver protocol for everything.
|
||||
|
||||
Here are the steps required to talk to a web view in your Appium test:
|
||||
|
||||
1. Navigate to a portion of your app where a web view is active
|
||||
1. Call [GET session/:sessionId/contexts](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md)
|
||||
1. This returns a list of contexts we can access, like 'NATIVE_APP' or 'WEBVIEW_1'
|
||||
1. Call [POST session/:sessionId/context](https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md)
|
||||
with the id of the context you want to access
|
||||
1. (This puts your Appium session into a mode where all commands are
|
||||
interpreted as being intended for automating the web view,
|
||||
rather than the native portion of the app. For example,
|
||||
if you run getElementByTagName, it will operate on the DOM of the web
|
||||
view, rather than return UIAElements. Of course,
|
||||
certain WebDriver methods only make sense in one context or another,
|
||||
so in the wrong context you will receive an error message).
|
||||
1. To stop automating in the web view context and go back to automating the
|
||||
native portion of the app, simply call `context` again with the native
|
||||
context id to leave the web frame.
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
// assuming we have an initialized `driver` object for an app
|
||||
driver
|
||||
.contexts().then(function (contexts) { // get list of available views. Returns array: ["NATIVE_APP","WEBVIEW_1"]
|
||||
return driver.context(contexts[1]); // choose the webview context
|
||||
})
|
||||
|
||||
// do some web testing
|
||||
.elementsByCss('.green_button').click()
|
||||
|
||||
.context('NATIVE_APP') // leave webview context
|
||||
|
||||
// do more native stuff here if we want
|
||||
|
||||
.quit() // stop webdrivage
|
||||
```
|
||||
|
||||
```java
|
||||
// java
|
||||
// assuming we have a set of capabilities
|
||||
driver = new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
|
||||
|
||||
Set<String> contextNames = driver.getContextHandles();
|
||||
for (String contextName : contextNames) {
|
||||
System.out.println(contextNames); //prints out something like NATIVE_APP \n WEBVIEW_1
|
||||
}
|
||||
driver.context(contextNames.toArray()[1]); // set context to WEBVIEW_1
|
||||
|
||||
//do some web testing
|
||||
String myText = driver.findElement(By.cssSelector(".green_button")).click();
|
||||
|
||||
driver.context("NATIVE_APP");
|
||||
|
||||
// do more native testing if we want
|
||||
|
||||
driver.quit();
|
||||
```
|
||||
|
||||
```ruby
|
||||
# ruby
|
||||
# assuming we have a set of capabilities
|
||||
@driver = Selenium::WebDriver.for(:remote, :desired_capabilities => capabilities, :url => SERVER_URL)
|
||||
|
||||
# I switch to the last context because its always the webview in our case, in other cases you may need to specify a context
|
||||
# View the appium logs while running @driver.contexts to figure out which context is the one you want and find the associated ID
|
||||
# Then switch to it using @driver.switch_to.context("WEBVIEW_6")
|
||||
|
||||
Given(/^I switch to webview$/) do
|
||||
webview = @driver.contexts.last
|
||||
@driver.switch_to.context(webview)
|
||||
end
|
||||
|
||||
Given(/^I switch out of webview$/) do
|
||||
@driver.switch_to.context(@driver.contexts.first)
|
||||
end
|
||||
|
||||
# Now you can use CSS to select an element inside your webview
|
||||
|
||||
And(/^I click a webview button $/) do
|
||||
@driver.find_element(:css, ".green_button").click
|
||||
end
|
||||
```
|
||||
|
||||
```python
|
||||
# python
|
||||
# assuming we have an initialized `driver` object for an app
|
||||
|
||||
# switch to webview
|
||||
webview = driver.contexts.last
|
||||
driver.switch_to.context(webview)
|
||||
|
||||
# do some webby stuff
|
||||
driver.find_element(:css, ".green_button").click
|
||||
|
||||
# switch back to native view
|
||||
driver.switch_to.context(driver.contexts.first)
|
||||
|
||||
# do more native testing if we want
|
||||
|
||||
driver.quit()
|
||||
```
|
||||
|
||||
```php
|
||||
// php
|
||||
// assuming we have an initialized `driver` object in an AppiumTestCase
|
||||
|
||||
public function testThings()
|
||||
{
|
||||
$expected_contexts = array(
|
||||
0 => 'NATIVE_APP',
|
||||
1 => 'WEBVIEW_1'
|
||||
);
|
||||
|
||||
$contexts = $this->contexts();
|
||||
$this->assertEquals($expected_contexts, $contexts);
|
||||
|
||||
$this->context($contexts[1]);
|
||||
$context = $this->context();
|
||||
$this->assertEquals('WEBVIEW_1', $context);
|
||||
|
||||
// do webby stuff
|
||||
|
||||
$this->context('NATIVE_APP');
|
||||
|
||||
// do mobile stuff
|
||||
}
|
||||
```
|
||||
|
||||
### Automating hybrid Android apps
|
||||
|
||||
Appium comes with built-in hybrid support via Chromedriver. Appium also uses
|
||||
Selendroid under the hood for webview support on devices older than 4.4. (In
|
||||
that case, you'll want to specify `"automationName": "selendroid"` as a desired
|
||||
capability).
|
||||
|
||||
Make sure
|
||||
[setWebContentsDebuggingEnabled](http://developer.android.com/reference/android/webkit/WebView.html#setWebContentsDebuggingEnabled(boolean)) is set to true as described in the [remote debugging docs](https://developer.chrome.com/devtools/docs/remote-debugging#configure-webview).
|
||||
|
||||
Once you've set your desired capabilities and started an appium session, follow the generalized instructions above.
|
||||
|
||||
### Automating hybrid iOS apps
|
||||
|
||||
To interact with a web view appium establishes a connection
|
||||
using a remote debugger. When executing against a
|
||||
simulator this connection is established directly as the simulator and
|
||||
the appium server are on the same machine.
|
||||
|
||||
Once you've set your desired capabilities and started an appium session, follow the generalized instructions above.
|
||||
|
||||
### Execution against a real iOS device
|
||||
|
||||
When executing against a real iOS device appium is unable to access the web view directly. Therefore the
|
||||
connection has to be established through the USB lead. To establish this
|
||||
connection we use the [ios-webkit-debugger-proxy](https://github.com/google/ios-webkit-debug-proxy).
|
||||
|
||||
For instruction on how to install and run ios-webkit-debugger-proxy see [iOS webkit debug proxy](/docs/en/advanced-concepts/ios-webkit-debug-proxy.md) documentation.
|
||||
|
||||
Now you can start an appium test session and follow the generalized instructions above.
|
||||
@@ -0,0 +1,65 @@
|
||||
## iOS WebKit Debug Proxy
|
||||
|
||||
For accessing web views on real iOS device appium uses [ios_webkit_debug_proxy](https://github.com/google/ios-webkit-debug-proxy).
|
||||
|
||||
### Installation
|
||||
|
||||
#### Using Homebrew
|
||||
|
||||
To install the latest tagged version of the ios-webkit-debug-proxy using
|
||||
Homebrew, run the following commands in the terminal:
|
||||
|
||||
``` center
|
||||
# The first command is only required if you don't have brew installed.
|
||||
> ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
> brew update
|
||||
> brew install ios-webkit-debug-proxy
|
||||
```
|
||||
|
||||
#### Building ios-webkit-debug-proxy from source
|
||||
|
||||
Open the command terminal on your mac. You can find instructions on how to open the
|
||||
terminal via your favorite search engine. Once that is open, verify you have
|
||||
[Homebew](http://brew.sh/) installed:
|
||||
|
||||
```shell
|
||||
$ brew -v
|
||||
```
|
||||
|
||||
When you're certain you have Homebrew, do the following (the $ indicates the command
|
||||
line prompt, do not enter it):
|
||||
|
||||
```shell
|
||||
$ cd ~
|
||||
$ sudo apt-get install autoconf automake libusb-dev libusb-1.0-0-dev libplist-dev libplist++-dev usbmuxd libtool libimobiledevice-dev
|
||||
$ git clone https://github.com/google/ios-webkit-debug-proxy.git
|
||||
$ cd ios-webkit-debug-proxy
|
||||
$ ./autogen.sh
|
||||
$ make
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
#### Running ios-webkit-debug-proxy
|
||||
|
||||
Once installed you can start the proxy with the following command:
|
||||
|
||||
``` center
|
||||
# Change the udid to be the udid of the attached device and make sure to set the port to 27753
|
||||
# as that is the port the remote-debugger uses. You can learn how to retrieve the UDID from
|
||||
# Apple's developer resources.
|
||||
> ios_webkit_debug_proxy -c 0e4b2f612b65e98c1d07d22ee08678130d345429:27753 -d
|
||||
```
|
||||
|
||||
You may also use the ios-webkit-debug-proxy-launcher to launch the
|
||||
proxy. It monitors the proxy log for errors, and relaunch the proxy
|
||||
where needed. This is also optional and may help with recent devices:
|
||||
|
||||
``` center
|
||||
# change the udid
|
||||
> ./bin/ios-webkit-debug-proxy-launcher.js -c 0e4b2f612b65e98c1d07d22ee08678130d345429:27753 -d
|
||||
```
|
||||
|
||||
**NOTE:** the proxy requires the **"web inspector"** to be turned on to
|
||||
allow a connection to be established. Turn it on by going to **settings >
|
||||
safari > advanced**. Please be aware that the web inspector was **added as
|
||||
part of iOS 6** and was not available previously.
|
||||
@@ -0,0 +1,15 @@
|
||||
## Setting up instruments without delay (iwd) for xcode 7 and iOS >= 9.0
|
||||
|
||||
For iOS >= 9.0 instruments without delay (iwd) does not work by passing binaries through
|
||||
the command line (appium does this under the hood for xcode < 7). See [iwd](https://github.com/lawrencelomax/instruments-without-delay/tree/xcode7-quirks#xcode-7--ios-9-support)
|
||||
|
||||
For enabling iwd for xcode >= 7,
|
||||
- Checkout [appium-instruments](https://github.com/appium/appium-instruments)
|
||||
- Run `xcode-iwd.sh` present in `<appium-instruments>/bin/`
|
||||
|
||||
```
|
||||
sh <appium-instruments>/bin/xcode-iwd.sh <path to xcode> <path to appium-instruments>
|
||||
```
|
||||
eg. `sh ./bin/xcode-iwd.sh /Applications/Xcode.app /Users/xyz/appium-instruments/`
|
||||
|
||||
Note: iwd with xcode7 will only work for iOS >= 9.0, you can switch to older xcode for iOS < 9.0
|
||||
@@ -0,0 +1,158 @@
|
||||
## Migrating your tests from Appium 0.18.x to Appium 1.x
|
||||
|
||||
Appium 1.0 has removed a number of deprecated features from the previous versions. This guide will help you know what needs to change in your test suite to take advantage of Appium 1.0.
|
||||
|
||||
### New client libraries
|
||||
|
||||
The biggest thing you need to worry about is using the new Appium client libraries instead of the vanilla WebDriver clients you are currently using. Visit the [Appium client list](/docs/en/about-appium/appium-clients.md) to find the client for your language. Downloads and instructions for integrating into your code are available on the individual client websites.
|
||||
|
||||
Ultimately, you'll be doing something like (to use Python as an example):
|
||||
|
||||
```center
|
||||
from appium import webdriver
|
||||
```
|
||||
|
||||
Instead of:
|
||||
|
||||
```center
|
||||
from selenium import webdriver
|
||||
```
|
||||
|
||||
### New desired capabilities
|
||||
|
||||
The following capabilities are no longer used:
|
||||
|
||||
* `device`
|
||||
* `version`
|
||||
|
||||
Instead, use these capabilities:
|
||||
|
||||
* `platformName` (either "iOS" or "Android")
|
||||
* `platformVersion` (the mobile OS version you want)
|
||||
* `deviceName` (the kind of device you want, like "iPhone Simulator")
|
||||
* `automationName` ("Selendroid" if you want to use Selendroid, otherwise, this can be omitted)
|
||||
|
||||
The `app` capability remains the same, but now refers exclusively to non-browser apps. To use browsers like Safari or Chrome, use the standard `browserName` cap. This means that `app` and `browserName` are exclusive.
|
||||
|
||||
We have also standardized on camelCase for Appium server caps. That means caps like `app-package` or `app-wait-activity` are now `appPackage` and `appWaitActivity` respectively. Of course, since Android app package and activity are now auto-detected, you should be able to omit them entirely in most cases.
|
||||
|
||||
### New locator strategies
|
||||
|
||||
We've removed the following locator strategies:
|
||||
|
||||
* `name`
|
||||
* `tag name`
|
||||
|
||||
We have now added the `accessibility_id` strategy to do what `name` used to do. The specifics will be relative to your Appium client.
|
||||
|
||||
`tag name` has been replaced by `class name`. So to find an element by its UI type, use the class name locator strategy for your client.
|
||||
|
||||
Note about `class name` and `xpath` strategies: these now require the fully-qualified class name for your element. This means that if you had an xpath selector that looked like this:
|
||||
|
||||
```center
|
||||
//table/cell/button
|
||||
```
|
||||
|
||||
It would now need to be:
|
||||
|
||||
```center
|
||||
//UIATableView/UIATableCell/UIAButton
|
||||
```
|
||||
|
||||
(And likewise for Android: `button` now needs to be `android.widget.Button`)
|
||||
|
||||
We've also added the following locator strategies:
|
||||
|
||||
* `-ios uiautomation`
|
||||
* `-android uiautomator`
|
||||
|
||||
Refer to your client for ways to use these new locator strategies.
|
||||
|
||||
### XML, not JSON
|
||||
|
||||
App source methods, which previously returned JSON, now return XML, so if you have code that relies on parsing the app source, it will need to be updated.
|
||||
|
||||
### Hybrid support through context, not window
|
||||
|
||||
Hybrid apps were previously supported by switching between "windows" using
|
||||
|
||||
* `window_handles`
|
||||
* `window`
|
||||
* `switch_to.window`
|
||||
|
||||
Now Appium supports the more conceptually consistent concept of "context". To get all of the available contexts, or the particular context the application is is, you use
|
||||
|
||||
```python
|
||||
# python
|
||||
driver.contexts
|
||||
current = driver.context
|
||||
```
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
driver.contexts().then(function (contexts) { /*...*/ })
|
||||
```
|
||||
|
||||
```c#
|
||||
// c#
|
||||
driver.GetContexts ()
|
||||
driver.GetContext ()
|
||||
```
|
||||
|
||||
```java
|
||||
// java
|
||||
Set<String> contextNames = driver.getContextHandles();
|
||||
String context = driver.getContext();
|
||||
```
|
||||
|
||||
```php
|
||||
// php
|
||||
$contexts = $this->contexts();
|
||||
$context = $this->context();
|
||||
```
|
||||
|
||||
```ruby
|
||||
# ruby
|
||||
contexts = available_contexts
|
||||
context = current_context
|
||||
```
|
||||
|
||||
And to switch between them, you use
|
||||
|
||||
```python
|
||||
# python
|
||||
driver.switch_to.context("WEBVIEW")
|
||||
```
|
||||
|
||||
```javascript
|
||||
// javascript
|
||||
driver.currentContext().then(function (context) { /*...*/ })
|
||||
```
|
||||
|
||||
```c#
|
||||
// c#
|
||||
driver.SetContext ("WEBVIEW");
|
||||
```
|
||||
|
||||
```java
|
||||
java
|
||||
driver.context(contextName);
|
||||
```
|
||||
|
||||
```php
|
||||
// php
|
||||
$this->context('WEBVIEW');
|
||||
```
|
||||
|
||||
```ruby
|
||||
# ruby
|
||||
set_context "WEBVIEW"
|
||||
```
|
||||
|
||||
### No more `execute_script("mobile: xxx")`
|
||||
|
||||
All the `mobile: ` methods have been removed, and have been replaced by native methods in the Appium client libraries. This means that a method call like `driver.execute("mobile: lock", [5])` will now look something more like `driver.lock(5)` (where `lock` has been turned into a native client method). Of course, the details on calling these methods will differ by client.
|
||||
|
||||
Of particular note, the gesture methods have been replaced by the new TouchAction / MultiAction API which allows for a much more powerful and general way of putting gestural automation together. Refer to your Appium client for usage notes on TouchAction / MultiAction.
|
||||
|
||||
And that's it! Happy migrating!
|
||||
@@ -0,0 +1,44 @@
|
||||
## Migrating your iOS tests from UIAutomation (iOS 9.2 and below) to XCUITest (iOS 9.3 and up)
|
||||
|
||||
For iOS automation, Appium relies on system frameworks provided by Apple. For iOS 9.2 and below, Apple's only automation technology was called UIAutomation, and it ran in the context of a process called "Instruments". As of iOS 10, Apple has completely removed the UIAutomation instrument, thus making it impossible for Appium to allow testing in the way it used to. Fortunately, Apple introduced a new automation technology, called XCUITest, beginning with iOS 9.3. For iOS 10 and up, this will be the only supported automation framework from Apple.
|
||||
|
||||
Appium has built in support for XCUITest beginning with Appium 1.6. For the most part, the capabilities of XCUITest match those of UIAutomation, and so the Appium team was able to ensure that test behavior will stay the same. This is one of the great things about using Appium! Even with Apple completely changing the technology your tests are using, your scripts can stay mostly the same! That being said, there are some differences you'll need to be aware of which might require modification of your test scripts if you want to run them under our XCUITest automation backend. This document will help you with those differences.
|
||||
|
||||
### Element class name schema
|
||||
|
||||
With XCUITest, Apple has given different class names to the UI elements which make up the view hierarchy. For example, `UIAButton` is now `XCUIElementTypeButton`. In many cases, there is a direct mapping between these two classes. If you use the `class name` locator strategy to find elements, Appium 1.6 will rewrite the selector for you. Likewise, if you use the `xpath` locator strategy, Appium 1.6 will find any `UIA*` elements in your XPath string and rewrite them appropriately.
|
||||
|
||||
This does not however guarantee that your tests will work exactly the same, for two reasons:
|
||||
|
||||
1. The application hierarchy reported to Appium will not necessarily be identical within XCUITest to what it was within UIAutomation. If you have a path-based XPath selector, it may need to be adjusted.
|
||||
2. The list of class names is not entirely identical either. Many elements are returned by XCUITest as belonging to the `XCUIElementTypeOther` class, a sort of catch-all container.
|
||||
|
||||
### Page source
|
||||
|
||||
As mentioned just above, if you rely on the app source XML from the `page source` command, the XML output will now differ significantly from what it was under UIAutomation.
|
||||
|
||||
### `-ios uiautomation` locator strategy
|
||||
|
||||
This locator strategy was specifically built on UIAutomation, so it is not included in the XCUITest automation backend. We will be working on a similar "native"-type locator strategy in coming releases.
|
||||
|
||||
### System dependencies
|
||||
|
||||
In addition to the many gotchas that might come with upgrading any XCode installation (unrelated to Appium), Appium's XCUITest support requires a new system dependency: [Carthage](https://github.com/Carthage/Carthage). Appium Doctor has now been updated to ensure that the `carthage` binary is on your path.
|
||||
|
||||
### API differences
|
||||
|
||||
Unfortunately, the XCUITest API and the UIAutomation API are not equivalent. In many cases (like with `tap/click`), the behavior is identical. But some features that were available in the UIAutomation backend are not yet available in the new XCUITest backend. These known lacking features include:
|
||||
* Geolocation support (e.g., `driver.location`)
|
||||
* Shaking the device
|
||||
* Locking the device
|
||||
* Rotating the device (note that this is *NOT* device _orientation_, which is supported)
|
||||
|
||||
We will endeavor to add these features back in future releases of Appium.
|
||||
|
||||
### Other known issues
|
||||
|
||||
Finally, a list of known issues with the initial 1.6 release:
|
||||
|
||||
* [Problems with processArguments](https://github.com/appium/appium/issues/6888)
|
||||
|
||||
As far as possible, we will add the missing features and fix other known issues in the [1.6.1 Milestone](https://github.com/appium/appium/milestone/27), so following that may be of interest to you.
|
||||
@@ -0,0 +1,54 @@
|
||||
## Settings
|
||||
|
||||
Settings are a new concept introduced by appium. They are currently not a part of the Mobile JSON Wire Protocol, or the Webdriver spec.
|
||||
|
||||
Settings are a way to specify the behavior of the appium server.
|
||||
|
||||
Settings are:
|
||||
- Mutable, they can be changed during a session
|
||||
- Only relevant during the session they are applied. They are reset for each new session.
|
||||
- Control the way the appium server behaves during test automation. They do not apply to controlling the app or device under test.
|
||||
|
||||
An example of a setting would be `ignoreUnimportantViews` for Android. Android can be set to ignore elements in the View Hierarchy which it deems irrelevant. Setting this can cause tests to run faster. A user who *wants* to access the ignored elements however, would want to disable `ignoreUnimportantViews`, and reenable it afterwards.
|
||||
|
||||
Another example of a use-case for settings would be telling appium to ignore elements which are not visible.
|
||||
|
||||
Settings are implemented via the following API endpoints:
|
||||
|
||||
**POST** /session/:sessionId/appium/settings
|
||||
|
||||
>Expects a JSON hash of settings, where keys correspond to setting names, and values to the value of the setting.
|
||||
```
|
||||
{
|
||||
settings: {
|
||||
ignoreUnimportantViews : true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**GET** /session/:sessionId/appium/settings
|
||||
|
||||
>Returns a JSON hash of all the currently specified settings.
|
||||
```
|
||||
{
|
||||
ignoreUnimportantViews : true
|
||||
}
|
||||
```
|
||||
|
||||
### Supported Settings
|
||||
|
||||
**"ignoreUnimportantViews"** - Boolean which sets whether Android devices should use `setCompressedLayoutHeirarchy()` which ignores all views which are marked IMPORTANT_FOR_ACCESSIBILITY_NO or IMPORTANT_FOR_ACCESSIBILITY_AUTO (and have been deemed not important by the system), in an attempt to make things less confusing or faster.
|
||||
|
||||
#### Android UiAutomator Configurator
|
||||
|
||||
sets [UiAutomator Configurator](https://developer.android.com/reference/android/support/test/uiautomator/Configurator.html) timeouts and delays in Android devices. only works in Android API 18 and above.
|
||||
|
||||
**"actionAcknowledgmentTimeout"** - Int which is the same as [setActionAcknowledgmentTimeout](https://developer.android.com/reference/android/support/test/uiautomator/Configurator.html#setActionAcknowledgmentTimeout(long)). If a negative value is given, it would set to default(3 * 1000 milliseconds)
|
||||
|
||||
**"keyInjectionDelay"** - Int which is the same as [setKeyInjectionDelay](https://developer.android.com/reference/android/support/test/uiautomator/Configurator.html#setKeyInjectionDelay(long)). If a negative value is given, it would set to default(0 milliseconds)
|
||||
|
||||
**"scrollAcknowledgmentTimeout"** - Int which is the same as [setScrollAcknowledgmentTimeout](https://developer.android.com/reference/android/support/test/uiautomator/Configurator.html#setScrollAcknowledgmentTimeout(long)). If a negative value is given, it would set to default(200 milliseconds)
|
||||
|
||||
**"waitForIdleTimeout"** - Int which is the same as [setWaitForIdleTimeout](https://developer.android.com/reference/android/support/test/uiautomator/Configurator.html#setWaitForIdleTimeout(long)). If a negative value is given, it would set to default(10 * 1000 milliseconds)
|
||||
|
||||
**"waitForSelectorTimeout"** - Int which is the same as [setWaitForSelectorTimeout](https://developer.android.com/reference/android/support/test/uiautomator/Configurator.html#setWaitForSelectorTimeout(long)). If a negative value is given, it would set to default(10 * 1000 milliseconds)
|
||||
@@ -0,0 +1,14 @@
|
||||
## Intel® Hardware Accelerated Execution Manager
|
||||
|
||||
If you find the android emulator a slow and your system runs on an Intel®
|
||||
cpu, you can check out HAXM. HAXM lets you leverage your hardware for
|
||||
virtualization, accelerating the emulator.
|
||||
|
||||
* To install HAXM open the Android SDK Manager, you will find the package
|
||||
under Extras.
|
||||
* You can find all relevant documentation on [Intel's website][1]
|
||||
* This will require an x86 emulator image
|
||||
* Use Intel's package to install HAXM; The Android SDK Manager appears to not
|
||||
do so successfully, depending on the version you might have installed
|
||||
|
||||
[1]: http://software.intel.com/en-us/articles/intel-hardware-accelerated-execution-manager/
|
||||
@@ -0,0 +1,50 @@
|
||||
## Android Setup
|
||||
|
||||
To get started, you'll need to install node.js (v4 or greater). Just
|
||||
follow the [instructions for your flavor of linux](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager).
|
||||
|
||||
Once you've got node.js installed, install the [Android SDK](http://developer.android.com/sdk/index.html).
|
||||
You will need to run the 'android' tool (included in the SDK, under the 'tools' directory).
|
||||
|
||||
Run the 'android' tool and use it to install an API Level 17 or greater.
|
||||
|
||||
(If you want to run Appium from source, you will also need [Apache Ant](http://ant.apache.org/) to build the bootstrap jar that Appium uses for running against Android simulators/devices.)
|
||||
|
||||
Finally, set `$ANDROID_HOME` to be your Android SDK path. If you unzipped the
|
||||
Android SDK to /usr/local/adt/, for example, you should add this to your
|
||||
shell startup:
|
||||
|
||||
export ANDROID_HOME="/usr/local/adt/sdk"
|
||||
|
||||
Now you're set up to run Appium! If you're running Appium from source, run
|
||||
`npm install` from your Appium checkout to install all the
|
||||
dependencies.
|
||||
|
||||
### Additional Setup for Older Versions of Android
|
||||
|
||||
Appium uses, and comes prepackaged with, Selendroid for running Android
|
||||
versions 2.3 to 4.1. Appium switches to using Selendroid automatically when it
|
||||
detects older versions, but there is some additional setup required if you're
|
||||
running from source.
|
||||
|
||||
* Make sure you have [Maven 3.1.1](http://maven.apache.org/download.cgi) or
|
||||
newer installed (`mvn`).
|
||||
|
||||
### Running Appium Android Tests
|
||||
|
||||
To run tests on Linux, you will need to have the Android Emulator booted and
|
||||
running an AVD with API Level 17 or greater. Then run Appium (`appium`) after
|
||||
installing via NPM, or `node .` in the source directory if running from source.
|
||||
|
||||
See the [server documentation](/docs/en/writing-running-appium/server-args.md) for all the command line arguments.
|
||||
|
||||
### Notes
|
||||
|
||||
* There exists a hardware accelerated emulator for android, it has its own
|
||||
limitations. For more information you can check out this
|
||||
[page](/docs/en/appium-setup/android-hax-emulator.md).
|
||||
* Make sure that `hw.battery=yes` in your AVD's `config.ini`, if you want to
|
||||
run any of the Appium tests, or use any of the power commands.
|
||||
* Selendroid requires the following permission for your app:
|
||||
`<uses-permission android:name="android.**permission.INTERNET"/>`,
|
||||
please make sure your app has internet permission set when you are using selendroid or older versions of Android i.e. 2.3 to 4.1
|
||||
@@ -0,0 +1,51 @@
|
||||
## Deploying an iOS app to a real device
|
||||
|
||||
To prepare for your Appium tests to run on a real device, you will need to:
|
||||
|
||||
1. Build your app with specific device-targeted parameters
|
||||
2. Use [ideviceinstaller](https://github.com/libimobiledevice/ideviceinstaller), a 3rd-party tool,
|
||||
to deploy this build to your device
|
||||
|
||||
### Xcodebuild with parameters:
|
||||
A newer xcodebuild now allows settings to be specified. Taken from [developer.apple.com](https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html):
|
||||
|
||||
```center
|
||||
xcodebuild [-project projectname] [-target targetname ...]
|
||||
[-configuration configurationname] [-sdk [sdkfullpath | sdkname]]
|
||||
[buildaction ...] [setting=value ...] [-userdefault=value ...]
|
||||
```
|
||||
|
||||
This is a resource to explore the available [settings](https://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-DontLinkElementID_10)
|
||||
|
||||
```center
|
||||
CODE_SIGN_IDENTITY (Code Signing Identity)
|
||||
Description: Identifier. Specifies the name of a code signing identity.
|
||||
Example value: iPhone Developer
|
||||
```
|
||||
|
||||
PROVISIONING_PROFILE is missing from the index of available commands,
|
||||
but may be necessary.
|
||||
|
||||
Specify "CODE_SIGN_IDENTITY" & "PROVISIONING_PROFILE" settings in the
|
||||
xcodebuild command:
|
||||
|
||||
```center
|
||||
xcodebuild -sdk <iphoneos> -target <target_name> -configuration <Debug> CODE_SIGN_IDENTITY="iPhone Developer: Mister Smith" PROVISIONING_PROFILE="XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX"
|
||||
```
|
||||
|
||||
On success, the app will be built to your ```<app_dir>/build/<configuration>-iphoneos/<app_name>.app```
|
||||
|
||||
### Deploy using ideviceinstaller
|
||||
|
||||
To install the latest tagged version of the ideviceinstaller using
|
||||
Homebrew, run the following commands in the terminal:
|
||||
|
||||
``` center
|
||||
# The first command is only required if you don't have brew installed.
|
||||
> ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
> brew update
|
||||
> brew install ideviceinstaller
|
||||
> ideviceinstaller -u <UDID of device> -i <path of .app/.ipa>
|
||||
```
|
||||
|
||||
Next: [Running Appium on Real Devices](real-devices.md)
|
||||
@@ -0,0 +1,30 @@
|
||||
## Parallel Android Tests
|
||||
|
||||
Appium provides a way for users to automate multiple Android sessions on a single machine. All it involves is starting multiple Appium servers with different flags.
|
||||
|
||||
The important flags for automating multiple Android sessions are:
|
||||
|
||||
- `-p` the main Appium port
|
||||
- `-U` the device id
|
||||
- `-bp` the Appium bootstrap port
|
||||
- `--chromedriver-port` the chromedriver port (if using webviews or chrome)
|
||||
- `--selendroid-port` the selendroid port (if using selendroid)
|
||||
|
||||
More information on these flags can be found [here](../writing-running-appium/caps.md).
|
||||
|
||||
If we had two devices with the ID's 43364 and 32456, we would start two different Appium servers with the following commands:
|
||||
|
||||
`node . -p 4492 -bp 2251 -U 32456`
|
||||
|
||||
`node . -p 4491 -bp 2252 -U 43364`
|
||||
|
||||
As long as your Appium and Appium bootstrap ports are between 0 and 65536, all they have to be is different so that two Appium servers aren't trying to listen on the same port. Be sure that your -u flag corresponds with the correct device ID. This is how Appium knows which device to communicate with, so it must be accurate.
|
||||
|
||||
If you are using chromedriver or selendroid, set a different port for each server.
|
||||
|
||||
### Parallel iOS Tests
|
||||
|
||||
Unfortunately, running local parallel iOS tests aren't possible. Unlike Android, only one version of the iOS simulator can be launched at a time, making it run multiple tests at once.
|
||||
|
||||
If you do want to run parallel iOS tests, you need to use Sauce. Simply upload your Appium test to Sauce, and it can run as many parallel iOS or Android tests as your account allows. See more about running your tests on Sauce [here](https://docs.saucelabs.com/tutorials/appium/).
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
## Appium Platform Support
|
||||
|
||||
Appium supports a variety of platforms and testing modalities (native,
|
||||
hybrid, web, real devices, simulators, etc...). This document is designed to
|
||||
make explicit the level of support and requirements for each of these.
|
||||
|
||||
### iOS Support
|
||||
|
||||
See [Running on OS X: iOS](running-on-osx.md) for iOS requirements and setup
|
||||
instructions.
|
||||
|
||||
* Versions: 7.1, 8.0, 8.1, 8.2, 8.3, 8.4, 9.0, 9.1 and 9.2
|
||||
* Devices: iPhone Simulator, iPad Simulator, and real iPhones and iPads
|
||||
* Native app support: Yes, with debug version of .app (simulator),
|
||||
or correctly-signed .ipa (real devices). Underlying support is provided by
|
||||
Apple's [UIAutomation](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/)
|
||||
framework.
|
||||
* Mobile web support: Yes, via automation of mobile Safari. For real devices,
|
||||
ios-webkit-remote-debugger is required, and automation of native aspects of
|
||||
the Safari interface is not possible. See the [mobile web doc](/docs/en/writing-running-appium/mobile-web.md) for instructions.
|
||||
* Hybrid support: Yes. For real devices, ios-webkit-remote-debugger is
|
||||
required. See the [hybrid doc](/docs/en/advanced-concepts/hybrid.md) for instructions.
|
||||
* Support for automating multiple apps in one session: No
|
||||
* Support for automating multiple devices simultaneously: No
|
||||
* Support for automating vendor-provided or third-party apps: Only
|
||||
vendor-provided apps (Preferences, Maps, etc...), and only on the simulator
|
||||
* Support for automating custom, non-standard UI controls: Minimal. You need to
|
||||
set accessibility information on the control which enables some basic
|
||||
automation.
|
||||
|
||||
### Android Support
|
||||
|
||||
See [Running on OS X: Android](running-on-osx.md),
|
||||
[Running on Windows](running-on-windows.md), or
|
||||
[Running on Linux](running-on-linux.md) for Android requirements and setup
|
||||
instructions.
|
||||
|
||||
* Versions: 2.3 and up
|
||||
* Versions 2.3 through 4.2 are supported via Appium's bundled version of
|
||||
[Selendroid](http://selendroid.io), which utilizes [Instrumentation](http://developer.android.com/reference/android/app/Instrumentation.html). Selendroid has a different set of commands than the default Appium (though this is rapidly being minimized) and a different support profile. To access this automation backend, use the `automationName` capability with the value `Selendroid`.
|
||||
* Versions 4.2 and up are supported via Appium's own [UiAutomator](http://developer.android.com/tools/testing-support-library/index.html#UIAutomator)
|
||||
libraries. This is the default automation backend.
|
||||
* Devices: Android emulators and real Android devices
|
||||
* Native app support: Yes
|
||||
* Mobile web support: Yes (but not when using Selendroid backend). Automation
|
||||
is effected using a bundled [Chromedriver](https://code.google.com/p/selenium/wiki/ChromeDriver)
|
||||
server as a proxy. With 4.2 and 4.3, automation works on official Chrome
|
||||
browser or Chromium only. With 4.4+, automation also works on the built-in
|
||||
"Browser" app. Chrome/Chromium/Browser must already be installed on the
|
||||
device under test. See the [mobile web doc](/docs/en/writing-running-appium/mobile-web.md) for instructions.
|
||||
* Hybrid support: Yes. See the [hybrid doc](/docs/en/advanced-concepts/hybrid.md) for instructions.
|
||||
* With default Appium automation backend: versions 4.4 and up
|
||||
* With Selendroid automation backend: versions 2.3 and up
|
||||
* Support for automating multiple apps in one session: Yes (but not when
|
||||
using the Selendroid backend)
|
||||
* Support for automating multiple devices simultaneously: Yes,
|
||||
though Appium must be started using different ports for the server
|
||||
parameters `--port`, `--bootstrap-port` (or `--selendroid-port`) and/or
|
||||
`--chromedriver-port`. See the [server args doc](/docs/en/writing-running-appium/server-args.md) for more
|
||||
information on these parameters.
|
||||
* Support for automating vendor-provided or third-party apps: Yes (but not
|
||||
when using the Selendroid backend)
|
||||
* Support for automating custom, non-standard UI controls: No
|
||||
|
||||
### Windows Support
|
||||
|
||||
See [running on Windows](running-on-windows.md) for details
|
||||
|
||||
* [Windows App Testing](windows-app-testing.md)
|
||||
@@ -0,0 +1,91 @@
|
||||
## Appium on real iOS devices
|
||||
|
||||
Appium has support for real device testing.
|
||||
|
||||
To get started on a real device, you will need the following:
|
||||
|
||||
* An [Apple Developer ID](https://developer.apple.com/programs/ios/)
|
||||
and a valid Developer Account with a configured distribution certificate and
|
||||
provisioning profile.
|
||||
* An iPad or iPhone. Make sure this has been set up for development in Xcode. See [this article](https://developer.apple.com/library/ios/recipes/xcode_help-devices_organizer/articles/provision_device_for_development-generic.html) for more information.
|
||||
* A signed `.ipa` file of your app, or the source code to build one.
|
||||
* A Mac with [Xcode](https://itunes.apple.com/en/app/xcode/id497799835?mt=12)
|
||||
and the Xcode Command Line Developer Tools.
|
||||
|
||||
### Provisioning Profile
|
||||
|
||||
A valid iOS Development Distribution Certificate and Provisioning Profile are
|
||||
necessary to test on a real device. Your app will also need to be signed. You
|
||||
can find information about this in the [Apple documentation](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/TestingYouriOSApp/TestingYouriOSApp.html).
|
||||
|
||||
Appium will attempt to install your app using Fruitstrap, but it is often easier
|
||||
to pre-install your app using Xcode to ensure there are no problems (see the [iOS deploy](ios-deploy.md) doc for more information).
|
||||
|
||||
### Testing using Xcode 8 (including iOS 10) with XCUITest
|
||||
|
||||
This functionality currently depends on logging based on `idevicesyslog`, and
|
||||
port forwarding based on `iProxy`, both of which are part of `libimobiledevice`.
|
||||
Install it with [Homebrew](http://brew.sh/),
|
||||
|
||||
```
|
||||
brew install libimobiledevice
|
||||
```
|
||||
|
||||
Alternatively, logging can be done using `deviceconsole`, which is available
|
||||
[here](https://github.com/rpetrich/deviceconsole). To choose between them, use
|
||||
the desired capability `realDeviceLogger`, passing in the path to the logging
|
||||
program.
|
||||
|
||||
|
||||
### Running your tests with Appium
|
||||
|
||||
Once your device and app are configured, you can run tests on that device by
|
||||
passing the `-U` or `--udid` flag to the server or the `udid` desired capability,
|
||||
and the bundle ID (if the app is installed on the device) or the path to the
|
||||
`.ipa` or `.apk` file via the `--app` flag or the `app` desired capability.
|
||||
|
||||
### Server Arguments
|
||||
|
||||
For example, if you are prelaunching your app and wish for Appium to force use
|
||||
a specific UDID, then you may use the below command:
|
||||
|
||||
```center
|
||||
appium -U <udid> --app <path or bundle>
|
||||
```
|
||||
|
||||
This will start Appium and have Appium use the device to test the app.
|
||||
|
||||
Refer to the [Appium server arguments](/docs/en/writing-running-appium/server-args.md) page for more detail on
|
||||
the arguments that you can use.
|
||||
|
||||
### Desired Capabilities
|
||||
|
||||
You can launch the app on a device by including the following desired
|
||||
capabilities in your tests:
|
||||
|
||||
* `app`
|
||||
* `udid`
|
||||
|
||||
Refer to the [Appium server capabilities](/docs/en/writing-running-appium/caps.md) page for more detail on
|
||||
the capabilities that you can use.
|
||||
|
||||
### Troubleshooting ideas
|
||||
|
||||
0. Make sure UDID is correct by checking it in Xcode Organizer or iTunes. It
|
||||
is a long string (20+ chars).
|
||||
0. Make sure that you can run your tests against the Simulator.
|
||||
0. Double check that you can invoke your automation from Instruments.
|
||||
0. Make sure Instruments is not already running.
|
||||
0. Make sure UI Automation is enabled on your device. Settings -> Developer -> Enable UI Automation
|
||||
|
||||
### Appium on real Android devices
|
||||
|
||||
Hooray! There's nothing extra to know about testing real Android devices: it
|
||||
works exactly the same as testing on emulators. Make sure that your device
|
||||
can connect to ADB and has Developer Mode enabled. For testing Chrome on a real
|
||||
device, you're responsible for ensuring that Chrome of an appropriate version
|
||||
is installed.
|
||||
|
||||
Also, you'll want to make sure that "Verify Apps" in settings is
|
||||
disabled/unchecked, otherwise it can prevent some of Appium's helper apps from
|
||||
launching and doing their job correctly.
|
||||
@@ -0,0 +1,12 @@
|
||||
## Running Appium on Linux
|
||||
|
||||
### Limitations
|
||||
|
||||
If you are running Appium on Linux, you cannot use the prebuilt '.app',
|
||||
which is built for OS X only. Additionally, you will not be able to test iOS
|
||||
apps because Appium relies on OS X-only libraries to support iOS testing.
|
||||
|
||||
### Setup (Android)
|
||||
|
||||
Instructions for setting up Android and running tests on Linux are the same as
|
||||
those on Mac OS X. See the [Android setup docs](/docs/en/appium-setup/android-setup.md).
|
||||
@@ -0,0 +1,163 @@
|
||||
## Running Appium on Mac OS X
|
||||
|
||||
Appium on OS X supports iOS and Android testing.
|
||||
|
||||
### System setup (iOS)
|
||||
|
||||
* Appium requires Mac OS X 10.7 or greater. We recommend OS X 10.10.
|
||||
* Make sure you have Xcode and the iOS SDK(s) installed. Xcode version 7.1 is
|
||||
recommended as earlier versions of Xcode are limited in which versions of iOS
|
||||
they can test against. See the next section for more detail.
|
||||
* You need to authorize use of the iOS Simulator. See [below](#authorizing-ios-on-the-computer).
|
||||
* If you're on Xcode 7.x, Instruments Without Delay (IWD) does not work. You can
|
||||
enable IWD (which will significantly speed up your tests) using
|
||||
[this method](/docs/en/advanced-concepts/iwd_xcode7.md)
|
||||
* If you're on Xcode 6, you need to launch each simulator you intend to use
|
||||
with appium in advance, and change the default to actually show the soft
|
||||
keyboard if you want sendKeys to work. You can do this by clicking on any
|
||||
textfield and hitting command-K until you notice the soft keyboard show up.
|
||||
* If you're on Xcode 6, you have a feature in Xcode called Devices
|
||||
(command-shift-2). You need to make sure that whichever deviceName you choose
|
||||
to use with Appium in your capabilities, there is only one of those per sdk
|
||||
version. In other words, if you send in a deviceName cap of "iPhone 5s" and
|
||||
a platformVersion cap of "8.0", you need to make sure that there is exactly
|
||||
one device with the name "iPhone 5s" and the 8.0 sdk in your devices list.
|
||||
Otherwise, Appium won't know which one to use.
|
||||
* In iOS8, devices each have their own setting which enables or disables
|
||||
UIAutomation. It lives in a "Developer" view in the Settings app. You need to
|
||||
verify that UIAutomaion is enabled in this view before the simulator or
|
||||
device can be automated.
|
||||
|
||||
### Authorizing iOS on the computer
|
||||
|
||||
You need to authorize use of the iOS Simulator by running the `authorize-ios`
|
||||
binary made available through `npm`. Install the program by running
|
||||
|
||||
```
|
||||
npm install -g authorize-ios
|
||||
```
|
||||
|
||||
And the invoke the program using
|
||||
|
||||
```
|
||||
sudo authorize-ios
|
||||
```
|
||||
|
||||
If you are running [Appium.app](https://github.com/appium/appium-dot-app), you can
|
||||
authorize iOS through the GUI.
|
||||
|
||||
You need to do this every time you install a new version of Xcode.
|
||||
|
||||
### Testing against multiple iOS SDKs
|
||||
|
||||
Xcode version 7.1 allows for automatic testing against iOS versions 7.1 and later.
|
||||
|
||||
If you're using multiple Xcode versions, you can switch between them using:
|
||||
|
||||
sudo xcode-select --switch <path to required xcode>
|
||||
|
||||
### Testing using Xcode 8 (including iOS 10) with XCUITest
|
||||
|
||||
In order to automate iOS devices with Xcode 8 (which includes all testing of iOS 10+),
|
||||
you need to install the [Carthage](https://github.com/Carthage/Carthage) dependency
|
||||
manager:
|
||||
|
||||
```
|
||||
brew install carthage
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### System setup (Android)
|
||||
|
||||
Instructions for setting up Android and running tests on Mac OS X are the same as
|
||||
those on Linux. See the [Android setup docs](/docs/en/appium-setup/android-setup.md).
|
||||
|
||||
### Running iOS tests on OS X using Jenkins
|
||||
|
||||
First download the jenkins-cli.jar and verify the Mac successfully connects to Jenkins master. Ensure you've run the `authorize-ios` command mentioned above.
|
||||
|
||||
`wget https://jenkins.ci.cloudbees.com/jnlpJars/jenkins-cli.jar`
|
||||
|
||||
```
|
||||
java -jar jenkins-cli.jar \
|
||||
-s https://team-appium.ci.cloudbees.com \
|
||||
-i ~/.ssh/id_rsa \
|
||||
on-premise-executor \
|
||||
-fsroot ~/jenkins \
|
||||
-labels osx \
|
||||
-name mac_appium
|
||||
```
|
||||
|
||||
Next define a LaunchAgent for Jenkins to launch automatically on login. A LaunchDaemon will not work because daemons don't have GUI access. Make sure the plist doesn't contain the `SessionCreate` or `User` key as that may prevent tests from running. You'll see a `Failed to authorize rights` error if misconfigured.
|
||||
|
||||
```
|
||||
$ sudo nano /Library/LaunchAgents/com.jenkins.ci.plist
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.jenkins.ci</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>java</string>
|
||||
<string>-Djava.awt.headless=true</string>
|
||||
<string>-jar</string>
|
||||
<string>/Users/appium/jenkins/jenkins-cli.jar</string>
|
||||
<string>-s</string>
|
||||
<string>https://instructure.ci.cloudbees.com</string>
|
||||
<string>on-premise-executor</string>
|
||||
<string>-fsroot</string>
|
||||
<string>/Users/appium/jenkins</string>
|
||||
<string>-executors</string>
|
||||
<string>1</string>
|
||||
<string>-labels</string>
|
||||
<string>mac</string>
|
||||
<string>-name</string>
|
||||
<string>mac_appium</string>
|
||||
<string>-persistent</string>
|
||||
</array>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/Users/appium/jenkins/stdout.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/Users/appium/jenkins/error.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Finally set the owner, permissions, and then start the agent.
|
||||
|
||||
```
|
||||
sudo chown root:wheel /Library/LaunchAgents/com.jenkins.ci.plist
|
||||
sudo chmod 644 /Library/LaunchAgents/com.jenkins.ci.plist
|
||||
|
||||
launchctl load /Library/LaunchAgents/com.jenkins.ci.plist
|
||||
launchctl start com.jenkins.ci
|
||||
```
|
||||
|
||||
|
||||
### Files generated by iOS test runs
|
||||
|
||||
Testing on iOS generates files that can sometimes get large. These include logs,
|
||||
temporary files, and derived data from Xcode runs. Generally the following locations
|
||||
are where they are found, should they need to be deleted:
|
||||
|
||||
```
|
||||
$HOME/Library/Logs/CoreSimulator/*
|
||||
```
|
||||
|
||||
For Instruments-based tests (iOS _not_ using `XCUITest` as `automationName`):
|
||||
|
||||
```
|
||||
/Library/Caches/com.apple.dt.instruments/*
|
||||
```
|
||||
|
||||
For XCUITest-based tests:
|
||||
|
||||
```
|
||||
$HOME/Library/Developer/Xcode/DerivedData/*
|
||||
```
|
||||
@@ -0,0 +1,44 @@
|
||||
#Windows Setup
|
||||
|
||||
Appium on Windows supports both Windows and Android app automation!
|
||||
|
||||
See [Windows App Testing](/docs/en/writing-running-appium/windows-app-testing.md) for more details.
|
||||
|
||||
## Running Appium on Windows
|
||||
|
||||
## Setup
|
||||
|
||||
To get started:
|
||||
|
||||
1. Download latest [node and npm tools](https://nodejs.org/download/release/v6.3.0/node-v6.3.0-x64.msi) MSI (version >= 6.0). The `npm` and `nodejs` paths should be in your PATH environment variable.
|
||||
2. Open admin cmd prompt
|
||||
3. Run the command `npm install -g appium` which will install Appium from NPM
|
||||
4. To start Appium, you can now simply run `appium` from the prompt.
|
||||
5. Follow the directions below for setup for either Android or Windows app testing.
|
||||
6. Run a test from any Appium client.
|
||||
|
||||
## Additional Setup for Android App Testing
|
||||
|
||||
1. Download the latest Java JDK [here](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) (accept the license agreement first). Set 'JAVA_HOME' to be your JDK path. The `bin` in that directory should be added to your PATH variable.
|
||||
2. Install the [Android SDK](http://developer.android.com/sdk/index.html). Set the `ANDROID_HOME` environment variable to be your Android SDK path and add the `tools` and `platform-tools` folders to your PATH variable.
|
||||
3. Install [Apache Ant](http://ant.apache.org/bindownload.cgi) or use the one that comes with the Android Windows SDK in the eclipse\plugins folder. Be sure to add the folder containing Ant to your PATH variable.
|
||||
4. Install [Apache Maven](http://maven.apache.org/download.cgi) and set the M2HOME and M2 environment variables. Set `M2_HOME` to the directory maven is installed in, and set `M2` to the `bin` in that directory. Add the path you used for `M2` to your PATH.
|
||||
5. To run tests on Windows, you will need to have the Android Emulator booted or an Android Device connected that is running an AVD with API Level 17 or greater. Then run Appium on the command line (via the `appium` command)
|
||||
6. Your test script should ensure that the `platformVersion` capability corresponds to the emulator or device version you are testing, and that the `app` capability is an absolute path to the .apk file of the Android app.
|
||||
|
||||
## Additional Setup for Windows App Testing
|
||||
|
||||
1. To test a Windows app, simply make sure you have turned [developer mode](https://msdn.microsoft.com/en-us/windows/uwp/get-started/enable-your-device-for-development) on.
|
||||
|
||||
(see the [Windows app testing](/docs/en/writing-running-appium/windows-app-testing.md) doc for instructions on how to run Windows app tests)
|
||||
|
||||
## Running Appium
|
||||
|
||||
See the [server documentation](/docs/en/writing-running-appium/server-args.md) for all the command line arguments.
|
||||
|
||||
* On Windows run Appium.exe as an administrator, or when running from source you need to run cmd as an administrator.
|
||||
* You must supply the `--no-reset` or `--full-reset` flags for
|
||||
Android to work on Windows.
|
||||
* There exists a hardware accelerated emulator for Android; it has it's own
|
||||
limitations. For more information you can check out this
|
||||
[page](/docs/en/appium-setup/android-hax-emulator.md).
|
||||
@@ -0,0 +1,189 @@
|
||||
## Troubleshooting Appium
|
||||
|
||||
Here's what to do if you're experiencing problems, before you submit a ticket
|
||||
to github or write to the [appium-discuss discussion group](https://discuss.appium.io).
|
||||
|
||||
### General
|
||||
|
||||
* Make sure you've followed the getting started steps in the [README](/README.md)
|
||||
* Make sure your system is set up appropriately (i.e., XCode is updated,
|
||||
Android SDK is installed and `ANDROID_HOME` is set.
|
||||
* Make sure the paths to your applications are correct
|
||||
* On windows run appium.app as administrator or when running from source you need to run cmd as administrator.
|
||||
|
||||
### If you're running Appium.app
|
||||
|
||||
* Update the app and restart. If you get a message saying the app can't be updated,
|
||||
re-download it from [appium.io](http://appium.io).
|
||||
|
||||
### If you're running Appium from source
|
||||
|
||||
* `git pull` to make sure you're running the latest code
|
||||
* Remove old dependencies: `rm -rf node_modules`
|
||||
* Re-install dependencies: `npm install`
|
||||
* Re-transpile the code: `gulp transpile`
|
||||
|
||||
* You can also use [Appium Doctor](https://github.com/appium/appium-doctor) to determine whether your system is configured correctly for Appium.
|
||||
* If you get this error after upgrading to Android SDK 22:
|
||||
`{ANDROID_HOME}/tools/ant/uibuild.xml:155: SDK does not have any Build Tools installed.`
|
||||
In the Android SDK 22, the platform and build tools are split up into their
|
||||
own items in the SDK manager. Make sure you install the build-tools and platform-tools.
|
||||
|
||||
### Android
|
||||
|
||||
* Make sure the Android emulator is up and running.
|
||||
* It's sometimes useful to run `adb kill-server && adb devices`. This can
|
||||
reset the connection to the Android device.
|
||||
* Make sure you set ANDROID_HOME pointing to the Android SDK directory
|
||||
|
||||
### Windows
|
||||
|
||||
* Make sure developer mode is on
|
||||
* Make sure command prompt is Admin
|
||||
* Check that the URL Appium server is listening to matches the one specified in test script
|
||||
|
||||
### IOS
|
||||
|
||||
* Make sure Instruments.app is not open
|
||||
* If you're running the simulator, make sure your actual device is not
|
||||
plugged in
|
||||
* Make sure the accessibility helper is turned off in your Settings app
|
||||
* Make sure the app is compiled for the version of the simulator that's being
|
||||
run
|
||||
* Make sure the app is compiled for the simulator (or real device) as
|
||||
appropriate (e.g., in debug mode for the simulator), or you might get
|
||||
a `posix spawn` error.
|
||||
* If you've ever run Appium with sudo, you might need to `sudo rm
|
||||
/tmp/instruments_sock` and try again as not-sudo.
|
||||
* If this is the first time you've run Appium, make sure to authorize the use
|
||||
of Instruments. See [running on OSX documentation](./running-on-osx.md#authorizing-ios-on-the-computer).
|
||||
* If Instruments is crashing when running against a physical device ("exited with code 253"), ensure Xcode has downloaded device symbols. Go to Window -> Devices, and it should start automatically. This is needed after iOS version upgrades.
|
||||
* If you see `iOS Simulator failed to install the application.` and the
|
||||
paths are correct, try restarting the computer.
|
||||
* If you have custom elements in your app, they will not be automatable by
|
||||
UIAutomation (and therefore Appium) by default. You need to set the
|
||||
accessibility status to 'enabled' on them. The way to do this in code is:
|
||||
|
||||
```center
|
||||
[myCustomView setAccessibilityEnabled:YES];
|
||||
```
|
||||
|
||||
* Tests on iOS may exhibit symptoms similar to a memory leak including sluggish
|
||||
performance or hangs. If you experience this problem, it's likely due to a
|
||||
known issue with NSLog. One option is to remove NSLog from your code.
|
||||
However, there are several more nuanced approaches that may also help without
|
||||
requiring that you refactor.
|
||||
|
||||
### Workaround 1
|
||||
NSLog is a macro and can be redefined. E.g.,
|
||||
```objectivec
|
||||
// *You'll need to define TEST or TEST2 and then recompile.*
|
||||
|
||||
#ifdef TEST
|
||||
#define NSLog(...) _BlackHoleTestLogger(__VA_ARGS__);
|
||||
#endif // TEST
|
||||
#ifdef TEST2
|
||||
#define NSLog(...) _StdoutTestLogger(__VA_ARGS__);
|
||||
#endif // TEST2
|
||||
|
||||
void _BlackHoleTestLogger(NSString *format, ...) {
|
||||
//
|
||||
}
|
||||
|
||||
void _StdoutTestLogger(NSString *format, ...) {
|
||||
va_list argumentList;
|
||||
va_start(argumentList, format);
|
||||
NSMutableString * message = [[NSMutableString alloc] initWithFormat:format
|
||||
arguments:argumentList];
|
||||
|
||||
printf(message);
|
||||
|
||||
va_end(argumentList);
|
||||
[message release];
|
||||
}
|
||||
```
|
||||
|
||||
### Workaround 2
|
||||
Manually replace the underlying function that NSLog wraps. This method was recommended by
|
||||
[Apple in a similar context.](https://support.apple.com/kb/TA45403?locale=en_US&viewlocale=en_US)
|
||||
|
||||
```objectivec
|
||||
extern void _NSSetLogCStringFunction(void(*)(const char *, unsigned, BOOL));
|
||||
|
||||
static void _GarbageFreeLogCString(const char *message, unsigned length, BOOL withSyslogBanner) {
|
||||
fprintf(stderr, "%s\\n", message);
|
||||
}
|
||||
|
||||
int main (int argc, const char *argv[]) {
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
int exitCode;
|
||||
|
||||
setbuf(stderr, NULL);
|
||||
|
||||
_NSSetLogCStringFunction(_GarbageFreeLogCString);
|
||||
exitCode = WOApplicationMain(@"Application", argc, argv);
|
||||
[pool release];
|
||||
return exitCode;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Webview/Hybrid/Safari app support
|
||||
|
||||
* Make Sure you enable the 'Web Inspector' on the real device.
|
||||
* Make Sure you enable the Safari - Advance Preferences- Developer menu for
|
||||
simulators.
|
||||
* Make sure you are properly switching contexts using the `context` appium commands provided by your client library.
|
||||
* If you getting this error: select_port() failed, when trying to open the
|
||||
proxy, see this [discussion](https://groups.google.com/forum/#!topic/appium-discuss/tw2GaSN8WX0)
|
||||
* In a Safari session, if the logs indicate that the initial url cannot be entered, make sure that
|
||||
you have the software keyboard enabled. See this [discussion](https://github.com/appium/appium/issues/6440).
|
||||
|
||||
### FirefoxOS
|
||||
|
||||
* Make sure the Boot-to-Gecko simulator is up and running.
|
||||
* Make sure the simulator screen is alive and unlocked (might require restarting B2G).
|
||||
|
||||
### Let the community know
|
||||
|
||||
Once you've tried the above steps and your issue still isn't resolved,
|
||||
here's what you can do:
|
||||
|
||||
If you're having trouble getting Appium working and the error messages Appium
|
||||
provides are not clear, join the [discussion group](https://discuss.appium.io)
|
||||
and send a message. Please include the following:
|
||||
|
||||
* How you're running Appium (Appium.app, npm, source)
|
||||
* What operating system you are using
|
||||
* What device and version you are testing against (i.e. Android 4.4, or iOS 7.1)
|
||||
* Whether you are running against a real device or a simulator/emulator
|
||||
* The client-side and server-side errors you're getting (i.e.,
|
||||
"In Python this is the exception I get in my test script,
|
||||
and here's a link to a paste of the Appium server output)
|
||||
* Per above, it's very important to include a paste of the Appium server
|
||||
output when it's run in verbose mode so that we can diagnose what's going on.
|
||||
|
||||
If you've found what you believe is a bug, go straight to the [issue tracker](https://github.com/appium/appium/issues)
|
||||
and submit an issue describing the bug and a repro case.
|
||||
|
||||
### Known Issues
|
||||
|
||||
* If you've installed Node from the Node website, it requires that you use sudo
|
||||
for `npm`. This is not ideal. Try to get node with [nvm](https://github.com/creationix/nvm),
|
||||
[n](https://github.com/visionmedia/n) or `brew install node` instead!
|
||||
* Webview support works on real iOS devices with a proxy, see [discussion](https://groups.google.com/d/msg/appium-discuss/u1ropm4OEbY/uJ3y422a5_kJ).
|
||||
* Sometimes iOS UI elements become invalidated milliseconds after they are
|
||||
found. This results in an error that looks like `(null) cannot be tapped`.
|
||||
Sometimes the only solution is to put the finding-and-clicking code in a retry
|
||||
block.
|
||||
* Appium may have difficulties finding the `node` executable if you've
|
||||
installed Node and npm via MacPorts. You must make sure that the MacPorts bin
|
||||
folder (`/opt/local/bin` by default) is added to `PATH` somewhere in your
|
||||
`~/.profile`, `~/.bash_profile` or `~/.bashrc`.
|
||||
|
||||
### Specific Errors
|
||||
|
||||
|Action|Error|Resolution|
|
||||
|------|-----|----------|
|
||||
|Running ios test|`[INST STDERR] posix spawn failure; aborting launch`|Your app is not compiled correctly for the simulator or device.|
|
||||
|Running mobile safari test|`error: Could not prepare mobile safari with version '7.1'`|You probably need to run the authorize script again to make the iOS SDK files writeable. See [running on OSX documentation](./running-on-osx.md#authorizing-ios-on-the-computer)|
|
||||
@@ -0,0 +1,155 @@
|
||||
## Running Appium from Source
|
||||
|
||||
So you want to run Appium from source and help fix bugs and add features?
|
||||
Great! Just fork the project, make a change, and send a pull request! Please
|
||||
have a look at our [Style Guide](style-guide-2.0.md) before getting to work.
|
||||
Please make sure the unit and functional tests pass before sending a pull
|
||||
request; for more information on how to run tests, keep reading!
|
||||
|
||||
Make sure you read and follow the setup instructions in the README first.
|
||||
|
||||
### Setting up Appium from Source
|
||||
|
||||
An Appium setup involves the Appium server, which sends messages back and forth
|
||||
between your test code and devices/emulators, and a test script, written in
|
||||
whatever language binding exists that is compatible with Appium. Run an
|
||||
instance of an Appium server, and then run your test.
|
||||
|
||||
The quick way to get started:
|
||||
|
||||
```center
|
||||
git clone https://github.com/appium/appium.git
|
||||
cd appium
|
||||
npm install
|
||||
gulp transpile # requires gulp, see below
|
||||
npm install -g authorize-ios # for ios only
|
||||
authorize-ios # for ios only
|
||||
node .
|
||||
```
|
||||
|
||||
### Hacking on Appium
|
||||
|
||||
Make sure you have `ant`, `maven`, `adb` installed and added to system `PATH`, also you
|
||||
would need the android-16 sdk (for Selendroid) and android-19 sdk installed.
|
||||
From your local repo's command prompt, install the following packages using the
|
||||
following commands (if you didn't install `node` using Homebrew, you might have
|
||||
to run `npm` with sudo privileges):
|
||||
|
||||
```center
|
||||
npm install -g mocha
|
||||
npm install -g gulp
|
||||
npm install -g gulp-cli
|
||||
npm install -g appium-doctor && appium-doctor --dev
|
||||
npm install
|
||||
gulp transpile
|
||||
```
|
||||
|
||||
The first two commands install test and build tools (`sudo` may not be
|
||||
necessary if you installed node.js via Homebrew). The third command verifies
|
||||
that all of the dependencies are set up correctly (since dependencies for
|
||||
building Appium are different from those for simply running Appium) and fourth
|
||||
command installs all app dependencies and builds supporting binaries and test
|
||||
apps. The final command transpiles all the code so that `node` can run it.
|
||||
|
||||
When pulling new code from GitHub, if there are changes to `package.json` it
|
||||
is necessary to remove the old dependencies and re-run `npm install`:
|
||||
|
||||
```center
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
gulp transpile
|
||||
```
|
||||
|
||||
At this point, you will be able to start the Appium server:
|
||||
|
||||
```center
|
||||
node .
|
||||
```
|
||||
|
||||
See [the server documentation](/docs/en/writing-running-appium/server-args.md)
|
||||
for a full list of arguments.
|
||||
|
||||
#### Hacking with Appium for iOS
|
||||
|
||||
To avoid a security dialog that may appear when launching your iOS apps you'll
|
||||
have to modify your `/etc/authorization` file in one of two ways:
|
||||
|
||||
1. Manually modify the element following `<allow-root>` under `<key>system.privilege.taskport</key>`
|
||||
in your `/etc/authorization` file to `<true/>`.
|
||||
|
||||
2. Run the following command which automatically modifies your
|
||||
`/etc/authorization` file for you:
|
||||
|
||||
```center
|
||||
sudo node_modules/.bin/authorize-ios.js
|
||||
|
||||
# alternatively
|
||||
sudo $(npm bin)/authorize-ios
|
||||
```
|
||||
|
||||
At this point, run:
|
||||
|
||||
```center
|
||||
rm -rf node-modules
|
||||
npm install
|
||||
gulp transpile
|
||||
```
|
||||
|
||||
Now your Appium instance is ready to go. Run `node .` to kick up the Appium server.
|
||||
|
||||
#### Hacking with Appium for Android
|
||||
|
||||
Set up Appium by running:
|
||||
|
||||
```center
|
||||
rm -rf node-modules
|
||||
npm install
|
||||
gulp transpile
|
||||
```
|
||||
|
||||
Make sure you have one and only one Android emulator or device running, e.g.,
|
||||
by running this command in another process (assuming the `emulator` command is
|
||||
on your path):
|
||||
|
||||
```center
|
||||
emulator -avd <MyAvdName>
|
||||
```
|
||||
|
||||
Now you are ready to run the Appium server via `node .`.
|
||||
|
||||
#### Making sure you're up to date
|
||||
|
||||
Since Appium uses dev versions of some packages, it often becomes necessary to
|
||||
install new `npm` packages or update various things. Running `npm install` will
|
||||
update everything necessary. You will also need to do this when Appium bumps
|
||||
its version up. Prior to running `npm install` it is recommended to remove
|
||||
all the old dependencies in the `node_modules` directory:
|
||||
|
||||
```center
|
||||
rm -rf node-modules
|
||||
npm install
|
||||
gulp transpile
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
|
||||
First, check out our documentation on [running tests in
|
||||
general](/docs/en/writing-running-appium/running-tests.md) Make sure your
|
||||
system is set up properly for the platforms you desire to test on.
|
||||
|
||||
Once your system is set up and your code is up to date, you can run unit tests
|
||||
with:
|
||||
|
||||
```center
|
||||
gulp once
|
||||
```
|
||||
|
||||
You can run functional tests for all supported platforms (after ensuring that
|
||||
Appium is running in another window with `node .`) with:
|
||||
|
||||
```center
|
||||
gulp e2e-test
|
||||
```
|
||||
|
||||
Before committing code, please run `gulp once` to execute some basic tests and
|
||||
check your changes against code quality standards.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user