Configurar o SonarCloud para um projeto usando Mocha e Istambul - fga-eps-mds/A-Disciplina-MDS-EPS GitHub Wiki
Como configurar o SonarCloud para um projeto JavaScript utilizando Mocha e Istambul
Histórico de Revisão
Data | Versão | Descrição | Revisor |
---|---|---|---|
18/11/2021 | 1.0 | Versão Inicial | Gabriel Marques Tiveron |
O que será usado
- Github Actions
- Node
- SonarCloud
- Mocha
- Istambul
- Python
Passo 1 - Adicionar modo de execução de testes
Para que haja um funcionamento adequado das funções é necessário que a execução dos testes seja feita através do seguinte comando
nyc --reporter=cobertura --reporter=text mocha **caminho_para_arquivos_teste** --recursive --reporter mocha-junit-reporter
Dessa forma, serão gerados dois arquivos após a execução dos testes, um do Mocha, onde será extraída a cobertura dos testes e outro do Istambul, onde será extraída as metricas de tempo de execução dos testes e sucesso. Esse comando pode ser adicionado no package.json
do projeto.
Passo 2 - Adicionar Secret no repositório
Para que se possa retornar o arquivo de métricas para o repositório, é necessário que sejam definidos secrets no mesmo. Para isso, basta seguir os seguintes passos:
- Na página principal do repositório acesse Settings
- Acesse a aba Secrets
- Crie secrets com o e-mail e o username do GitHub que tenha acesso ao repositório.
Obs: Os nomes dos secrets devem estar exatamente como na imagem, ou devem ser alterados quando utilizados no passo 4.
Passo 3 - Parser de métricas Mocha / Istambul
import xmltodict, json
import requests
import sys
import re
from datetime import datetime
TODAY = datetime.now()
METRICS_SONAR = [
# lista de métricas do SonarCloud
]
BASE_URL = 'https://sonarcloud.io/api/measures/component_tree?component='
def read_xml(path):
with open(path) as xml_file:
data = xmltodict.parse(xml_file.read())
return json.loads(json.dumps(data))
def testing(df, coverage):
for suite in coverage['coverage']['packages']['package']:
_class = suite['classes']['class']
try:
df[_class['@filename']]['coverage'] = float(_class['@line-rate']) * 100
except:
pass
def get_test_obj(path_time, path_coverage):
time = read_xml(path_time)
coverage = read_xml(path_coverage)
df = {}
for suite in time['testsuites']['testsuite']:
name = suite['@name']
tests = suite['@tests']
time = suite['@time']
try:
success_density = (int(tests) - int(suite['@failures'])) / int(tests)
except:
success_density = 0
if name == 'Root Suite':
continue
name = name.split('->')[0].replace(" ", "")
if name not in df:
df[name] = { 'test_execution_time': float(time), 'tests': int(tests), 'test_success_density': success_density }
else:
df[name]['test_execution_time'] += float(time)
df[name]['tests'] += int(tests)
testing(df, coverage)
return df
if __name__ == '__main__':
REPO = sys.argv[1] # REPO name Ex.: fga-eps-mds_2021-1-PUMA-UserService
# Get metrics from Sonar Cloud
response = requests.get(f'{BASE_URL}{REPO}&metricKeys={",".join(METRICS_SONAR)}&ps=500')
path_time = # caminho para o arquivo test-results.xml
path_coverage = # caminho para o arquivo cobertura-coverage.xml
df = get_test_obj(path_time, path_coverage)
file_path = f'./{REPO}-{TODAY.strftime("%m-%d-%Y-%H-%M")}.json'
j = json.loads(response.text)
for component in j['components']:
path = component['path']
if path in df.keys():
for key in df[path].keys():
component['measures'].append({ 'metric': key, 'value': df[path][key] })
with open(file_path, 'w') as fp:
fp.write(json.dumps(j))
fp.close()
Passo 4 - Configurar workflow no GitHub Actions
Crie um arquivo chamado .github/workflows/<nome_do_arquivo>.yml
com o seguinte conteúdo:
name: <<nome do workflow>>
on:
push:
branches:
- <<branch alvo do workflow>>
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: testexec
id: tests
run: |
<< executar a rotina de testes do repositório >>
- name: collect
id: metrics
run: |
pip3 install xmltodict
python3 test_coverage.py fga-eps-mds_${{ github.event.repository.name }}
<< Nesse ponto haverá um arquivo JSON com as metricas de testes juntamente com as
métricas do SonarCloud, basta então enviálas para onde desejar >>
Obs: Um exemplo dessa rotina pode se conferida neste link.
Para cada projeto há sua individualidade, para a execução dos testes ou para onde enviar o json gerado do sonar.