Cloud Native Observability and Cypress - an Unlikely Marriage
Tags: observability, testing, cloudnative, cypress
Published: 2024-01-26 00:20:32

OpenTelemetry and distributed tracing are critical in enabling troubleshooting and monitoring of your complex, distributed, Cloud Native application.

Cypress is a powerful tool for testing front-end applications, enabling quick and confident releases of front-end changes. Imagine if you could combine Cypress with distributed traces.

Now you can! Use distributed traces directly in your Cypress tests to cover the entire distributed system, including both the front end and back end, with trace-based tests. Here’s how Tracetest and Cypress fell in love. 👇

## Tracetest ❤️ Cypress

The [Tracetest integration with Cypress](https://docs.tracetest.io/tools-and-integrations/cypress/) provides:

- **Full observability.** Cypress allows you to visually debug test runs. With a distributed trace captured with each test run, you will also have visibility of exactly what happened across the full front end and back end system.
- **Faster MTTR for failed tests.** Having full observability will allow you to quickly identify the root cause of failed tests, determine whether the problem is in the frontend or backend, and  easily identify the correct team to fix the problem. Armed with data from both Cypress and the distributed trace, the team correcting the bug will have the necessary information to find a solution quickly.
- **Actual end-to-end tests.** The industry sometimes calls front end tests ‘end to end’, but they are not. Frontend tests can fully test the front end, and even assert on values returned by API calls, but it cannot verify deeply. In today’s asynchronous, message-based architectures, an API calls often initiates a full process, but quickly returns a status code of 200 to say ‘we have the request’. It then relies on multiple backend systems, developed by different teams, to properly execute a flow. Checking that the full process works as expected is an actually end-to-end test. Trace-based tests leverage the visibility empowered by a distributed trace to allow assertions to be placed on the systems through out the flow, providing actual end-to-end testing.
- **Increased confidence to deploy.** With your ‘golden paths’ covered by real end-to-end tests, your teams can release with confidence, knowing the tests running as part of your CI/CD process are ensuring critical flows.

Well, the marriage has happened, and we would like to invite you to attend the reception party!

Tracetest, the leading trace-based test tool, now works directly with your current Cypress tests to fully test your instrumented application. Bring your favorite observability tracing backend, such as Jaeger, Tempo, Honeycomb, AWS X-ray, Dynatrace, Sumo Logic, or [9 others](https://tracetest.io/integrations) to the event, and let’s party!

{% embed https://www.youtube.com/watch?v=yDXoa8znTQQ %}

## Show Me The Wedding Photos!

Let’s look at the rich artifacts provided by these observability enabled Cypress tests.

First, you get the rich results provided by a Cypress test:

![https://res.cloudinary.com/djwdcmwdz/image/upload/v1705666619/Blogposts/cloud-native-observability-cypress-unlikely-marriage/cypress_zfzxsv.png](https://res.cloudinary.com/djwdcmwdz/image/upload/v1705666619/Blogposts/cloud-native-observability-cypress-unlikely-marriage/cypress_zfzxsv.png)

Second, you get a distributed trace, showing entire process flow provided by instrumentation in your frontend and backend:

![https://res.cloudinary.com/djwdcmwdz/image/upload/v1705666620/Blogposts/cloud-native-observability-cypress-unlikely-marriage/trace_dbzieq.png](https://res.cloudinary.com/djwdcmwdz/image/upload/v1705666620/Blogposts/cloud-native-observability-cypress-unlikely-marriage/trace_dbzieq.png)

Finally, using trace-based testing assertions, you can have your Cypress test also verify the proper execution of the full system:

![https://res.cloudinary.com/djwdcmwdz/image/upload/v1705666619/Blogposts/cloud-native-observability-cypress-unlikely-marriage/tracetest_ldqyae.png](https://res.cloudinary.com/djwdcmwdz/image/upload/v1705666619/Blogposts/cloud-native-observability-cypress-unlikely-marriage/tracetest_ldqyae.png)

As shown, trace-based tests can assert the following:

- Ensure the JavaScript bundle in the UI loads in less than 300 ms.
- All HTTP internal calls between systems returned a successful status code.
- Check to make sure a particular service received a message and processed it.
- See if a call to an external service returned the proper value.
- See if a particular, or all, database calls take less than 100 ms.

With these assertions created and included in the Cypress test, the test now can assert across the entire system, verifying both functionality and performance.

## What To Bring to the Reception Party?

There are a few requirements:

- Use Cypress for your frontend tests. If you use Playwright… stayed tuned for an upcoming event, as this particular party is not for you!
- Have observability, that hopefully works and plays well with the OpenTelemetry standard, configured for your backend systems so you can produce distributed traces.
- Use the OpenTelemetry browser instrumentation in your frontend app.
- Sign up for an account on [Tracetest](https://app.tracetest.io/) so you can run trace-based tests.
- See the instructions on how to [include Tracetest libraries in your Cypress tests](https://docs.tracetest.io/tools-and-integrations/cypress/).

The [instructions](https://docs.tracetest.io/tools-and-integrations/cypress/) provide a full example, with an instrument cloud native app, an OTel instrumented react front end, and Cypress tests with Tracetest included. This is an example of a Cypress test which includes a trace-based test:

```jsx
import Tracetest, { Types } from '@tracetest/cypress';

const TRACETEST_API_TOKEN = Cypress.env('TRACETEST_API_TOKEN') || '';

let tracetest: Types.TracetestCypress | undefined = undefined;

const definition = `
type: Test
spec:
  id: aW1wb3J0cyBhIHBva2Vtb24=
  name: imports a pokemon
  trigger:
    type: cypress
  specs:
  - selector: span[tracetest.span.type="http"] span[tracetest.span.type="http"]
    name: "All HTTP Spans: Status  code is 200"
    assertions:
    - attr:http.status_code   =   200
  - selector: span[tracetest.span.type="database"]
    name: "All Database Spans: Processing time is less than 100ms"
    assertions:
    - attr:tracetest.span.duration < 2s
  outputs:
  - name: MY_OUTPUT
    selector: span[tracetest.span.type="general" name="Tracetest trigger"]
    value: attr:name
`;

describe('Home', { defaultCommandTimeout: 60000 }, () => {
  before(done => {
    Tracetest({ apiToken: TRACETEST_API_TOKEN }).then(instance => {
      tracetest = instance;
      tracetest
        .setOptions({
          'imports a pokemon': {
            definition,
          },
        })
        .then(() => done());
    });
  });

  beforeEach(() => {
    cy.visit('/', {
      onBeforeLoad: win => tracetest.capture(win.document),
    });
  });

  // uncomment to wait for trace tests to be done
  after(done => {
    tracetest.summary().then(() => done());
  });

  it('create a pokemon', () => {
    cy.get('[data-cy="create-pokemon-button"]').should('be.visible').click();
    cy.get('[data-cy="create-pokemon-modal"]').should('be.visible');
    cy.get('#name').type('Pikachu');
    cy.get('#type').type('Electric');
    cy.get('#imageUrl').type('https://oyster.ignimgs.com/mediawiki/apis.ign.com/pokemon-blue-version/8/89/Pikachu.jpg');

    cy.get('button').contains('OK').click();
  });

  it('imports a pokemon', () => {
    cy.get('[data-cy="import-pokemon-button"]').click();
    cy.get('[data-cy="import-pokemon-form"]').should('be.visible');

    cy.get('[id="id"]')
      .last()
      .type(Math.floor(Math.random() * 101).toString());
    cy.get('button').contains('OK').click({ force: true });
  });

  it('deletes a pokemon', () => {
    cy.get('[data-cy="pokemon-list"]').should('be.visible');
    cy.get('[data-cy="pokemon-card"]').first().click().get('[data-cy="delete-pokemon-button"]').first().click();
  });
});
```

## Attending the Reception Party

[Tune in live for a webinar workshop on January 24th at 9am PT (12pm ET)](https://www.linkedin.com/events/7153780303713447937/comments/) to learn hands-on how to enhance your existing Cypress tests with trace-based testing!

{% embed https://www.youtube.com/watch?v=k0d_ap5jatU %}

## A Promising Union

With the combination of distributed tracing, Tracetest, and Cypress, true end-to-end tests that matches Martin Fowler’s definition, is finally achieved.

> *An end-to-end test verifies that a system meets external requirements and achieves its goals, testing the entire system, from end to end.*
> 

With these tests in place, your entire dev team can release at high velocity with greater confidence.

Want to see some examples of these Tracetest infused Cypress tests? We are running these tests in our demo environment. [Join the environment](https://app.tracetest.io/organizations/ttorg_2179a9cd8ba8dfa5/invites/invite_760904a64b4b9dc9/accept) and look at the three Cypress tests:

![https://res.cloudinary.com/djwdcmwdz/image/upload/v1705666756/Blogposts/cloud-native-observability-cypress-unlikely-marriage/testlist_zn8mxd.png](https://res.cloudinary.com/djwdcmwdz/image/upload/v1705666756/Blogposts/cloud-native-observability-cypress-unlikely-marriage/testlist_zn8mxd.png)

Have questions? Join the discussion with the matchmakers of this union in the [Tracetest Slack channel](https://dub.sh/tracetest-community)!