Jump to content

Como gerar cobertura de código no Cypress para o SonarQube


Postagens Recomendadas

Instalação e uso do Cypress

Primeiramente, é necessária a instalação do Cypress no seu projeto Node.js como uma devDependency:

npm install -D Cypress 

Para executar o Cypress diretamente da raiz do seu projeto, adicione os dois scripts no package.json. O primeiro abrirá a GUI do Cypress, enquanto que o segundo rodará todos os testes do projeto em modo silencioso.

{
  "scripts": {
    "cypress:open": "cypress open",
    "cypress:run": "cypress run"
  }
}

Após a adição, execute o comando abaixo definido para abrir o Cypress.  Caso seja a primeira vez que esteja usando o Cypress, o Launchpad do programa será exibido para guiar as decisões de projeto e configurações de tarefas que devem ser definidas antes do primeiro código ser escrito.

npm run cypress:open

Instrumentalização do código

Para calcular a taxa de cobertura em testes E2E no Cypress, é preciso primeiramente instrumentalizar o código do projeto.  A instrumentalização do código é definida como a inserção de contadores adicionais no código-fonte de um projeto antes do tempo de execução. E é por meio desses contadores que o Cypress realiza a computação das linhas do código-fonte que foram executadas durante a realização dos testes e gera o total de cobertura da aplicação.

O Cypress em si não faz a instrumentalização do código. Ela deve ser feita usando o módulo nyc ou o plugin babel-plugin-istanbul durante a transpilação do código de um projeto que use Babel. Nesse tutorial, será descrito como gerar código instrumentado com o babel-plugin-istanbul. Maiores informações sobre a instrumentalização e a cobertura de código do Cypress estão disponíveis na sua documentação.

Adicione em seu projeto as seguintes dependências:

npm install -D @babel/core @babel/preset-react babel-plugin-istanbul babel-plugin-transform-class-properties

Em seguida, crie um arquivo babel.config.js na raiz do repositório do seu projeto, com as configurações abaixo. O if é usado para garantir que o preset e os plugins necessários sejam inseridos apenas durante a fase de testes, já que não há a necessidade de instrumentalizar código em outros ambientes.

module.exports = function (api) {
    api.cache(true);

    let presets = []
    let plugins = []

    if (process.env.test) {
        presets = [
            "@babel/preset-react"
        ]

        plugins = [
            "transform-class-properties",
            "istanbul"
        ]
    }

    return {
        presets,
        plugins
    };
}

Para confirmar se o código foi instrumentalizado, suba a aplicação. Lembre-se que, para o exemplo acima é preciso definir process.env como teste.

Abra o console do navegador (do seu próprio navegador, e não o que o Cypress abre para rodar os testes), digite window.__coverage__ e aperte Enter. Caso apareçam dados como na imagem abaixo, o código do seu projeto foi instrumentalizado com sucesso 🎉

 

image.png

 

Cobertura de Código E2E

Para gerar cobertura de código durante a execução dos testes, o Cypress utiliza o plugin cypress/code-coverage. Ele faz o merge da cobertura individual obtida em cada teste, salva esse resultado combinado e utiliza o nyc para gerar relatórios em HTML com esses dados de cobertura.

Primeiramente, instale o plugin com o comando:

npm install -D @cypress/code-coverage

Adicione os códigos a seguir nos respectivos arquivos da pasta do Cypress:

// cypress/support/e2e.js

import '@cypress/code-coverage/support'
 
// cypress/plugins/index.js

module.exports = (on, config) => {
  require('@cypress/code-coverage/task')(on, config)
  
  return config
}

Abra a GUI do Cypress e execute um dos testes do seu projeto. Se os comandos dos retângulos verdes na imagem abaixo estiverem presentes durante a execução do teste, então o plugin foi integrado corretamente e a cobertura está sendo gerada.

image.png

Quando o teste terminar de rodar, o arquivo JSON com o merge das coberturas será salvo na pasta nyc_output.  É desse arquivo JSON que podem ser gerados relatórios em diversos formatos, como texto, HTML e LCOV. O plugin também salva um relatório em HTML e um arquivo LCOV com todas as informações de cobertura na pasta coverage.

Geração de Relatórios para o SonarQube

O arquivo lcov.info gerado após o termino da execução dos testes contém informações como a porcentagem de cobertura de código em todo o projeto e ele deve ser enviado via sonarscanner para o SonarQube. Porém, para o Sonar contabilizar o total de testes existentes no projeto é preciso também do TestExecutionReport, que no caso do Cypress pode ser gerado por meio da lib cypress-sonarqube-reporter.

Primeiro, instale as dependências:

npm install -D cypress-sonarqube-reporter sonarqube-scanner

Em seguida, no arquivo cypress.json defina o sonarqube-reporter como reporter e configure as reporterOptions desejadas. Nesse exemplo, os relatórios .xml de cada teste serão salvos em coverage/xml-reports/.

// cypress.json

{
  "reporter": "cypress-sonarqube-reporter",
  "reporterOptions": {
    "overwrite": true,
    "preserveSpecsDir": false,
    "outputDir": "coverage/xml-reports/"
  }
}

Para que todos os .xml de cada teste sejam gerados corretamente, é preciso aplicar a função SpecTitle da lib nos títulos dos describes de todos os arquivos de testes existentes no seu projeto, como no exemplo abaixo:

Observação: se por alguma razão um mesmo arquivo de teste tiver dois ou mais describes que não estejam aninhados, é preciso aplicar o SpecTitle em cada um deles para funcionar corretamente.

// File: cypress/integration/Sample.spec.js
const specTitle = require("cypress-sonarqube-reporter/specTitle");
describe(specTitle("The root suite"), () => {
    it("Test case #1 (must pass)", () => {
        expect(true).to.be.true;
    });
    describe("A sub suite", () => {
        it("Test case #2 (must pass)", () => {
            expect(true).to.be.true;
        });
        it("Test case #3 (must fail)", () => {
            expect(true).to.be.false;
        });
    });
    describe("Another sub suite", () => {
        xit("Test case #4 (must be skipped)", () => {
            expect(true).to.be.false;
        });
        it("Test case #5 (must raise an error)", () => {
            undefined.toString();
        });
    });
});

describe(specTitle("Another root suite"), () => {
    it("Test case #4 (must pass)", () => {
        expect(true).to.be.true;
    });
});

Em seguida é preciso fazer o merge de todos os .xml de cada teste em um arquivo .xml único,  de nome sonar.xml nesse exemplo.

// cypress/plugins/index.js

module.exports = (on, config) => {
  require('@cypress/code-coverage/task')(on, config)
  
  on('after:run', (results) => {
    return require('cypress-sonarqube-reporter/mergeReports')(results, {
      mergeFileName: "sonar.xml"
    })
  })

  return config
}

Logo após, basta rodar todos os testes com o comando abaixo e se tudo foi configurado corretamente, o arquivo coverage/xml-reports/sonar.xml será gerado com sucesso.

npm run cypress:run

Agora, crie o arquivo sonar.js com as seguintes informações do seu repositório para o escaneamento e envio dos dados para o SonarQube:

const scanner = require('sonarqube-scanner')

scanner(
  {
    serverUrl : 'http://sonarqube.tecnospeed.local',
    token : '<token gerado no SonarQube para o seu projeto>',
    options: {
      'sonar.projectKey': '<project key do seu projeto>',
      'sonar.projectName': 'nome do seu projeto',
      'sonar.javascript.lcov.reportPaths': 'coverage/lcov.info',
      'sonar.testExecutionReportPaths': 'coverage/xml-reports/sonar.xml',
      'sonar.sources': 'src',
      'sonar.tests': 'cypress/integration'
    }
  },
  () => process.exit()
)

 

Stage de testes no Pipeline do Gitlab

Adicione no .gitignore as pastas criadas pelo sonarscanner e pelas dependências do gerador de cobertura do cypress:

coverage
.scannerwork
.nyc_output

Agora basta adicionar o script de execução dos testes do cypress e do sonar em um pipeline de testes no gitlab:

// .gitlab-ci.yml

stages:
  - test
  
test:
  image: cypress/browsers:node16.5.0-chrome94-ff93
  stage: test
  script:
    - npm set registry http://devdocker.tecnospeed.local:4873/
    - npm install
    - npm run cypress:run
  after_script:
    - node sonar.js

Se tudo correr bem após a execução do pipeline, a página de seu projeto no SonarQube será criada/atualizada com as informações relacionadas a cobertura e total de testes, duplicidades, bugs e etc. como no exemplo da imagem abaixo:

image.png

 

Referências:

https://docs.cypress.io/guides/tooling/code-coverage#Using-NYC

https://github.com/BBE78/cypress-sonarqube-reporter

  • Curtir 5
  • Amei 3
Link to comment
Compartilhe em outros sites

  • 2 months later...

Boa tardde. tudo bem?

eu estou com uma pequena duvida, porque não estou conseguindo instrumentalizar minha aplicação cypress....
independente do que eu faça

Eu fui até a parte em criar o babel.config.js, fiz tudo certinho, porém quando fui rodar o cypress, o window._coverage_ não deu 

 

Link to comment
Compartilhe em outros sites

1 hora atrás, Victor Eduardo Dias Pavesi disse:

Boa tardde. tudo bem?

eu estou com uma pequena duvida, porque não estou conseguindo instrumentalizar minha aplicação cypress....
independente do que eu faça

Eu fui até a parte em criar o babel.config.js, fiz tudo certinho, porém quando fui rodar o cypress, o window._coverage_ não deu 

 

Boa tarde Victor, tudo bem sim e com você?

Por gentileza, só confirma se você instalou todas as dependências citadas nessa parte do texto:

Em 05/08/2022 at 11:47, Kevin Silva disse:
npm install -D @babel/core @babel/preset-react babel-plugin-istanbul babel-plugin-transform-class-properties

 

 

E verifica também qual a versão do seu Node e das dependências acima? Aqui no meu projeto eu usei o node 16 e as dependências instaladas com as seguintes versões:

"@babel/core": "^7.16.5",
"@babel/preset-react": "^7.18.6",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-istanbul": "^6.1.1"

 

Outra coisa também, você fez a verificação do window.__coverage__ no seu navegador mesmo ou no navegador que o cypress abre para rodar os testes?

Link to comment
Compartilhe em outros sites

Eu estou com as mesmas configurações que o senhor, mesmas versões tudo perfeito!

Eu fiz o windows.__coverage__ no navegador que o cypress abre, não é este? 

E por sinal, esse babel.config.js precisa ser criado fora da pasta igual o cypress.config ou tem que ser dentro da pasta support por exemplo

 

 

Link to comment
Compartilhe em outros sites

Entendi Victor,

isso, o windows.__coverage__ tem que ser feito no seu navegador mesmo. No navegador que o Cypress chama vai aparecer undefined após dar o Enter.

E o arquivo babel.config.js tem que ser criado na raiz do repositório que nem o cypress.config 👍

 

Link to comment
Compartilhe em outros sites

Boa tarde!

Caso o seu projeto não esteja usando Vue.js +  Nuxt.js, você pode usar e definir o próprio NODE_ENV como "test". Daí no package.json você pode criar um script com essa configuração por exemplo:

"dev:test": "NODE_ENV=test comando_para_subir_a_aplicação_em_modo_dev"

Aí depois naquele trecho daria para deixar assim:

Em 05/08/2022 at 11:47, Kevin Silva disse:
if (process.env.NODE_ENV == "test") {
        presets = [
            "@babel/preset-react"
        ]

        plugins = [
            "transform-class-properties",
            "istanbul"
        ]
    }

 

 

Link to comment
Compartilhe em outros sites

  • 1 year later...

Bom dia. Tudo bom? Sou novo aqui no forum e estou tentando, usar o cypress com o sonarqube. Eu não ententi muito bom o passo  que diz: "Para confirmar se o código foi instrumentalizado, suba a aplicação. Lembre-se que, para o exemplo acima é preciso definir process.env como teste.". É para subir onde? No sonarqube? Poderia explicar por favor?

Link to comment
Compartilhe em outros sites

Uma outra duvida: "Posteriormente, basta rodar todos os testes com o comando abaixo e se tudo foi configurado corretamente, o arquivo coverage/xml-reports/sonar.xml será gerado com sucesso. Por fim, crie o arquivo sonar.js com as seguintes informações do seu repositório para o escaneamento e envio dos dados para o SonarQube:", Qual seria o comando? o arquivo sonar.js, em qual pasta coloco?

Link to comment
Compartilhe em outros sites

Em 10/11/2023 at 14:20, hamilton_desouza disse:

Uma outra duvida: "Posteriormente, basta rodar todos os testes com o comando abaixo e se tudo foi configurado corretamente, o arquivo coverage/xml-reports/sonar.xml será gerado com sucesso. Por fim, crie o arquivo sonar.js com as seguintes informações do seu repositório para o escaneamento e envio dos dados para o SonarQube:", Qual seria o comando? o arquivo sonar.js, em qual pasta coloco?

Bom dia Hamilton, tente rodar com o comando abaixo:

npm run cypress:run

 

E o arquivo sonar.js deve ficar na pasta raiz do seu projeto, ao lado de arquivos como o package.json.

  • Curtir 1
Link to comment
Compartilhe em outros sites

Crie uma conta ou entre para comentar 😀

Você precisa ser um membro para deixar um comentário.

Crie a sua conta

Participe da nossa comunidade, crie sua conta.
É bem rápido!

Criar minha conta agora

Entrar

Você já tem uma conta?
Faça o login agora.

Entrar agora


×
×
  • Create New...