Displaying Test Screenshots in GitHub Actions

Anthony RimetThibault Barrat
Anthony Rimet & Thibault BarratNovember 20, 2023
#github#js#tutorial

"It works on my machine." We have often used this sentence, particularly when working on integration tests. How can you debug an end-to-end (e2e) test that fails on the CI but works on your machine?

E2E test runners like Cypress and Playwright can take a screenshot in case of failure. So the challenge boils down to grabbing this screenshot in the workflow, and exposing it to developers to understand why the test failed. Thankfully, there is a solution: build artifacts. Let's explore how to accomplish this.

Cypress with Github Actions

To learn how to install Cypress, please visit the Cypress documentation. For the purpose of this article, I am basing my tests on Cypress examples:

describe('example todo application', () => {
    beforeEach(() => {
        cy.visit('<https://example.cypress.io/todo>');
    });

    it('displays two default items in the todo list', () => {
        cy.get('.todo-list li').should('have.length', 2);
        cy.get('.todo-list li')
            .first()
            .should('have.text', 'Pay electric bill');
        cy.get('.todo-list li')
            .last()
            .should('have.text', 'Walk the dog');
        cy.get('h1').should('have.text', 'TEST FAILED'); // THIS LINE WILL INTENTIONALLY FAIL THE TEST
    });
});

Once everything is set up, you can create a GitHub action associated with your project. In the .github/workflows/main.yml file, you can use the following code:

## Adapt this file to your current configuration
name: Cypress Tests
on: push

jobs:
    cypress-run:
        runs-on: ubuntu-22.04
        steps:
            - name: Checkout
              uses: actions/checkout@v4
            - name: Cypress run
              uses: cypress-io/github-action@v6

Now, you just need to push your changes to GitHub. The action will be triggered and you will be able to see the result in the Actions tab of your repository.

Cypress GitHub Action

As you can see, the test failed.

Cypress GitHub Action

However, the tests passed on my machine. How can I check what's different in the CI?

Displaying Screenshots on GitHub Actions

By default, Cypress automatically takes a screenshot in case of failure during the cypress run execution. Screenshots are stored in the cypress/screenshots folder, which you can modify in the configuration.

The following action step downloads the cypress/screenshots folder in case of an error, and creates a GitHub artifact with it. An artifact is a file or a collection of files generated during the execution of a workflow that we can share between different jobs.

- name: Upload screenshots
  uses: actions/upload-artifact@v3
  if: failure()
  with:
    name: cypress-screenshots
    path: cypress/screenshots

In case of failure, the link to the artifact appears on GitHub:

Cypress GitHub Action

If you download the file, you have a screenshot of the interface at the time of your error:

Action result

This trick helps to have a better visualization of what is happening during a failed test.

And Playwright ?

If you are using Playwright, you can use the same solution to display screenshots. To do this, you need to modify your configuration:

playwright.config.js

module.exports = defineConfig({
	...,
  use: {
    ...,
    screenshot: 'only-on-failure', // Take screenshot on failure
  },
  outputDir: './playwright/output', // Screnshoot folder, can be updated.

Then, create an github-action like this:

jobs:
    test:
        timeout-minutes: 60
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v3
            - uses: actions/setup-node@v3
              with:
                  node-version: 18
            - name: Install dependencies
              run: npm ci
            - name: Install Playwright Browsers
              run: npx playwright install --with-deps
            - name: Run Playwright tests
              run: npx playwright test
            - uses: actions/upload-artifact@v3
              if: always()
              with:
                  name: playwright-report
                  path: playwright-report/
                  retention-days: 30
            - uses: actions/upload-artifact@v3
              if: failure()      
              with:
                  name: playwright-output
                  path: playwright/output ## Folder used in playwright.config.js `outputDir`
                  retention-days: 30

Playwright also offers an automatic report that you can download!

Cypress Cloud

Having a screenshot is great, but it can be difficult to understand what is happening. To solve this problem, Cypress offers a cloud solution that allows you to see the execution of your tests in real time. You can also download the video of the execution. It's called Cypress Cloud. And the configuration is very simple:

Create an account on https://www.cypress.io/ and create a project. Add the project id inside the cypress.config.js

module.exports = {
  projectId: "t1odjw",
  // ...rest of the Cypress project config
}

Then, you will have access to a token that you can add to your GitHub secrets. Then, you can modify your GitHub action like this:

name: Cypress Tests
on: [push]
jobs:
  cypress-run:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Cypress run
        uses: cypress-io/github-action@v6
        with:
          record: true # Trigger the record for Cypress Cloud
          parallel: true
        env:
          CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Now each time your action is triggered, you will be able to see the execution of your tests in real time into your Cypress Cloud dashboard.

Cypress Cloud

Be careful, the Cypress Cloud is not free. You can find the pricing here.

Conclusion

Now you know how to display screenshots of your Cypress tests on GitHub Actions. This will allow you to better understand the errors that occur during your tests. You could say to your colleagues: "It works on my machine and on the CI" !

You can find the code of this article on GitHub

Nota Bene: This article talks about GitHub actions, but you can use the same solution with other CI like Gitlab CI. It has also an artifact system and an easy integration for GitLab.

Did you like this article? Share it!