Create a new synthetic test
editCreate a new synthetic test
editThis functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.
Have a question? Want to leave feedback? Visit the Synthetics discussion forum.
Syntax
editTo write synthetic tests for your application, you’ll need to know basic JavaScript and Playwright syntax. Synthetics agent exposes a an API for creating and running tests:
-
journey(name, ({ page, browser, client, params }) => {})
— A journey tests one discrete unit of functionality. For example, logging into a website, adding something to a cart, or joining a mailing list. Each journey provides a fresh playwrightbrowser
,context
, andpage
instance. See Create ajourney
for more information. -
step(name, function)
— A journey consists of multiple steps, i.e., actions that should be completed in a specific order. Steps are displayed individually in the Uptime app for easy debugging and error tracking. -
beforeAll(function)
— Runs a provided function prior to alljourney
runs. If the provided function is a promise, the runner will wait for the promise to resolve before invoking the journey. This function is useful for setting up global state or a server that will be used across multiple journeys. -
before(function)
— Runs a provided function prior to a singlejourney
runs. This function is useful for setting up global state or a server that will be used for a single journey. -
afterAll(function)
— Runs a provided function after all the journeys have completed. This function is useful for removing global state or closing a server that was used in multiple journeys. -
after(function)
— Runs a provided function after a single journey has completed. This function is useful for removing global state or closing a server that was used in a single journey.
Playwright is browser testing library developed by Microsoft. It is reliable and fast and features a modern API that auto waits for page elements to be ready.
Create a journey
editThe journey
function takes a single parameter, name
,
and provides access to page
, params
, browser
, and context
:
-
browser
— A browser is created by Playwright. -
page
— Apage
object from Playwright that lets you control the browser’s current page. -
context
— A browser context that doesn’t share cookies or cache with other browser contexts. -
params
— User-defined variables that allow you to invoke the Synthetics suite with custom parameters. For example, if you want to use a different homepage depending on theenv
(localhost fordev
, and a URL forprod
).
See the official Playwright API documentation for more information.
Putting it all together, a basic, two step journey might look something like this:
journey("Journey name", async ({page}) => { step("Step 1 name", async () => { // Do something here }) step("Step 2 name", async () => { // Do something else here }) });
Create a step
editSteps can be as simple or complex as you need them to be. The Playwright page API reference will be your friend while writing tests.
A basic first step might simply load a page:
See the |
A more complex second step might wait for a page element to be selected, and then ensure that it matches an expected value. Consider the following HTML snippet:
<header class="header"> <h1>todos</h1> <input class="new-todo" autofocus autocomplete="off" placeholder="What needs to be done?" </header>
You can verify that new-todo
class element contains the expected placeholder
(input hint)
with the following test:
step("Check placeholder text", async () => { const input = await page.$('input.new-todo'); deepStrictEqual(await input.getAttribute('placeholder'), "What needs to be done?"); })
Query the page for the |
|
Return the |
Sample Synthetic test
editA complete example of a basic synthetic test looks like this:
import { journey, step } from '@elastic/synthetics'; import { deepStrictEqual } from 'assert'; journey("Ensure placeholder is correct", async ({page}) => { step("Go to elastic.co", async () => { await page.goto('https://www.elastic.co'); }) step("Check placeholder text", async () => { const input = await page.$('input.new-todo'); deepStrictEqual(await input.getAttribute('placeholder'), "What needs to be done?"); }) });
Running synthetic tests
editAs explained in the quickstart, there are two ways to run synthetic tests:
-
Run as an inline journey — copy/paste into
heartbeat.yml
- Run a test suite — import your tests into Heartbeat
Which option is right for you? That depends.
If you want to invoke a single journey with few steps, an inline journey might be the easiest workflow — you only need paste your tests into your heartbeat.yml
file.
if you have a complex test suite, or your tests need to live with your application code,
you’re likely better off setting up a synthetic test suite.
Run an inline journey
editThe easiest way to run a synthetic test is by creating an inline journey.
The journey
keyword isn’t required, and access to variables like page
and params
is automatic.
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.
You don’t need to worry about anything else.
An example, short.js
, is provided in the
elastic/synthetics GitHub repository:
// test-homepage-hover.js 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 this, or any other inline example locally, change into the directory of your test,
and pipe the file contents to the npx @elastic/synthetics
command.
For example:
cat examples/inline/short.js | npx @elastic/synthetics --inline
If everything works as expected, you’ll get the following response:
Journey: inline ✓ Step: 'load homepage' succeeded (1831 ms) ✓ Step: 'hover over products menu' succeeded (97 ms) 2 passed (2511 ms)
The script can then be copied into your in your heartbeat.yml
:
heartbeat.monitors: - type: browser id: my-monitor name: My Monitor schedule: "@every 1m" 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]'); });
That’s it! You can either spin up Heartbeat yourself, or jump to Step 3: Run run.sh
of the Quickstart to use the provided Docker project template.
Run a test suite
editIf you have a suite of tests you’d like to implement, you can use Elastic synthetics as a library.
In this method, you use Docker to run both Heartbeat and elastic-synthetics
.
Install the @elastic/synthetics
package globally to get started:
npm install -g @elastic/synthetics
Now it’s time to write your tests:
- Create a new NPM/Node.js project.
-
Create a
javascript
ortypescript
file that imports your tests. All synthetic test files must use the.journey.ts
or.journey.js
file extension. - Compile everything together.
At Elastic, we’re fans of examples, so one is provided in the elastic/synthetics repository. If you’d like to test it locally, clone the repo, and install the example:
# Check out the synthetics repo and included examples git clone git@github.com:elastic/synthetics.git &&\ cd synthetics/examples/todos/ &&\ # Install all required dependencies for the todos example npm install
You are now inside the a synthetics test-suite, which is also an NPM project.
You can now run the provided tests; all files matching the filename *.journey.*
will be run.
Please note, you must run the following commands from within the examples/todos
folder.
The todos
folder has its own package.json
, which makes it its own NPM project. If you
run these commands outside the todos
folder you can run into confusing situations with
NPM’s module resolution that can cause this command to not work.
# Run tests on the current directory. Please note the dot `.` which indicates # that we want to run tests on the current directory npx @elastic/synthetics .
Once you have your tests up and running, follow the steps in the quickstart guide to integrate with the provided Docker project template. You’ll need to write some additional orchestration to get Heartbeat on a box, pull your source of tests, and share it with Heartbeat.