A Developer's Overview of Appium
Anyone is welcome to become an Appium developer; just read this guide and get
some of your code merged, and you are one of us! If you stick around and help
a lot, we will also make you a committer so that you can continue to help the
community more easily. If you are developing code for Appium and have
questions, reach out to the developer community at
email@example.com. Note that this is a mailing list for
development questions, not usage questions or bug reports. Usage questions
belong on discuss.appium.io. The GitHub issue
tracker is for bug reports and feature requests only.
Agile Development Workflow
The Appium team runs development according to a very lightweight version of
SCRUM. Every two weeks we begin a new "sprint", or a period of time in which we
have decided what we want to accomplish. Anyone familiar with the Appium
codebase is welcome to attend our sprint planning and participate as a SCRUM
team member for that sprint. No long-term commitments required! During the
sprint, we update each other with daily progress in the
#standup room in our
Appium Slack Group (there are no real-time daily
standups). At the end of the sprint, to celebrate our accomplishments and
reflect on how things went, we hold a "retrospective", which might result in
a list of things we can try differently or do better next time around.
Ultimately, the goal is to time an Appium release at the end of each sprint, so every two weeks. We're not quite there, but hopefully we will be soon.
Current meeting times:
- Sprint Planning: every other Monday from 10:00 AM - 10:45 AM (Pacific Time)
- Sprint Retrospective: every other other Friday from 1:00 PM - 1:30 PM (Pacific Time)
We hold meetings using Zoom video chat.
For project management, we use the ZenHub browser plugin, which adds various features like Kanban boards and Epics to the GitHub interface. To fully participate in Appium SCRUM, you'll need to have this browser plugin installed.
If you are interested in participating a sprint, ping
the Appium Slack Group, or DM
@jlipps on Twitter, and we'll share how to join
the video chat for the next sprint.
Appium is primarily a collection of node.js packages that
combine to form a running node.js server. These packages are maintained
independently of one another and each have their own GitHub repo, CI, and
release process. Some packages (like
appium-ios-driver) are large and add
significant functionality to Appium, while others play a support role and
expose one specific bit of functionality that is reused by other packages.
For an overview of the package hierarchy and the role that each package plays, please check out our package overview doc.
Because this version of the language is not yet supported natively by older
versions of node.js, Appium code is transpiled to ES5 (the more
widely-supported version of JS). This transpilation process must occur before
any code is run. In addition to the new language features of ES6, we have
adopted two very important keywords from the subsequent version of JS, namely
await, which assist in writing asynchronous code cleanly. Because
of the transpilation step, Appium packages include tools which watch code for
changes and automatically re-transpile the code. Usually, the same tool will
automatically run unit tests as well to ensure that nothing small has broken.
Most Appium packages have this as the default behavior when running
Linting and Style
It's important for all of Appium's JS to look and feel the same. This includes style conventions as well as coding patterns and which libraries we use to solve various problems. You should get familiar with our new ES2015 Style Guide. When transpiling, Appium packages will automatically run ESLint or other lint tools and provide warning or error feedback if the code doesn't conform to our style. These tools are not necessarily exhaustive of the kinds of style issues we care about, so we may also mention style issues in our reviews. This isn't to be nit-picky but to have a clean, consistent, and readable codebase!
Getting your code into Appium is easy: just submit a PR to one of our repos and engage with the maintainers in the review process. We have a number of requirements for code submissions (but don't worry! If the following seems like a lot, we will helpfully and patiently walk you through each step. Just send in your PR and we'll go from there):
- Follow the style of the surrounding code and our Style Guide
- Atomic commits--one commit per logical change (i.e., make sure that commits don't need to come in a group in order for the program to work. It should work at any given commit). Usually this means one commit per PR. You'll want to get very familiar with
git rebase -iand squashing!
- No merge commits: always rebase on top of latest master (or whatever other branch you're asking to merge into) before submitting your PR.
- Almost all changes should have tests. Bugfixes should at the least have unit tests that prove that the bug has been fixed. New features should have unit tests and in most cases e2e tests to prove that the feature actually works. We will be happy to walk you through the test creation process. Reading the surrounding test code is a good place to start. Our CI systems usually run test coverage statistics and we will likely not merge code that decreases test coverage.
If you do all of these things before submission, your code will almost certainly be accepted very quickly! Of course, if you're thinking of making a change to Appium that requires a lot of work, you might reach out to the developers list to make sure that the change is in line with our philosophy and in principle something that we'll accept before you get going.
Always make sure that your changes are tested! In addition to writing unit and e2e tests, make sure you run existing tests before you begin to make changes and before you push code to be reviewed. We do have CI set up for every Appium repository as a safety net for reviewers to know whether the code they are reviewing has passed muster. Running tests in any Appium package is easy! Unless the README says otherwise, here are the things you can do:
npm run lint # run eslint on the code npm run watch # watch directory to re-transpile on code change, lint, and run unit tests npm run test # same as above but don't watch npm run e2e-test # transpile and run end-to-end/functional tests _FORCE_LOGS=1 <command> # show module log output during test run
Note that we have a convention for unit test files to end in
for e2e test files to end in
The release process for any Appium module other than the main Appium package is pretty straightforward (note that you will need to be an NPM owner for the package if you want to publish it. Ownership is managed by the Appium committers; talk to @jlipps or @imurchie if you believe you should be an owner and are not):
rm -rf node_modules && rm -rf package-lock.json && npm installand run tests to make sure a clean install works.
- Determine whether we have a patch (bugfix), minor (feature), or major (breaking) release according to the principles of SemVer (see also this explanation of how SemVer works with NPM).
- Update the
READMEwith any appropriate changes and commit. Most subpackages don't have a
npm version <version-type>with the appropriate version type.
- Push the appropriate branch to GitHub, and don't forget to include the
--tagsflag to include the tag just created by
--tag betaif this isn't an official release).
For the main Appium packages, all the above steps must be taken, but with
several changes. One reason is that for the main package we use NPM shrinkwrap
to ensure dependencies don't change between installations. Another reason is
that we develop on master and release on various branches. The way it works is
as follows: we always develop and add new code to master. When we are ready to
make a new minor or major release (i.e.,
2.0.0), we create
a release branch (
2.0 respectively). We then publish off of that
branch. As we feel the need to make patch releases, we first pull the patch
into master, then cherry-pick individual patches to the release branch (perhaps
even multiple release branches). Then we again publish from those branches with
the updated patch version (
2.0.1 for example).
A note about
npm shrinkwrap: We use npm shrinkwrap
in order to lock dependencies on release. Without it, any development on dependent
packages will be reflected when Appium is installed, which may lead to issues. Since
the configuration file,
npm-shrinkwrap.json, only exists on release branches,
it is necessary to manually manage it during the release process. It needs to be
checked in to GitHub along with changes to
package.json. With npm 5+ there is
package-lock.json file produced. During the shrinkwrap process this is
converted into the
- Remove the NPM shrinkwrap and package-lock JSON files if they exists.
rm -rf node_modules && npm installand run tests to make sure a clean install works.
- Determine whether we have a
major(breaking) release according to the principles of SemVer.
package.jsonwith the appropriate new version.
- Update the CHANGELOG/README with appropriate changes and submit for review as a PR, along with shrinkwrap and
package.jsonchanges. Wait for it to be merged, then pull it into the release branch.
rm -rf node_modules && npm install --productionto get just the production dependencies.
npm shrinkwrapto write the new NPM shrinkwrap JSON file, and commit this file.
- Create a tag of the form
v<version>on the release branch (usually a minor branch like
git tag -a v<version>, e.g.,
git tag -a v1.5.0. This is not necessary for beta versions.
- Push the tag to upstream:
git push --tags <remote> <branch>
- Install dev dependencies (or at least
appium-gulp-plugins), and undo the changes to the NPM shrinkwrap JSON file (e.g.,
git checkout -- npm-shrinkwrap.json).
--tag betaif this isn't an official release).
- Remove the NPM shrinkwrap JSON file from Git and push the changes
- Update the site docs or put in an issue to have the site docs updated
- From Appium repo, run
npm run generate-docsand make a pull request if there are any newly generated docs.
- When the above PR is merged, clone the appium.io repo (if you haven't done so already)
- Check out and pull the latest
- Follow the setup guide in the README.md
- Generate the docs by running
npm run build:docs
- Test by running
npm run serveand navigating to https://localhost:4000/
- Make a new branch
- Commit and push changes and make a pull request to have changes merged into
- From Appium repo, run
- Create a new release on GitHub: go to
https://github.com/appium/appium/releases/tag/v<VERSION>and hit "Edit Tag". Make the release name
2.0.5), then paste in the changelog (but not the changelog header for this version). If it's a beta release, mark as pre-release.
- Create a new post on discuss.appium.io announcing the release. Post it in the "News" category. Paste in the changelog and any choice comments. Pin it and unpin the previous release post.
- Begin process of releasing
- Notify @jlipps to so he can tweet a link to the discuss post.