Get the Code
Both the marionette server and client code is managed in mozilla-central, so please follow this guide to install mercurial. Once that is done, you can now clone our source code (called mozilla-central):
hg clone https://hg.mozilla.org/mozilla-central/
Which will create a folder called 'mozilla-central' that contains our source code. NOTE: mozilla-central is a *very large* repository, you will need to have about 2GB of space available. This repository holds the code for not just Marionette, but all of Firefox and supporting projects.
Get a Marionette-enabled Build
You'll need a version of Firefox with marionette built into it.
If you're writing code for the marionette server (JS code)
You should make your own Firefox build. You can build your own by following instructions here. You may also be able to make your build process shorted by enabling artifact builds.
If you're writing code for the marionette client (Python code)
You can make your own Firefox build or you can download a copy of Firefox. The easiest way to download a specific Firefox build is with a tool called mozdownload.
Once you have the build, install it, and keep note of the installation directory. You'll need it in the following steps.
Getting it all hooked up
I strongly recommend using virtualenv when working in python. To install it run 'pip install virtualenv'. If you do not have pip, you can get it using 'easy_install pip'
Once you have this, go into the mozilla-central source code you downloaded and do:
cd $srcdir/testing/marionette virtualenv venv source venv/bin/activate # install marionette_driver package cd client python setup.py develop # install marionette_client package (a.k.a. Marionette Test Runner) cd ../harness python setup.py develop
Now you will have a marionette_client installed in your virtual environment! To test out if everything is in working order, let's run a sample test.
To do this, you'll need to know where the firefox-bin lives in the Firefox version you downloaded/built. If you built it, it will be in your object directory: (object directory)/dist/bin/firefox-bin.
If you built or downloaded your build earlier
If you downloaded the build (Nightly), you'll have to find the path to the executable inside the installation directory you made note of earlier. For mac, it's FirefoxNightlyDebug.app/Contents/MacOS/firefox-bin; for linux, once you untar the file, it should be firefox/firefox-bin. For windows, it will be firefox.exe, located in the directory you installed Nightly in. Once you have the path, follow these steps to run a test
cd (mozilla-central)/testing/marionette/harness/marionette/ python runtests.py --binary=<path to firefox executable> tests/unit/test_execute_script.py
Note: If you're using windows, if you're using the shell provided by mozilla-build, instead of using "C:\<path using \ slashes>" type file paths, you should use "/c/<path using / slashes>".
Starting a Marionette-Enabled Firefox without runtests.py
The instructions in the previous section start a Firefox instance using runtests.py (ie: our test runner). You can start your own Firefox instance with marionette running. All you need is to create a Firefox profile with marionette preferences enabled. It is recommended that you create a profile just for testing (separate from your default browsing one), so that if anything goes wrong, you can just create a new test profile.
To create a profile, you need to start the profile manager. To do that, you'll need to find the path to your firefox executable inside the installation directory you made note of earlier. For mac, it's FirefoxNightlyDebug.app/Contents/MacOS/firefox-bin; for linux, once you untar the file, it should be firefox/firefox-bin. For windows, it will be firefox.exe, located in the directory you installed Nightly in. Once you have the path, follow these steps to run a test
and run the following:
<path to executable> -P
You'll then be presented with the profile manager window. Click the 'Create Profile...' button and create a new profile, then select that new profile and click 'Start Firefox'. You'll now have a Firefox instance started with your brand new profile! Note: the next time you start Firefox, it will use the default profile, not the one you just created. You have to use the instruction above to use this test profile again.
In the Firefox address bar, type in 'about:config' and hit enter. Accept the warning, and you'll be presented with a large list of preferences. You will need to add the following preferences to about:config (right click on the page to create a new entry). The first is a boolean, the second is a string. The -> indicates the mapping of the name to the value:
marionette.defaultPrefs.enabled -> true marionette.defaultPrefs.port -> 2828
Your test profile is now ready to go. You will only ever need to set these preferences ONCE per profile, so don't worry about repeating this step.
Now, since the Marionette server starts when Firefox starts up, you'll need to restart firefox with this profile. Close this Firefox instance, and start up the profile manager again:
<path to executable> -P
Select the test profile you created and click 'Start Firefox'. Marionette should now be started!
You can verify if Marionette has started by checking the port it is running on. By default, it runs on port 2828. You can use Telnet to check:
telnet localhost 2828
If there is a Marionette server running, you'll see something like:
Trying ::1... telnet: connect to address ::1: Connection refused Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. 66:{ "from": "root", "applicationType": "gecko", "traits": [] }
If there is no Marionette server running, you'll see a lot of "telnet: connect to address fe80::1: Connection refused" messages
Running tests
The easiest way to run tests if you're working in a mozilla-central checkout is with mach. If you don't want to use mach, read on.
To run tests against an existing Marionette server, you'll need to change directories into our test-harness code:
cd (mozilla-central)/testing/marionette/harness/marionette/
Note: If you're using windows, if you're using the shell provided by mozilla-build, instead of using "C:\<path using \ slashes>" type file paths, you should use "/c/<path using / slashes>".
To run the tests, you'll need to call 'runtests.py' with the --address parameter set to the Marionette server host and port like so:
python runtests.py --address=localhost:2828 tests/unit/test_execute_script.py
If you're using a device or b2g desktop
If you're using a different environment, you can run it using the following command. If you're using a phone with marionette, you'll need first run 'adb forward tcp:2828 tcp:2828' before doing this to make sure the port is forwarded: python runtests.py --address=localhost:2828 tests/unit/test_execute_script.py
python runtests.py --address=localhost:2828 tests/unit/test_execute_script.py
Parts of the Codebase
Server
If you're working on the server code, all the marionette bits you need live in (mozilla-central)/testing/marionette/ as .js files.
Once you've made changes, you can build them into your version of firefox by running:
make -C (objdir)/testing/marionette
where (objdir) is the path to your object directory.
If you've updated your repository since you last built (ie: if you ran 'hg pull -u' or 'hg pull' and 'hg update'), then you'll need to rebuild:
cd (mozilla-central) ./mach build
where (mozilla-central) is the top of your mozilla-central repository
Important Concepts
Essentially, in the browser, there are two places you can interact with: 'content' and 'chrome'. Content is the websites you interact with, all the html and the webpage's DOM.
Chrome is the browser specific stuff like the navigation bar and the scrollbar, ie, the things that live outside of the webpage itself. Code that is executed here has many privileges, privileges that code in content space doesn't have access to, like creating local files.
Marionette can run commands against the content of a webpage and against the chrome, ie: the browser part of the webpage. The client can send commands to either the content or the chrome of a window. The server is able to manage that using two components: marionette-server.js and marionette-listener.js
marionette-server.js is what manages all the 'chrome' facing code. This is where the client connection is managed, and where any commands that's being executed against the chrome of a webpage gets handled. If the client wishes to execute commands against the content, then marionette-server.js sends the command to marionette-listener.js to be handled.
marionette-listener.js is a file loaded per window, and it handles all content commands sent to this window.
Client and Test Harness
If you're working on the client code, you'll be working in (mozilla-central)/testing/marionette/client/
If you're working on the test harness (a.k.a. the Marionette Python test runner), you'll be in (mozilla-central)/testing/marionette/harness/. Key classes include BaseMarionetteTestRunner, BaseMarionetteArguments, MarionetteTestCase and MarionetteHarness.
Marionette Harness Unit Tests
There are pytest-style unit tests under (mozilla-central)/testing/marionette/harness/tests/harness_unit that excercise the harness code.
The easiest way to run these tests locally is with ./mach python-test. For example:
./mach python-test --path-only testing/marionette/harness/marionette/tests/harness_unit
If you don't want to use mach (because you need to pass extra arguments to py.test or otherwise customize it, say), you can install the requirements yourself and run py.test directly:
# First, create/activate a virtualenv cd testing/config/ pip install -r marionette_harness_test_requirements.txt # If you're going to be editing the client or anything else, make sure to install those packages in development mode (pip install -e /path/to/package) # For example... grep ^\\. marionette_harness_test_requirements.txt | while read line; do pip install -e $line; done # Run the tests cd ../marionette/harness/ py.test --verbose marionette/tests/harness_unit/
In automation, the harness tests are only scheduled whenever anything under (mozilla-central)testing/marionette/harness changes. That is, if you push to try you don't need to include a job name for these tests in your try syntax. If you want to run only the Marionette Harness Tests on a try push that includes harness changes, use this try syntax to narrow down to TaskCluster jobs on Linux64: -- this should prevent you from triggering any unnecessary build jobs.
Style Guide
Javascript
Please follow the style of the file you're working on. We use a "tab width" of 2 spaces (we do not use actual tabs).
Python
We attempt to follow the PEP-8 style guide, but in general, follow the style of the file you're working on. We use a "tab width" of 4 spaces (we do not use actual tabs).