Run synthetic tests

edit

There are two ways to run synthetic tests:

  • If you have more than one journey, rely on dependencies, or your tests need to live with your application code, use a test suite.
  • If you want to create a single journey and manage it individually, use an inline monitor.
Use a test suite
edit

A test suite can contain any number of journeys in any number of files using the file extensions .journey.ts or .journey.js. You can use the @elastic/synthetics package as a library to run a test suite.

To test a test suite locally, start by writing your tests:

  1. Create a new NPM/Node.js project.
  2. Create a javascript or typescript file that imports your tests (using the .journey.ts or .journey.js file extension).
  3. Make sure any dependencies are defined with an import outside of the journey object.
  4. Compile everything together.

See an example of a test suite in the elastic/synthetics-demo repository. The examples below show how to test that repository’s todo directory locally.

Clone the repository, change into the directory containing the synthetics test suite, and install the necessary dependencies including @elastic/synthetics:

# Check out the synthetics repo and included examples
git clone git@github.com:elastic/synthetics-demo.git &&\
cd synthetics-demo/todos/ &&\
# Install all required dependencies for the todos example
npm install

If you want to test your own suite locally, be sure to install the @elastic/synthetics package:

npm install -g @elastic/synthetics

From inside the directory containing the synthetics test suite, run the provided tests. By default, the elastic-synthetics runner will only run files matching the filename *.journey.(ts|js)*.

# Run tests on the current directory. The dot `.` indicates
# that it should run all tests in the current directory.
npx @elastic/synthetics .
Send to Elastic Stack
edit

After testing locally, you can run the test suite using the Elastic Synthetics integration or Heartbeat depending on the approach you chose to set up.

Copy and paste the path to your zip file into heartbeat.yml. For a full list of configuration options, see Browser options in the Heartbeat documentation.

- name: Todos
  id: todos
  type: browser
  schedule: "@every 1m"
  params:
    target_url: "https://elastic.github.io/synthetics-demo/" 
  source:
    zip_url: 
      url: "https://github.com/elastic/synthetics-demo/archive/refs/heads/main.zip" 
      folder: "todos/synthetics-tests" 
      username: "" 
      password: ""

The params section lets you define custom parameters to use in your script. In this example the target_url parameter is used by the test suite to determine which site to test.

In this example, our library of synthetic tests is downloaded from the remote zip endpoint for our todos example.

Note that the url refers to the endpoint where the test project exists.

Folder refers to the relative path where the synthetic journey files are located. Heartbeat will invoke the synthetics library on this folder.

Username and password are blank here, but if provided, will be sent as HTTP Basic Authentication headers to the remote zip endpoint.

Use an inline monitor
edit

An inline monitor is a single journey that you manage individually. When writing an inline monitor, the journey keyword isn’t required, and variables like page and params will be part of your script’s scope.

To create an inline monitor, copy the steps from inside a journey and paste it into Kibana or your Heartbeat configuration.

Inline monitors can be quick to set up, but can also be more difficult to manage. Each inline monitor can contain only one journey, which must be maintained directly in Kibana or in your Heartbeat configuration file.

If you depend on external packages, have your journeys next to your code repository, or wish to embed and manage more than one journey from a single monitor configuration use a test suite.

Test locally
edit

To test the inline monitor’s journey locally, change into your test’s directory and pipe the journey’s contents to the npx @elastic/synthetics command.

Assume, for example, that your inline monitor includes the following code:

step('load homepage', async () => {
    await page.goto('https://www.elastic.co');
});
step('hover over products menu', async () => {
    await page.hover('css=[data-nav-item=products]');
});

To run that journey locally, you can save that code to a file and pipe the file’s contents into @elastic-synthetics:

cat path/to/sample.js | npx @elastic/synthetics --inline

And you’ll get a response like the following:

Journey: inline
   ✓  Step: 'load homepage' succeeded (1831 ms)
   ✓  Step: 'hover over products menu' succeeded (97 ms)

 2 passed (2511 ms)
Send to Elastic Stack
edit

After testing locally, you can copy the script into your Elastic Synthetics integration or heartbeat.yml depending on the approach you chose to set up.

Copy and paste your test steps into heartbeat.yml. Heartbeat spawns a separate Node.js process, schedules your tests, and runs them on a Chromium browser.

For a full list of configuration options, see Browser options in the Heartbeat documentation.

- type: browser
  id: elastic-website 
  name: Elastic website
  schedule: "@every 1m"
  source:
    inline:
      script: |- 
      step("load homepage", async () => {
        await page.goto('https://www.elastic.co');
      });
      step("hover over products menu", async () => {
        await page.hover('css=[data-nav-item=products]');
      });

Each monitor gets its own ID in the Uptime app and its own schedule entry. This allows tests to be run in parallel and analyzed separately.

In this example, a synthetic journey is defined inline. This is a two-step script that first loads a homepage and then hovers over a product menu. See Write a synthetic test for more information.

Run on CI
edit

You can also run a synthetic test suite on your CI environment. Elastic’s synthetics runner can output results in a few different formats, including JSON and JUnit (the standard format supported by most CI platforms).

If any of your journeys fail, the synthetics agent it will yield a non-zero exit code, which most CI systems pick up as a failure by default.

You can see an example using GitHub Actions in the elastic/synthetics-demo repository. This example sets up a job that executes the synthetics runner and tells the runner to yield results in a JUnit format.