forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			176 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
Performance scripts
 | 
						|
===================
 | 
						|
 | 
						|
Performance scripts are programs that drive the browser to run a specific
 | 
						|
benchmark (like a page load or a lower level call) and produce metrics.
 | 
						|
 | 
						|
We support two flavors right now in `perftest` (but it's easy to add
 | 
						|
new ones):
 | 
						|
 | 
						|
- **xpcshell** a classical xpcshell test, turned into a performance test
 | 
						|
- **browsertime** a browsertime script, which runs a full browser and controls
 | 
						|
  it via a Selenium client.
 | 
						|
 | 
						|
In order to qualify as performance tests, both flavors require metadata.
 | 
						|
 | 
						|
For our supported flavors that are both Javascript modules, those are
 | 
						|
provided in a `perfMetadata` mapping variable in the module, or in
 | 
						|
the `module.exports` variable when using Node.
 | 
						|
 | 
						|
This is the list of fields:
 | 
						|
 | 
						|
- **owner**: name of the owner (person or team) [mandatory]
 | 
						|
- **author**: author of the test
 | 
						|
- **name**: name of the test [mandatory]
 | 
						|
- **description**: short description [mandatory]
 | 
						|
- **longDescription**: longer description
 | 
						|
- **options**: options used to run the test
 | 
						|
- **supportedBrowsers**: list of supported browsers (or "Any")
 | 
						|
- **supportedPlatforms**: list of supported platforms (or "Any")
 | 
						|
- **tags** a list of tags that describe the test
 | 
						|
 | 
						|
Tests are registered using tests manifests and the **PERFTESTS_MANIFESTS**
 | 
						|
variable in `moz.build` files - it's good practice to name this file
 | 
						|
`perftest.ini`.
 | 
						|
 | 
						|
Example of such a file: https://searchfox.org/mozilla-central/source/testing/performance/perftest.ini
 | 
						|
 | 
						|
 | 
						|
xpcshell
 | 
						|
--------
 | 
						|
 | 
						|
`xpcshell` tests are plain xpcshell tests, with two more things:
 | 
						|
 | 
						|
- the `perfMetadata` variable, as described in the previous section
 | 
						|
- calls to `info("perfMetrics", ...)` to send metrics to the `perftest` framework.
 | 
						|
 | 
						|
Here's an example of such a metrics call::
 | 
						|
 | 
						|
    # compute some speed metrics
 | 
						|
    let speed = 12345;
 | 
						|
    info("perfMetrics", { speed });
 | 
						|
 | 
						|
 | 
						|
Browsertime
 | 
						|
-----------
 | 
						|
 | 
						|
With the browsertime layer, performance scenarios are Node modules that
 | 
						|
implement at least one async function that will be called by the framework once
 | 
						|
the browser has started. The function gets a webdriver session and can interact
 | 
						|
with the browser.
 | 
						|
 | 
						|
You can write complex, interactive scenarios to simulate a user journey,
 | 
						|
and collect various metrics.
 | 
						|
 | 
						|
Full documentation is available `here <https://www.sitespeed.io/documentation/sitespeed.io/scripting/>`_
 | 
						|
 | 
						|
The mozilla-central repository has a few performance tests script in
 | 
						|
`testing/performance` and more should be added in components in the future.
 | 
						|
 | 
						|
By convention, a performance test is prefixed with **perftest_** to be
 | 
						|
recognized by the `perftest` command.
 | 
						|
 | 
						|
A performance test implements at least one async function published in node's
 | 
						|
`module.exports` as `test`. The function receives two objects:
 | 
						|
 | 
						|
- **context**, which contains:
 | 
						|
 | 
						|
  - **options** - All the options sent from the CLI to Browsertime
 | 
						|
  - **log** - an instance to the log system so you can log from your navigation script
 | 
						|
  - **index** - the index of the runs, so you can keep track of which run you are currently on
 | 
						|
  - **storageManager** - The Browsertime storage manager that can help you read/store files to disk
 | 
						|
  - **selenium.webdriver** - The Selenium WebDriver public API object
 | 
						|
  - **selenium.driver** - The instantiated version of the WebDriver driving the current version of the browser
 | 
						|
 | 
						|
- **command** provides API to interact with the browser. It's a wrapper
 | 
						|
  around the selenium client `Full documentation here <https://www.sitespeed.io/documentation/sitespeed.io/scripting/#commands>`_
 | 
						|
 | 
						|
 | 
						|
Below is an example of a test that visits the BBC homepage and clicks on a link.
 | 
						|
 | 
						|
.. sourcecode:: javascript
 | 
						|
 | 
						|
    "use strict";
 | 
						|
 | 
						|
    async function setUp(context) {
 | 
						|
      context.log.info("setUp example!");
 | 
						|
    }
 | 
						|
 | 
						|
    async function test(context, commands) {
 | 
						|
        await commands.navigate("https://www.bbc.com/");
 | 
						|
 | 
						|
        // Wait for browser to settle
 | 
						|
        await commands.wait.byTime(10000);
 | 
						|
 | 
						|
        // Start the measurement
 | 
						|
        await commands.measure.start("pageload");
 | 
						|
 | 
						|
        // Click on the link and wait for page complete check to finish.
 | 
						|
        await commands.click.byClassNameAndWait("block-link__overlay-link");
 | 
						|
 | 
						|
        // Stop and collect the measurement
 | 
						|
        await commands.measure.stop();
 | 
						|
    }
 | 
						|
 | 
						|
    async function tearDown(context) {
 | 
						|
      context.log.info("tearDown example!");
 | 
						|
    }
 | 
						|
 | 
						|
    module.exports = {
 | 
						|
        setUp,
 | 
						|
        test,
 | 
						|
        tearDown,
 | 
						|
        owner: "Performance Team",
 | 
						|
        test_name: "BBC",
 | 
						|
        description: "Measures pageload performance when clicking on a link from the bbc.com",
 | 
						|
        supportedBrowsers: "Any",
 | 
						|
        supportePlatforms: "Any",
 | 
						|
    };
 | 
						|
 | 
						|
 | 
						|
Besides the `test` function, scripts can implement a `setUp` and a `tearDown` function to run
 | 
						|
some code before and after the test. Those functions will be called just once, whereas
 | 
						|
the `test` function might be called several times (through the `iterations` option)
 | 
						|
 | 
						|
 | 
						|
Hooks
 | 
						|
-----
 | 
						|
 | 
						|
A Python module can be used to run functions during a run lifecycle. Available hooks are:
 | 
						|
 | 
						|
- **before_iterations(args)** runs before everything is started. Gets the args, which
 | 
						|
  can be changed. The **args** argument also contains a **virtualenv** variable that
 | 
						|
  can be used for installing Python packages (e.g. through `install_package <https://searchfox.org/mozilla-central/source/python/mozperftest/mozperftest/utils.py#115-144>`_).
 | 
						|
- **before_runs(env)** runs before the test is launched. Can be used to
 | 
						|
  change the running environment.
 | 
						|
- **after_runs(env)** runs after the test is done.
 | 
						|
- **on_exception(env, layer, exception)** called on any exception. Provides the
 | 
						|
  layer in which the exception occured, and the exception. If the hook returns `True`
 | 
						|
  the exception is ignored and the test resumes. If the hook returns `False`, the
 | 
						|
  exception is ignored and the test ends immediatly. The hook can also re-raise the
 | 
						|
  exception or raise its own exception.
 | 
						|
 | 
						|
In the example below, the `before_runs` hook is setting the options on the fly,
 | 
						|
so users don't have to provide them in the command line::
 | 
						|
 | 
						|
    from mozperftest.browser.browsertime import add_options
 | 
						|
 | 
						|
    url = "'https://www.example.com'"
 | 
						|
 | 
						|
    common_options = [("processStartTime", "true"),
 | 
						|
                      ("firefox.disableBrowsertimeExtension", "true"),
 | 
						|
                      ("firefox.android.intentArgument", "'-a'"),
 | 
						|
                      ("firefox.android.intentArgument", "'android.intent.action.VIEW'"),
 | 
						|
                      ("firefox.android.intentArgument", "'-d'"),
 | 
						|
                      ("firefox.android.intentArgument", url)]
 | 
						|
 | 
						|
 | 
						|
    def before_runs(env, **kw):
 | 
						|
        add_options(env, common_options)
 | 
						|
 | 
						|
 | 
						|
To use this hook module, it can be passed to the `--hooks` option::
 | 
						|
 | 
						|
    $  ./mach perftest --hooks hooks.py perftest_example.js
 | 
						|
 | 
						|
 |