Escolar Documentos
Profissional Documentos
Cultura Documentos
Natal-RN
Agosto 2021
José Gameleira do Rêgo Neto
Linha de pesquisa:
Engenharia de Software
Orientador
Prof. Dr. Uirá Kulesza
Natal-RN
Agosto 2021
Universidade Federal do Rio Grande do Norte - UFRN
Sistema de Bibliotecas - SISBI
Catalogação de Publicação na Fonte. UFRN - Biblioteca Setorial Prof. Ronaldo Xavier de Arruda - CCET
Natal-RN, 13/08/2021
Dedico esse trabalho a toda minha família, meu orientador e meus colegas de grupo de
pesquisa. Sem o suporte dessas pessoas, eu não conseguiria ter chegado até aqui.
Agradecimentos
Alan Turing
Entendendo a Relação entre Integração Contínua e
Cobertura de Testes: Um Estudo Empírico
Resumo
Abstract
1 Grupos do datasetCI . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 46
4 Grupos do datasetCoverallsCI . . . . . . . . . . . . . . . . . . . . . . p. 56
CI – Continuous Integration
1 Introdução p. 15
2 Fundamentação Teórica p. 20
2.4 Coveralls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 24
3 Configurações do Estudo p. 27
3.2.1 DatasetCI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 28
3.2.4 DatasetCoveralls . . . . . . . . . . . . . . . . . . . . . . . . . . p. 31
3.4 Considerações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 45
4 Resultados p. 46
5 Trabalhos Relacionados p. 60
6 Considerações finais p. 64
Referências p. 69
Apêndice A -- DatasetCI p. 73
Apêndice D -- DatasetCoveralls p. 81
1 Introdução
A qualidade de software é uma área que vem sendo amplamente estudada na engenha-
ria de software (CROWSTON; ANNABI; HOWISON, 2003). Tal investigação fornece diversas
medidas de qualidade de software, incluindo compreensibilidade, integridade, concisão,
portabilidade, consistência, capacidade de manutenção, testabilidade, usabilidade, con-
fiabilidade, estrutura e eficiência (BOEHM; BROWN; LIPOW, 1976) (GORTON; LIU, 2002).
Diversos trabalhos discorrem sobre como a qualidade, entre elas a de código, impactam
no sucesso do software (CHOW; CAO, 2008) (LEE; KIM; GUPTA, 2009) (REEL, 1999).
Em projetos open source existe a necessidade que o seu código fonte seja rigorosamente
modular, independente e autoexplicativo (STAMELOS et al., 2002). Outra razão para obter
código de alta qualidade de um projeto de código aberto é o fato de que a próxima
etapa pode ser a iniciação (fork ) de uma extensão fechada do projeto, necessitando que
os requisitos sejam melhor definidos, demandas de design e documentação sejam mais
rigorosas, e isso exige um código de alta qualidade (STAMELOS et al., 2002).
A integração contínua (CI - continuous integration) é uma prática que busca contribuir
para a qualidade do software. Entretanto, é necessário investigar quais os aspectos de CI
que mais impactam na manutenção ou melhoria da qualidade do código fonte. CI pode
trazer a falsa impressão de que apenas gerar builds/ é suficiente para atingir um alto nível
de qualidade no código (NERY, 2020). Um dos objetivos de CI é o aumento da cobertura
17
de testes a cada nova mudança, mas também manter o conjunto de testes rápido (MEYER,
2014). Dessa forma, além de automatizar os testes, em teoria a prática de CI pode acarretar
o aumento de cobertura do código.
Quando um projeto adota integração contínua, o ideal é que ele se beneficie de todas
as vantagens que essa prática apresenta. Entretanto, muitos projetos podem não adotar
CI completamente, principalmente a parte de testes automatizados, já que existe um custo
associado a produção dos mesmos (LI et al., 2019).
Este trabalho propõe a condução de um estudo empírico que busca entender o impacto
que a adoção de integração contínua na cobertura dos testes. Em um primeiro momento,
nós investigamos as tendências de cobertura de código ao longo do tempo de um grupo
de 30 projetos que adotaram integração contínua (projetos CI) e de projetos que não
adotaram integração contínua (projetos NOCI ). Posterior a essa etapa, verificamos quais
as tendências existentes entre esses dois grupos, comparando as dados entre os respecti-
vos grupos. Numa segunda etapa, comparamos as tendências de dados de cobertura de
projetos CI apenas após a data de adoção de integração contínua 30 projetos POSCI com
os dados de cobertura de 92 projetos do Github que utilizam o TravisCI para CI por
pelo menos 1 ano e o Coveralls1 : um serviço web de coleta e armazenamento de dados de
1
https://coveralls.io/
18
Nós decidimos em usar pelo menos 30 projetos em cada conjunto de análise por ser
considerado, de forma heurística na estatística, como o número mínimo de tamanho de
uma amostra para se aplicar métodos estatísticos. Em relação a quantidade de dias (30
dias) e anos (2 anos) foram ideias que nos baseamos no trabalho de (NERY, 2020). Pelo
fato de que no Coveralls encontramos apenas projetos que adotaram CI, nós coletamos
versões apenas do intervalo de 1 ano. Este valor representa os dados após a adoção de CI.
A questão de pesquisa central do nosso trabalho é: existe uma relação entre integração
contínua e aumento, estabilização ou diminuição da cobertura de testes em projetos open-
source? Nossa primeira parte da pesquisa investiga de forma direta tal questão. Enquanto
a segunda parte da análise busca descobrir se existe semelhanças nas tendências entre os
dados de projetos CI (da primeira parte) com os dados dos projetos advindos do Coveralls.
Para responder nossa questão de pesquisa central, nós coletamos a cobertura dos testes
de 24 versões de 30 projetos CI e 24 versões de 30 projetos NOCI e coletamos a cobertura
de 12 versões de 92 projetos do Github que utilizaram o TravisCI e o Coveralls. Para
cada parte da análise realizada nesse estudo, nós explicamos o processo de obtenção e
tratamento dos dados na seção 3.
2 Fundamentação Teórica
A qualidade de software pode ser definida como um processo sistemático que focaliza
todas as etapas e artefatos produzidos com o objetivo de garantir a conformidade de
processos e produtos, prevenindo e eliminando defeitos (FITZPATRICK, 1996).
Os sistemas de software são uma parte cada vez maior da vida, de aplicativos de
negócios a produtos de consumo. A maioria das pessoas já teve uma experiência com soft-
ware que não funcionou conforme o esperado. O software que não funciona corretamente
pode causar muitos problemas, como por exemplo: perda de dinheiro, perda de tempo ou
reputação comercial. Os erros ocorridos no código ou na documentação podem resultar
em falhas no software final, mas nem todos os defeitos o fazem.
previstos. Embora os testes automatizados demandem maior esforço na sua fase de criação,
as execuções dos testes manuais representam um custo muito mais elevado do que os testes
automatizados. Como a Figura 11 ilustra.
2.4 Coveralls
para qualquer pessoa acessa-los online. Para utiliza-lo é necessário que o código esteja nos
repositórios onlines: GitHub2 , BitBucket3 ou GitLab4
• Cobertura por linha: Nele é possível navegar pelos arquivos individuais que foram
alterados em um novo commit e ver exatamente o que mudou na cobertura do build,
linha por linha.
• Visão geral do repositório: A visão geral de Coveralls permite que se veja facilmente
os níveis de cobertura atuais dos repositórios e um gráfico das mudanças de cobertura
ao longo do tempo.
• Divulgação de relatórios: É possível que outras pessoas tenham acesso aos seus
relatórios de cobertura por meio de requisições na sua API.
2
https://github.com/
3
https://bitbucket.org/
4
https://gitlab.com/
5
https://coveralls.io/features
26
• Não necessidade de adoção de CI: É possível utilizar o Coveralls sem utilizar CI.
3 Configurações do Estudo
Este capítulo detalha as configurações adotadas para o estudo conduzido nesta disser-
tação. A seção 3.1 apresenta as questões de pesquisa utilizadas para guiar o andamento
deste trabalho. A seção 3.2 descreve os datasets utilizados no estudo. A seção 3.3 denota
o procedimento conduzido para o estudo, expondo tecnologias utilizadas e critérios para
realização de cada passo. Por último, a seção 3.4 apresenta as considerações finais deste
capítulo.
• QP2 - Existe uma associação entre as taxas de cobertura de testes dos projetos CI
analisados com as de outros projetos CI advindos do Coveralls?
Esta seção descreve como os projetos foram selecionados e o processo de coleta dos
dados utilizado na presente pesquisa. No presente trabalho, reaproveitamos o conjunto de
dados disponibilizado por (NERY, 2020). O autor analisa dois grupos de projetos de código
aberto: (I) projetos que adotaram CI em algum momento de sua vida (datasetCI) e (II)
projetos que nunca adotaram CI durante sua vida (datasetN OCI). Nós adicionalmente
criamos mais dois datasets para ajudar a responder as questões de pesquisa propostas,
consistindo no (III) grupo de projeto CI foi elaborado como um subconjunto dos projetos
CI, nos quais foram extraídos apenas os valores de cobertura das versões após a adoção de
CI (datasetP OSCI) e (IV) no grupo de projetos Coveralls que representam os projetos
nos quais seus valores de cobertura foram retirados do Coveralls (datasetCoveralls).
(NERY, 2020) analisou apenas projetos com as linguagens JAVA, Python, PHP, Ruby
e Javascript. Desse modo, o datasetCI, datasetsN OCI e datasetP OSCI apresentam
apenas projetos de uma dessas 5 linguagens, já que eles foram elaborados tomando como
base o dataset de (NERY, 2020). O único diferente é o datasetCoveralls que não apresenta
essa restrição de linguagem. O motivo que levou a não ter a exclusão de projetos de
outras linguagens, motivou-se na opção de se ter uma maior quantidade de projetos que
atendessem aos critérios e também buscar que os resultados encontrados nesse dataset
sejam mais próximos de um ambiente mais realista.
3.2.1 DatasetCI
Esse dataset é composto por projetos com um volume de dados histórico estatistica-
mente relevante e que adotaram CI em algum momento de sua história. O processo pelos
autores utilizado para coletar o conjunto de dados é ilustrado na Figura 3.
jetos que usam Travis-CI. Os autores evitaram projetos que usam Jenkins, uma vez que
o histórico completo de CI de tais projetos não está disponível. A identificação que um
determinado projeto utiliza o Travis-CI é realizada com base na existência de builds as-
sociados ao projeto no Travis-CI. Portanto, considerou-se como data de adoção do CI,
a data do primeiro build publicado no refrido serviço. Dos 3.000 projetos, 1.784 (59,5%)
usaram Travis-CI.
No passo 3, os pull requests de cada projeto foram agruparam em dois grupos: antes e
depois da data de adoção de CI. Os projetos com menos de 100 pull requests nos intervalos
antes ou depois e CI foram excluídos por não conterem uma quantidade considerável de
dados. Além disso, os projetos considerados toy também foram descartados, restando 87
projetos após a etapa 3.
Após a coleta dos dados, a base de dados foi dividida em uma matriz bidimensional,
com 31 linhas e 25 colunas. Na primeira coluna está o nome do projeto, já nas próximas
24 colunas são os valores de coberturas coletados para análise, 12 de versões antes de
CI e 12 de versões posteriores ao uso de CI. Os valores de cobertura são organizados de
forma crescente de data, ou seja vão da primeira versão do projeto no período de antes
de adotar CI até a última versão do período de CI. A primeira linha é o cabeçalho com as
informações de cada variável e as próximas 30 linhas são os valores coletados de cobertura
de cada um dos projetos. O apêndice A mostra os valores de cobertura dessa base de
dados.
O DatasetN OCI consiste de projetos que nunca adotaram CI. A Figura 4 apresenta
o processo de construção desse dataset utilizado por Bernardo et al. (BERNARDO; COSTA;
30
KULESZA, 2018). Novamente, os 3.000 projetos mais populares do GitHub escritos nas
linguagens Java, Python, Ruby, PHP e JavaScript foram selecionados. Ressaltamos mais
uma vez que a popularidade é mensurada através do número de estrelas que um projeto
possui no GitHub na data da coleta. Em seguida, os projetos que possuem ao menos um
build no Travis-CI foram descartados. Como explicado anteriormente, a presença de builds
no Travis-CI foi utilizado como critério determinante para caracterizar o uso de CI por
um projeto.
A etapa 3 busca excluir do estudo os projetos inativos e imaturos. De tal sorte que,
essa etapa filtrou os projetos ativos em 2018 e que possuem menos 4 anos de atividade no
GitHub. Ao final desse etapa temos 392 projetos candidatos.
O datasetP OSCI representa os dados de cobertura dos projetos apenas para o pe-
ríodo após a adoção de integração contínua definido na seção 3.2.1. Desse modo, no lugar
de apresentar 24 valores de coberturas das versões dos projetos como no datasetCI, este
agrupamento apresenta apenas 12 valores de coberturas, que são exatamente aqueles co-
letados apenas após a data definida de CI. Este dataset é um subconjunto do dataset CI
(ver figura 8). A figura 5 mostra todo o processo de escolha do elementos desta base de
dados.
3.2.4 DatasetCoveralls
Esta base de dados consiste nos dados obtidos por meio do serviço web de divulgação
de coberturas chamado Coveralls. Neste serviço os projetos podem divulgar os valores
de cobertura obtidos de modo a ajudá-lo a rastrear sua cobertura de código ao longo do
tempo e garantir que todo o novo código seja totalmente coberto (COVERALLS, 2021). Os
projetos não precisam utilizar CI para divulgar seus dados no Coveralls, entretanto não
encontramos nenhum projeto que tenha um valor de cobertura divulgado antes da data
32
do primeiro build com sucesso no TravisCI. A figura 6 mostra o processo de criação deste
dataset com os respectivos projetos resultantes de cada etapa.
Esta seção detalha todos os passos realizados durante o estudo, desde a definição do
conjunto de dados, o tratamento realizado nos dados e os algoritmos utilizados para se
1
https://api.github.com/
2
https://api.travis-ci.org
3
https://coveralls.io/
33
obter os resultados. Este trabalho foi conduzido como um estudo empírico, por meio da
obtenção de dados quantitativos em projetos relevantes de código aberto.
Esta seção é organizada nas seguintes subseções: A subseção 3.3.1 apresenta o pro-
cesso utilizado na coleta de dados. A seção 3.3.2 descreve os procedimentos utilizados para
adequar os dados a forma desejada. Em seguida, a subseção 3.3.3 apresenta quais algo-
ritmos, métodos e classificações foram utilizados para responder as questões de pesquisas
propostas.
Uma visão geral dos passos utilizados na análise das questões de pesquisas e denotando
quais foram os artefatos de entrada e os nomes dos algoritmos utilizados são mostrados,
respectivamente, nas figuras 7 e 8
CI.
Dessa forma, se faz necessário a adoção de um critério que permita dividir o histórico
de dados dos projetos NOCI. O presente trabalho se baseou na proposta apresentada por
(NERY; COSTA; KULESZA, 2019). Os autores optaram por selecionar um ponto no tempo
que é proporcional à vida útil de um projeto. Primeiro, foram selecionados aleatoriamente
10 projetos do conjunto de dados de projetos de CI. Em seguida, calculamos o número
de meses antes da adoção do CI. Identificamos a proporção de tempo (em termos de
porcentagem) que os 10 projetos levaram para adotar a CI em relação ao tempo de
vida dos projetos. Finalmente, calculamos a mediana das proporções. Verificamos que, na
mediana, os projetos amostrados adotaram CI em 27,36% de sua vida. Posteriormente,
clonamos os repositórios de todos os projetos de CI e NOCI. Realizamos uma verificação
de 24 versões para todos os projetos (ou seja, ambos os projetos CI e NOCI) seguindo
o processo descrito na Figura 9. Para projetos de CI, o evento divisor é a adoção de CI,
obviamente, enquanto para projetos NOCI, o evento divisor é 27% do seu tempo de vida
até o dia da coleta.
Em relação aos projetos advindos do Coveralls, nós usamos a ideia de (NERY, 2020)
para obter a quantidade e o intervalo de tempo entre os commits que representam as ver-
sões de cobertura a serem analisadas. Entretanto tomamos algumas decisões diferentes,
como a (i) obrigatoriedade que os projetos precisam utilizar o Travis CI durante todo
o período analisado, (ii) foi contabilizado apenas projetos que obtiveram pelo menos 12
mudanças após a data de adoção de CI (primeiro build no Travis) somados com os 15
dias de intervalo de transição. Cada versão tem que ter no mínimo 30 dias de diferença
entre si e (iii) uso de mais projetos do que apenas apenas 30. A primeira mudança foi
36
motivada pela preocupação de não contabilizar dados de projetos que pararam de utilizar
a integração contínua durante o período analisado. A segunda mudança foi realizada para
não contabilizar um mesmo commit várias vezes, dessa forma garantimos que o valor de
cobertura da próxima versão não é uma repetição da versão antiga mais próxima. A ter-
ceira mudança foi motivada pela necessidade de verificar se a maximização da quantidade
de projetos CI analisados do Coveralls vai fazer com que os dados mudem de forma ra-
dical. Caso exista uma grande diferença entre os resultados coletados pela ferramentas e
os advindos do Coveralls, não seria possível usar o Coveralls para aumentar os dados do
datasetP OSCI.
Na busca em garantir uma replicação dos resultados de (NERY, 2020), nós utilizamos
as mesmas ferramentas que ele utilizou para as linguagens Java (Openclover), JavaScript
4
https://openclover.org/
5
https://istanbul.js.org/
6
https://coverage.readthedocs.io/en/coverage-5.5/
7
https://github.com/simplecov-ruby/simplecov
8
https://phpunit.de/
37
(Istanbul) e Python (Coverage.py). Para obter o valor de cobertura em Ruby, nós uti-
lizamos a SimpleCov, uma ferramenta bastante popular que está presente em mais de
100.000 repositórios Ruby no Github 9 . Nos projetos em PHP, nós utilizamos o PHPUnit
por também se tratar de um projeto maplamente utilizado pela comunidade. Ele está
presente em mais de 1.400.000 projetos 10
.
A ideia por trás dessa abordagem é encontrar uma maneira de comparar a compacta-
ção de agrupamentos, clusters, de uma distribuição de referência nula dos dados, ou seja,
9
https://github.com/simplecov-ruby/simplecov
10
https://github.com/sebastianbergmann/phpunit/
38
uma distribuição sem agrupamento óbvio. Sua estimativa para o número ideal de agrupa-
mentos (clusters) é o valor para o qual a a estrutura de agrupamento está mais longe da
distribuição de referência. Em linhas gerais, o algoritmo realiza os seguintes passos:
• Escolha o número de clusters como o menor valor de k, de forma que o Gap Statistic
esteja dentro de uma unidade de desvio padrão k + 1, ou seja: GAP (k) ≥ GAP (k +
1) − sk+1 .
A abordagem Gap Statistic é computada pela função clusGap do pacote cluster (MA-
ECHLER, 2021) da linguagem de programação R. A equação 3.1 mostra a função utilizada
para computar a Gap Statistic. Os parâmetros de entradas que não estão na equação são
opcionais e estes foram utilizados com os respectivos valores padrões.
clusGap(dataset,
F U N = kmeans,
nstart = 25,
(3.1)
iter.max = 50,
K.max = dataset.nrow − 1,
B = 599)
Figura 10: Diferenças entre os métodos Distância Euclidiana e DTW (MÜLLER, 2007)
A definição formal desta técnica é a seguinte: Suponha que investiguemos duas séries
temporais: A = a1 , a2 , ..., an , e B = b1 , b2 , ..., bm , com comprimentos n e m, respectiva-
mente. Para alinhar essas sequências, construímos uma matriz nxm onde elemento (i, j)
da matriz contém a distância d(ai , bj ) entre os pontos ai e bj . Neste contexto, a distân-
cia euclidiana é normalmente usada. Cada elemento da matriz (i, j) agora corresponde a
um alinhamento entre os pontos ai e bj , e um caminho de alinhamento W , formado por
conjunto contíguo de elementos de matriz, define um mapeamento entre as sequências A
e B. Formalmente, W = w1, w2, ..., wk com wk = (i, j)k e max(m, n) ≤ k < m + n − 1.
O objetivo do algoritmo é encontrar o caminho W ideal, ou seja, aquele que minimiza o
custo de alinhamento DT W (A, B) entre A e B:
v
u K
1u X
DT W (A, B) = min( t wk )
K k=1
Os parâmetros de entradas que não estão na equação são opcionais e estes foram utilizados
com os respectivos valores padrões.
tsclust(dataset,
type = f uzzy,
seed = 123, (3.2)
k = clusters,
distance = dtw)
• Raising: Consiste nos grupos dos centroides que representam um crescimento con-
tínuo no analisado período de tempo.
Na linha 2 está a instrução de definição da semente para que as funções que depende de
geração de números pseudo-aleatórios sempre retornem os mesmo resultados. Fazem uso
desse mecanismo de geração o algoritmo de kmeans utilizado na função clusGap. A linha
3 descreve a instrução para realizar uma cópia do dataset que não tenha a coluna com os
nomes do projetos, para que sejam utilizados apenas os valores numéricos. A função da
linha 4 é a função para computar o algoritmo de Gap Statistic descrita na seção 3.3.3.1.
A linha 5 descreve a função maxSE que também faz parte do pacote de cluster e serve
para determinar qual dos números de clusters analisados apresenta maior valor e deve
ser escolhido como o mais adequado. Na linha 6 é a instrução de retorno do número de
clusters mais adequado.
Obtido o número ideal de clusters, o próximo passo do estudo foi computar o algoritmo
de DTW descrito na seção 3.3.3.2 para cada um dos datasets. O algoritmo 2 mostra
um pseudo-código com as instruções utilizadas para obter a imagem com os grupos das
observações (projetos).
44
Como entrada o algoritmo tem o dataset com os dados com os valores das observações,
a seed com a semente para a sequência pseudo-aleatória e num_clusters com o número
de clusters nos quais os projetos estarão agrupados.
Na linha 3 está a instrução para realizar uma cópia do dataset que não tenha a coluna
com os nomes do projetos, para que sejam utilizados apenas os valores numéricos A linha
4 denota a função que computa a equação 3.2 que computa o algoritmo DTW descrito
na seção 3.3.3.2. Na linha 4, tem o armazenamento do gráfico com os agrupamentos dos
projetos presentes na variável dtw. Por último, tem o retorno da imagem gravada na
variável groups_img.
Nesta questão de pesquisa tentamos verificar como a cobertura de projetos que ado-
taram integração contínua se comportam após a respectiva data de adoção. Para isso,
definimos dois conjuntos de dados: (I) Projetos CI do dataset de (NERY, 2020) que apre-
senta apenas as versões coletadas após a data de adoção de CI, chamamos esse conjunto
de datasetP OSCI e (II) projetos que adotaram CI e que os seus valores de coberturas
foram divulgados no Coveralls, chamamos esse conjunto de dados de datasetCoveralls.
Nós realizamos uma análise comparativa local para cada grupo, que consiste em comparar
os valores obtidos entre projetos de um mesmo agrupamento e uma análise comparativa
entre grupos, no qual se confronta os resultados obtidos de cada grupo entre si.
45
3.4 Considerações
4 Resultados
Este capítulo apresenta e discute os resultados obtidos do nosso estudo. Ele é organi-
zado de acordo com as questões de pesquisa propostas. Ao final da apresentação de cada
questão de pesquisa, nós apresentamos discussões e implicações relacionadas as respostas.
Foi observado que houve uma pequena quantidade de grupos (3 grupos) retornadas
47
pelo uso do algoritmo 1, em relação ao intervalo possível de grupos que vão de 2 à 29. Essa
baixa quantidade de grupos evidencia que as observações apresentam comportamentos
mais parecidos entre si. Os centroides dos grupos (linhas tracejadas nos gráficos) ilustram
a forma como as observações se comportam de maneira geral e, desse modo, servem para
analisar a tendência do grupo. Os grupos 1 e 2 foram classificados como de tendência
Maintaining (manutenção da cobertura) e o grupo 3 como de tendência Raising (aumento
da cobertura).
metade dos projetos (13/30) tem uma cobertura com valor alto e tendendo a estabilizar
seus valores durante o tempo, quase todos os valores de cobertura do grupo 2 foram acima
de 0.5.
Aplicando dataset = datasetN OCI e seed = 123 com o algoritmo 1 obtemos como
resultado que a melhor quantidade de grupos usando o Gap Statistic é 25. A Figura 12
mostra a imagem gerada usando o algoritmo 2 de agrupamento DTW tendo como entrada:
dataset = datasetN OCI, seed = 123 e num_clusters = 25 e a tabela 2 mostra a quan-
tidade de observações em cada um dos grupos estipulados e a sua respectiva classificação
de tendência.
Houve um total de 25 grupos retornados pelo algoritmo 1 para o datasetN OCI. Este
é um valor bem próximo do máximo possível que é 29. A alta quantidade de grupos
(25 dos 29 possíveis) nos diz que os projetos apresentam valores de coberturas bastante
distintos entre si. Os centroides obtidos se comportam, em sua maioria, de forma análoga
49
aos projetos pertencentes aos grupos. Fato esse ocorre porque existe apenas uma variação
entre 1 e 3 na quantidade de membros de cada grupo. Nós observamos que apenas três
grupos (1, 11 e 19) tiveram tendência de Raising (aumento da cobertura), apenas dois
grupos (8 e 12) tiveram tendência de Decreasing (redução da cobertura) e, por fim, um
total de vinte grupos (grupos 2, 3, 4, 5, 6, 7, 9, 10, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23,
24 e 25) tiveram a classificação de Maintaning (manutenção da cobertura).
Nós também observamos que tanto projetos CI como NOCI tendem a manter o valor
de cobertura com o passar do tempo, com a distinção que os projetos CI geralmente
apresentam valores de cobertura maiores do que 75% do que os projetos NOCI. Esse
fato é embasado pela alta quantidade de projetos pertencentes a tendência Maintaining
presente nos projetos CI e NOCI, representando 66,6% (20 projetos) do datasetCI e 83%
(25 projetos) do datasetN OCI. Comparando os valores de cada grupo que foi classificado
como Maintaining observamos que o centroide do grupo 2 dos projetos CI com 13 projetos
e os centroides dos grupos 5, 7, 9, 16, 18, 20 dos projetos NOCI são as observações que
apresentam valores acima de 0.75 (75%). Desse modo, a proporção entre projetos da classe
Maintaining que apresentam o valor de cobertura alto e o total de projetos desta classe é
13/20 (65%) para o datasetCI e (28%) para o datasetN OCI. Essa distinção de valores
nas proporções permite observar que existe uma diferença significante (acima de 25%) de
valores entre a tendência de Maintaining entre as bases de dados.
Outra constatação é que projetos CI tem uma tendência de ter aumento no valor de
cobertura com o passar do tempo em relação a projetos NOCI. Essa afirmação é embasada
na tendência de Raising encontrada para muitos dos projetos. Enquanto que no datasetCI
observamos o grupo 1 com 10 projetos na classe Raising, no datasetN OCI vimos que para
a mesma classe obtemos os grupos 1, 11 e 19 com apenas 3 projetos.
testes para projetos que adotam CI. A seguir apresentamos uma visão geral sobre os
resultados encontrados:
• DatasetCI:
• DatasetN OCI:
– Existe uma pequena possibilidade queda de pelo menos 20% cobertura (2/30
projetos).
e apresenta menor complexidade de ser realizada, pois não necessita da execução dos
projetos.
Aplicando dataset = datasetP osCI e seed = 123 no algoritmo 1 obtemos como resul-
tado que a melhor quantidade de grupos usando o Gap Statistic é 16. A Figura 13 mostra
a imagem gerada usando o algoritmo 2 tendo como entrada: dataset = datasetP osCI,
seed = 123 e num_clusters = 16 e a tabela 2 mostra a quantidade de observações em
cada um dos grupos estipulados e a sua respectiva classificação de tendência.
Apesar de haver a tendência de Maintaining nos grupos, o que significa que o com-
portamento deles tendem a serem mais parecido, os valores absolutos das coberturas dos
centroides foram distintos. Os centroides do grupos 8, 9, 10 e 12 apresentaram valores
acima de 0.75 (75%), e estes grupos englobam 16 (53,3%) projetos. Apenas os grupos
1, 6 e 15 apresentam valores baixos de cobertura, abaixo de 25%. Eles compreendem 5
projetos (16,6%) do total de 30 projetos analisados desta base de dados. Tais resultados
nos fazem observar que as amostras de cobertura após a adoção de CI tende a manter o
valor de cobertura e esse valor normalmente é alto.
Nós classificamos apenas o grupo 7 como Decreasing, que representa apenas 1 projeto
(3,3% do total) . Não houve nenhum grupo classificado com Raising. Analisando os resul-
tados obtidos, o fato de não ter ocorrido uma tendência de crescimento de cobertura nos
permitiu observar que o uso de CI não melhorou a cobertura dos projetos citados. O que
54
pode ter acontecido é que os projetos já tenham conseguido garantir uma alta cobertura
dos testes na etapa de transição para CI ou mesmo antes de adotar CI.
Outro padrão percebido foi de similaridade entre grupos com coberturas acima de
75%, nós notamos que estes também representam os grupos com mais membros. Estes
55
são os grupos 10, 20 e 26, que totalizaram 51 (55,4%) observações. Isso implica que as
condições adotadas por esses projetos no datasetCoveralls para manter esse nível de
cobertura durante o ciclo de desenvolvimento devem ser estudadas de forma a prover
informações uteis para gerentes de projetos que quiserem aplicações que mantenham uma
alta cobertura dos seus testes.
Entendido como se comportam os projetos internamente por meios dos centroides dos
grupos nas bases datasetP osCI e datasetCoveralls, nós buscamos analisar uma possível
relação entre eles. A Tabela 5 denota a comparação de alguns dos principais pontos
alavancados em cada uma das bases de dados utilizadas para resolução desta questão
de pesquisa.
cobertura dos grupos que apresentam mais observações. Esses acontecimentos ocorreram
mesmo com uma grande diferença na quantidade de projetos analisados (30 e 92). Outro
critério que teve resultados equivalentes foram os da quantidade de grupos com membros,
com datasetP osCI com 25 grupos e datasetCI com 18, isso visto a disparidade de valores
absolutos das observações.
Esta seção discute os resultados obtidos nas questões de pesquisas propostas, apresen-
tando as hipóteses que se confirmaram ou não se confirmaram. As respostas das questões
de pesquisas permitiram entender mais sobre o comportamento da cobertura de testes
57
Na QP2 comparamos os valores de duas bases de dados de origem distintas que fo-
ram obtidas em épocas distintas. O dataset de (NERY, 2020) apresentou que houve um
crescimento significante de cobertura em projetos CI, entretanto nós não conseguimos
identificar esse comportamento analisando apenas as coberturas após a a adoção de CI
para a base de dados do Coveralls. Acreditamos que essa diferença se deu porque (NERY,
2020) utilizou como base de comparação os dados de antes e depois de CI e nós utili-
zamos apenas os dados após a adoção de CI. Considerando apenas o datasetP OSCI,
notamos um padrão de estabilidade na cobertura, algo muito parecido com o encontrado
no datasetCoveralls.
A seleção dos projetos NOCI também apresentam algumas ameaças. A seleção dos
projetos foi realizada por meio da análise de projetos não suportados pelo Travis CI. No
entanto, reconhecemos que os projetos podem usar outras ferramentas para integração
contínua (ex: Jenkins, Circle CI e Gitlab CI).
no GitHub.
Para garantir que não distorcemos os resultados e permitir um maior escrutínio, dis-
ponibilizamos todos os dados que coletamos nessa pesquisa.
Nosso conjunto de dados é mais amplo e mais diverso do que os estudos anteriores
encontrados sobre o tema. Por fim, uma vez que todos os projetos analisados nesse estudo
são de código aberto, não podemos fazer nenhuma afirmação sobre como nossos resultados
podem ser generalizados para projetos de software proprietário.
60
5 Trabalhos Relacionados
Este capítulo confronta este trabalho com outras pesquisas e estudos que analisam a
relação entre a integração contínua e cobertura de testes. A seção 5.1 destaca os pontos
principais de trabalhos relacionados de análise da cobertura de projetos que adotaram
integração contínua. A seção 5.2 apresenta uma análise comparativa entre nosso estudo e
os trabalhos relacionados.
(HILTON; BELL; MARINOV, 2018) realizaram uma avaliação em larga escala da co-
bertura de código em 7816 builds de 47 projetos escritos nas linguagens Java, Python e
Scala. Os autores observaram que as linhas cobertas variam amplamente entre os pro-
jetos, mesmo quando a cobertura geral parece permanecer inalterada. Nos experimentos
conduzidos pelos autores, considerou-se os últimos 250 commits dos projetos como janela
temporal para analisar a evolução da cobertura de código. O trabalho apresentado pelos
citados autores também focam na cobertura de patches assim como ocorre com relatado
pelo trabalho de (MARINESCU; HOSEK; CADAR, 2014), contudo (HILTON; BELL; MARINOV,
2018) apresentam um dataset maior. Entretanto, os 250 últimos commits podem não re-
presentar substancialmente a evolução da cobertura de código ao longo do tempo. O nosso
estudo aborda esse ponto ao investigar a evolução da cobertura de código em uma janela
de tempo de 2 anos. Nesse sentido, o estudo de 2 anos de cobertura de código nos permite
fornecer uma visão geral mais ampla da evolução da cobertura dos testes.
61
(NERY; COSTA; KULESZA, 2019) apresentam um estudo empírico sobre a relação entre
a adoção de integração contínua e o evolução do código de teste dos softwares. Os autores
compararam 82 projetos que adotaram CI com 82 outros projetos que nunca usaram CI.
Ao todo, os pesquisadores avaliaram 3936 versões de diferentes projetos a fim de estudar as
tendências no volume e cobertura do código de teste. Os resultados apresentados indicam
que 40.2% dos projetos de CI possuem uma tendência de aumento da taxa de teste-código,
enquanto apenas 17% dos projetos de NOCI têm uma tendência de aumento. O estudo
também reporta evidências de que os projetos de CI melhoraram a cobertura geral de
teste, enquanto os projetos de NOCI não apresentam melhorias nesse aspecto. Contudo, o
estudo sobre cobertura foi realizado com uma quantidade restrita de projetos. Os autores
estudaram as tendências de cobertura em apenas 20 projetos, sendo 10 projetos CI e 10
projetos NOCI. A presente pesquisa completa o trabalho de (NERY; COSTA; KULESZA,
2019) no que tange a análise da tendência de cobertura. Uma vez que analisamos as
tendências de cobertura em projetos CI e NOCI em uma base de dados bem mais ampla
tanto no volume de dados quanto na diversidade de linguagens.
todos os pull requests do começo de CI até uma determinada data, o que faz com que a
quantidade de dados a serem analisadas sejam bem consideráveis, já que foram, no total,
163.653 pull requests.
Este trabalho se propôs a explorar um caminho que não foi visto nos trabalhos relaci-
onados descrito nessa seção (exceção para o trabalho de (NERY; COSTA; KULESZA, 2019))
que foi o de analisar CI e a cobertura procurando relacioná-las. Buscamos abranger proje-
tos de várias linguagens de programações diferentes, ter um intervalo temporal de coleta
de dados de anos e ter vários projetos de perspectivas distintas. O conjunto das caracte-
rísticas distintas ditas anteriormente faz com que esse trabalho tenha sua importância no
ramo de pesquisa sobre a relação de integração contínua e cobertura de código, agregando
conhecimento e servindo como um trabalho de base para novas pesquisas na área.
Tabela 6: Comparação entre os projetos por CI, cobertura, tipo do estudo e tempo
Analisa Analisa Tipo de
Trabalho\Tópicos Tempo
CI cobertura estudo
CI/NOCI : 2 anos
Nosso trabalho X X Empírico
Coveralls : 1 ano
(HILTON, 2018) X Empírico 250 últimos commits
(ZHAO, 2017) X Empírico 100 últimos builds
(NERY, 2019) X X Empírico 2 anos
(BERNARDO, 2018) X Empírico Adoção de CI à 11/11/2016
6 Considerações finais
Verificamos que ainda existem muitas suposições no comunidade que permanece em-
piricamente inexplorada, principalmente, em relação aos efeitos de CI na cobertura de
código. O trabalho conduzido por (NERY, 2020) dar um primeiro passo sobre essa ques-
tão. Contudo, o referido trabalho realizou o estudo de cobertura em um conjunto rela-
tivamente pequeno de projetos, sendo necessário, portanto, um estudo mais robusto em
termos de volume de dados. Nesse contexto, a presente pesquisa estende o trabalho de
(NERY, 2020), realizando uma investigação mais ampla e voltada especificamente a ques-
tão da cobertura em projetos código aberto. Além disso, esse pesquisa investiga se existe
alguma similaridade de comportamentos entre as coberturas de projetos CI e dos proje-
tos retirados do Coveralls. Observar se projetos CI oriundos de fontes distintas possuem
comportamentos similares contribui na validação de generalização dos resultados. No res-
tante deste capítulo, delineamos as contribuições desta pesquisa e discutimos possíveis
trabalhos futuros.
• Levando em consideração apenas as versões coletadas após CI, chamadas nesse es-
tudo de datasetP OSCI, percebemos que também não existe uma similaridade entre
o comportamento das coberturas dos projetos, já que o algoritmo de melhor quan-
tidade de clusters retornou 16.
• Analisando os dados obtidos do datasetP OSCI podemos observar que ele teve uma
tendência dominante de maintaining com 29 projetos. Decreasing apresentou apenas
1 projeto e raising não foi identificado em nenhum projeto.
Os dados relativos ao datasetP OSCI indicam que existe uma relação de similaridade
de comportamento, tendência geral e tendência dos subgrupos mais populosos com o
datasetCoveralls. Notou-se que a tendência predominante no datasetCoveralls foi a de
manutenção da cobertura (90/92 projetos). Os demais projetos apresentaram tendência
de alta, enquanto que ninguém apresentou tendência de queda nas amostras.
De acordo com os nossos resultados nós concluímos que as coberturas do datasetP OSCI
e datasetCoveralls se comportam de forma bastante análoga, ou seja, acreditamos que
existe uma grande possibilidade de que os dados advindos do Coveralls possam substituir
os dados obtidos dos projetos CI de (NERY, 2020). Entretanto, é necessário uma verificação
estatística para validação.
Trabalhos futuros podem replicar as análises que são realizadas nesta dissertação
usando projetos e linguagens de programação adicionais. Além disso, a replicação deste
estudo usando projetos privados é necessária (ou seja, deve-se estudar o impacto de CI
na cobertura em projetos da iniciativa privada em vez de projetos de código aberto).
Esses estudos de replicação são importantes para chegar a conclusões mais generalizáveis
sobre o impacto de CI na cobertura de testes. Para fins de replicação, publicamos nossos
conjuntos de dados para o pesquisador interessado. Além disso, pesquisas podem ser
68
Uma proposta de extensão desse trabalho pode ser a utilização de análise estatística
para comparar os valores do datasetP OSCI e datasetCoveralls. Nesse trabalho descobri-
mos que estes datasets são equivalentes para alguns aspectos. Entretanto, uma análise com
base estatística pode garantir de forma estatística que realmente estes conjuntos são da
mesma população. Testes estatísticos de hipóteses não paramétricos podem ser utilizados
para esse fim.
69
Referências
AHMED, I. et al. Can testedness be effectively measured? In: . New York, NY,
USA: Association for Computing Machinery, 2016. (FSE 2016), p. 547–558. ISBN
9781450342186. Disponível em: <https://doi.org/10.1145/2950290.2950324>.
BELLER, M.; GOUSIOS, G.; ZAIDMAN, A. Oops, my tests broke the build: An analysis
of travis ci builds with github. [S.l.], 2016.
BERNDT, D. J.; CLIFFORD, J. Using dynamic time warping to find patterns in time
series. In: SEATTLE, WA, USA:. KDD workshop. [S.l.], 1994. v. 10, n. 16, p. 359–370.
CHOW, T.; CAO, D.-B. A survey study of critical success factors in agile software
projects. Journal of systems and software, Elsevier, v. 81, n. 6, p. 961–971, 2008.
CROWSTON, K.; ANNABI, H.; HOWISON, J. Defining open source software project
success. 2003.
70
GALILI, T. K-means Clustering (from "R in Action"). ago. 2013. Disponível em:
<https://www.r-statistics.com/2013/08/k-means-clustering-from-r-in-action/>. Acesso em
17 de Junho, 2021.
GORTON, I.; LIU, A. Software component quality assessment in practice: successes and
practical impediments. In: Proceedings of the 24th international conference on software
engineering. [S.l.: s.n.], 2002. p. 555–558.
HILTON, M.; BELL, J.; MARINOV, D. A large-scale study of test coverage evolution.
In: Proceedings of the 33rd ACM/IEEE International Conference on Automated Software
Engineering. [S.l.: s.n.], 2018. p. 53–63.
LEE, S.-Y. T.; KIM, H.-W.; GUPTA, S. Measuring open source software success. Omega,
Elsevier, v. 37, n. 2, p. 426–438, 2009.
LI, Y. et al. A class-level test selection approach toward full coverage for continuous
integration. In: SEKE. [S.l.: s.n.], 2019. p. 49–70.
MAECHLER, M. Gap Statistic for Estimating the Number of Clusters. Abr 2021.
Disponível em: <https://stat.ethz.ch/R-manual/R-devel/library/cluster/html/clusGap.
html>. Acesso em 17 de Junho, 2021.
71
MARINESCU, P.; HOSEK, P.; CADAR, C. Covrig: A framework for the analysis of code,
test, and coverage evolution in real software. In: Proceedings of the 2014 International
Symposium on Software Testing and Analysis. New York, NY, USA: Association for
Computing Machinery, 2014. (ISSTA 2014), p. 93–104. ISBN 9781450326452. Disponível
em: <https://doi.org/10.1145/2610384.2610419>.
MÅRTENSSON, T.; STÅHL, D.; BOSCH, J. Test activities in the continuous integration
and delivery pipeline. Journal of Software: Evolution and Process, Wiley Online Library,
v. 31, n. 4, p. e2153, 2019.
MEYER, M. Continuous integration and its tools. IEEE software, IEEE, v. 31, n. 3, p.
14–16, 2014.
MÜLLER, M. Dynamic time warping. Information retrieval for music and motion,
Springer, p. 69–84, 2007.
PINTO, G. et al. Work practices and challenges in continuous integration: A survey with
travis ci users. Software: Practice and Experience, Wiley Online Library, v. 48, n. 12, p.
2223–2236, 2018.
PINTO, G.; REBOUÇAS, M.; CASTOR, F. Inadequate testing, time pressure, and
(over) confidence: a tale of continuous integration users. In: IEEE. 2017 IEEE/ACM 10th
International Workshop on Cooperative and Human Aspects of Software Engineering
(CHASE). [S.l.], 2017. p. 74–77.
REEL, J. S. Critical success factors in software projects. IEEE software, IEEE, v. 16,
n. 3, p. 18–23, 1999.
SARDA, A. tsclust: Time series clustering. Feb 2017. Disponível em: <https:
//www.rdocumentation.org/packages/dtwclust/versions/3.1.1/topics/tsclust>. Acesso em
19 de Julho, 2021.
TEAM, R. core. Rscript: Scripting Front-End for R. Feb 2020. Disponível em:
<https://www.rdocumentation.org/packages/utils/versions/3.6.2/topics/Rscript>. Acesso
em 19 de Julho, 2021.
YANG, Y. et al. Hunting for bugs in code coverage tools via randomized differential
testing. In: IEEE. 2019 IEEE/ACM 41st International Conference on Software
Engineering (ICSE). [S.l.], 2019. p. 488–499.
APÊNDICE A -- DatasetCI
Project/Version 1 2 3 4 5 6 7 8
AnalyticalGraphicsInc/cesium 0.85 0.82 0.84 0.87 0.86 0.94 0.95 0.95
Leaflet/Leaflet 0.46 0.46 0.46 0.46 0.46 0.46 0.46 0.46
Marak/faker.js 1.0 1.0 1.0 1.0 0.95 0.96 0.96 0.96
Netflix/Hystrix 0.31 0.31 0.31 0.28 0.28 0.62 0.79 0.8
Pylons/pyramid 0.99 0.99 0.99 0.99 0.99 0.99 0.99 0.99
Yelp/mrjob 0.81 0.82 0.82 0.82 0.82 0.83 0.82 0.82
aframevr/aframe 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
ansible/ansible 0.55 0.6 0.6 0.6 0.6 0.6 0.6 0.04
bcit-ci/CodeIgniter 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
cakephp/cakephp 0.75 0.75 0.75 0.0 0.84 0.84 0.85 0.85
craftyjs/Crafty 0.33 0.32 0.32 0.34 0.37 0.39 0.47 0.47
cython/cython 0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9
dropwizard/dropwizard 0.43 0.44 0.45 0.45 0.46 0.46 0.39 0.5
dropwizard/metrics 0.69 0.68 0.66 0.66 0.66 0.66 0.67 0.67
fog/fog 0.12 0.62 0.61 0.07 0.61 0.62 0.63 0.64
gollum/gollum 0.86 0.85 0.82 0.85 0.86 0.9 0.9 0.9
jashkenas/backbone 0.92 0.93 0.93 0.93 0.94 0.94 0.96 0.97
jashkenas/underscore 0.96 0.96 0.96 0.96 0.97 0.96 0.96 0.96
kivy/kivy 0.09 0.09 0.17 0.09 0.08 0.08 0.08 0.08
loomio/loomio 0.71 0.58 0.5 0.51 0.46 0.45 0.46 0.43
matplotlib/matplotlib 0.0 0.37 0.46 0.46 0.47 0.47 0.46 0.48
mozilla/pdf.js 0.16 0.27 0.27 0.21 0.21 0.21 0.2 0.19
request/request 0.66 0.65 0.65 0.67 0.84 0.84 0.84 0.84
robolectric/robolectric 0.68 0.71 0.71 0.72 0.72 0.72 0.73 0.73
scipy/scipy 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.18
sensu/sensu 0.0 0.0 0.0 0.0 0.0 0.0 0.54 0.78
serverless/serverless 0.0 0.0 0.0 0.0 0.22 0.14 0.23 0.22
square/picasso 0.0 0.29 0.56 0.54 0.56 0.48 0.48 0.56
sympy/sympy 0.74 0.75 0.73 0.75 0.75 0.76 0.76 0.77
yiisoft/yii 0.26 0.26 0.26 0.26 0.26 0.26 0.26 0.26
Project/Version 9 10 11 12 13 14 15 16
AnalyticalGraphicsInc/cesium 0.95 0.95 0.95 0.95 0.95 0.94 0.94 0.94
Leaflet/Leaflet 0.46 0.46 0.46 0.47 0.5 0.47 0.57 0.57
Marak/faker.js 1.0 1.0 1.0 1.0 0.86 0.85 0.86 0.85
Netflix/Hystrix 0.79 0.79 0.79 0.8 0.76 0.75 0.74 0.74
Pylons/pyramid 0.99 1.0 1.0 0.99 1.0 1.0 1.0 1.0
Yelp/mrjob 0.82 0.82 0.82 0.82 0.82 0.83 0.83 0.83
aframevr/aframe 0.5 0.39 0.63 0.61 0.24 0.75 0.79 0.86
ansible/ansible 0.05 0.05 0.05 0.05 0.05 0.05 0.06 0.06
bcit-ci/CodeIgniter 0.0 0.0 0.0 0.0 0.1 0.12 0.18 0.19
cakephp/cakephp 0.85 0.86 0.86 0.86 0.81 0.86 0.86 0.86
craftyjs/Crafty 0.47 0.52 0.54 0.64 0.69 0.7 0.73 0.73
cython/cython 0.9 0.9 0.9 0.9 0.9 0.9 0.91 0.91
dropwizard/dropwizard 0.5 0.5 0.5 0.61 0.61 0.65 0.66 0.66
dropwizard/metrics 0.67 0.67 0.67 0.76 0.75 0.75 0.74 0.74
fog/fog 0.63 0.65 0.19 0.64 0.66 0.66 0.66 0.51
gollum/gollum 0.58 0.58 0.57 0.57 0.45 0.83 0.83 0.83
jashkenas/backbone 0.97 0.98 0.98 0.98 0.97 0.97 0.98 0.98
jashkenas/underscore 0.97 0.97 0.97 0.97 0.97 0.97 0.97 0.97
kivy/kivy 0.08 0.08 0.08 0.09 0.09 0.09 0.28 0.28
loomio/loomio 0.41 0.41 0.41 0.41 0.22 0.21 0.13 0.13
matplotlib/matplotlib 0.49 0.49 0.5 0.5 0.56 0.57 0.58 0.57
mozilla/pdf.js 0.19 0.16 0.16 0.16 0.16 0.16 0.16 0.16
request/request 0.84 0.84 0.85 0.85 0.84 0.84 0.84 0.84
robolectric/robolectric 0.73 0.69 0.67 0.7 0.74 0.74 0.74 0.75
scipy/scipy 0.18 0.18 0.18 0.18 0.18 0.18 0.17 0.17
sensu/sensu 0.52 0.75 0.74 0.74 0.51 0.69 0.69 0.67
serverless/serverless 0.2 0.13 0.06 0.26 0.37 0.88 0.92 0.91
square/picasso 0.56 0.56 0.56 0.56 0.56 0.58 0.6 0.6
sympy/sympy 0.77 0.78 0.78 0.79 0.27 0.27 0.26 0.26
yiisoft/yii 0.28 0.28 0.28 0.28 0.29 0.32 0.33 0.33
Project/Version 17 18 19 20 21 22 23 24
AnalyticalGraphicsInc/cesium 0.94 0.94 0.94 0.94 0.93 0.94 0.95 0.95
Leaflet/Leaflet 0.57 0.57 0.57 0.58 0.57 0.61 0.53 0.5
Marak/faker.js 0.86 0.85 0.86 0.86 0.86 0.87 0.96 0.96
Netflix/Hystrix 0.76 0.74 0.74 0.75 0.74 0.74 0.74 0.73
Pylons/pyramid 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.99
Yelp/mrjob 0.83 0.83 0.82 0.8 0.81 0.8 0.81 0.81
aframevr/aframe 0.86 0.86 0.81 0.67 0.84 0.84 0.84 0.82
ansible/ansible 0.06 0.06 0.07 0.08 0.08 0.08 0.08 0.08
bcit-ci/CodeIgniter 0.19 0.19 0.46 0.46 0.49 0.53 0.17 0.17
cakephp/cakephp 0.86 0.86 0.86 0.86 0.86 0.0 0.86 0.86
craftyjs/Crafty 0.73 0.73 0.74 0.74 0.74 0.72 0.75 0.72
cython/cython 0.91 0.91 0.91 0.91 0.91 0.91 0.91 0.91
dropwizard/dropwizard 0.66 0.66 0.64 0.65 0.65 0.65 0.66 0.66
dropwizard/metrics 0.74 0.74 0.74 0.74 0.74 0.73 0.72 0.73
fog/fog 0.67 0.67 0.66 0.66 0.66 0.67 0.67 0.67
gollum/gollum 0.82 0.86 0.86 0.86 0.79 0.79 0.79 0.79
jashkenas/backbone 0.97 0.97 0.97 0.97 0.97 0.97 0.98 0.97
jashkenas/underscore 0.97 0.97 0.97 0.97 0.97 0.97 0.97 0.97
kivy/kivy 0.28 0.28 0.28 0.31 0.31 0.31 0.31 0.31
loomio/loomio 0.0 0.13 0.14 0.13 0.13 0.38 0.38 0.39
matplotlib/matplotlib 0.58 0.57 0.61 0.56 0.52 0.55 0.55 0.55
mozilla/pdf.js 0.16 0.16 0.15 0.15 0.15 0.15 0.0 0.0
request/request 0.85 0.85 0.85 0.85 0.85 0.85 0.86 0.87
robolectric/robolectric 0.75 0.76 0.76 0.77 0.77 0.77 0.78 0.78
scipy/scipy 0.17 0.17 0.17 0.17 0.17 0.0 0.17 0.17
sensu/sensu 0.7 0.81 0.61 0.61 0.6 0.22 0.27 0.27
serverless/serverless 0.94 0.94 0.96 0.95 0.96 0.96 0.97 0.97
square/picasso 0.59 0.59 0.59 0.59 0.61 0.61 0.62 0.63
sympy/sympy 0.27 0.27 0.27 0.27 0.27 0.27 0.27 0.27
yiisoft/yii 0.38 0.4 0.34 0.39 0.4 0.41 0.41 0.42
Project/Version 1 2 3 4 5 6 7 8
BorisMoore/jsrender 0.96 0.96 0.94 0.94 0.94 0.94 0.91 0.92
MyCATApache/Mycat-Server 0.24 0.26 0.24 0.24 0.23 0.23 0.23 0.24
Shopify/liquid 0.25 0.25 0.25 0.25 0.24 0.25 0.24 0.25
Voog/wysihtml 0.47 0.46 0.5 0.5 0.49 0.49 0.49 0.48
alibaba/cobar 0.34 0.34 0.34 0.34 0.34 0.34 0.34 0.34
alibaba/jstorm 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.02
ankane/ahoy 0.27 0.27 0.27 0.27 0.28 0.0 0.31 0.31
bup/bup 0.56 0.56 0.56 0.56 0.56 0.65 0.65 0.64
chriskiehl/Gooey 0.34 0.34 0.35 0.26 0.22 0.24 0.24 0.23
cowbell/sharedrop 0.0 0.0 0.0 0.0 0.0 0.0 0.4 0.2
dataarts/dat.gui 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
fxsjy/jieba 0.72 0.73 0.76 0.75 0.79 0.68 0.68 0.75
hankcs/HanLP 0.0 0.14 0.45 0.46 0.14 0.13 0.12 0.13
httpie/httpie 0.94 0.93 0.94 0.94 0.93 0.93 0.92 0.89
idank/explainshell 0.28 0.2 0.2 0.2 0.2 0.2 0.2 0.2
jubos/fake-s3 0.29 0.29 0.29 0.29 0.29 0.29 0.29 0.29
julianshapiro/velocity 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
kennethreitz/grequests 0.95 0.95 0.95 0.95 0.98 0.98 0.98 0.98
lmenezes/elasticsearch-kopf 0.0 0.9 0.16 0.15 1.0 0.26 0.29 0.34
maxwellito/vivus 0.76 0.91 0.91 0.98 0.98 0.98 0.98 0.98
mleibman/SlickGrid 0.43 0.43 0.43 0.43 0.43 0.44 0.44 0.43
mojombo/chronic 0.86 0.86 0.86 0.86 0.86 0.86 0.86 0.86
mrniko/netty-socketio 0.32 0.32 0.31 0.31 0.31 0.27 0.27 0.26
powmedia/backbone-forms 0.7 0.67 0.67 0.67 0.67 0.67 0.67 0.56
psf/requests 0.58 0.59 0.61 0.61 0.63 0.63 0.64 0.64
pybrain/pybrain 0.3 0.3 0.3 0.3 0.3 0.29 0.29 0.29
serratus/quaggaJS 0.0 0.0 0.26 0.27 0.26 0.26 0.26 0.22
symfony/process 0.61 0.6 0.61 0.72 0.62 0.66 0.65 0.67
symfony/routing 0.78 0.79 0.78 0.78 0.78 0.78 0.78 0.79
symfony/var-dumper 0.57 0.58 0.57 0.0 0.63 0.65 0.6 0.65
Project/Version 9 10 11 12 13 14 15 16
BorisMoore/jsrender 0.92 0.92 0.91 0.91 0.91 0.91 0.91 0.91
MyCATApache/Mycat-Server 0.24 0.23 0.22 0.22 0.21 0.2 0.2 0.19
Shopify/liquid 0.25 0.25 0.27 0.27 0.27 0.27 0.27 0.27
Voog/wysihtml 0.48 0.47 0.46 0.46 0.46 0.46 0.42 0.46
alibaba/cobar 0.34 0.34 0.34 0.34 0.34 0.34 0.34 0.34
alibaba/jstorm 0.02 0.02 0.02 0.02 0.14 0.14 0.14 0.14
ankane/ahoy 0.31 0.31 0.31 0.33 0.33 0.33 0.33 0.33
bup/bup 0.65 0.65 0.65 0.65 0.66 0.66 0.66 0.66
chriskiehl/Gooey 0.23 0.23 0.29 0.26 0.28 0.28 0.28 0.28
cowbell/sharedrop 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2
dataarts/dat.gui 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
fxsjy/jieba 0.79 0.68 0.79 0.68 0.71 0.79 0.75 0.75
hankcs/HanLP 0.13 0.13 0.13 0.11 0.11 0.11 0.11 0.11
httpie/httpie 0.88 0.6 0.61 0.9 0.9 0.9 0.9 0.9
idank/explainshell 0.2 0.22 0.22 0.22 0.22 0.22 0.22 0.22
jubos/fake-s3 0.29 0.31 0.31 0.31 0.32 0.32 0.32 0.32
julianshapiro/velocity 0.45 0.45 0.45 0.45 0.45 0.45 0.45 0.45
kennethreitz/grequests 0.98 0.95 0.95 0.95 0.98 0.98 0.99 0.99
lmenezes/elasticsearch-kopf 0.4 0.43 0.46 0.55 0.56 0.55 0.55 0.54
maxwellito/vivus 0.98 0.98 0.98 0.98 0.98 0.98 0.98 0.98
mleibman/SlickGrid 0.41 0.41 0.41 0.41 0.41 0.4 0.4 0.4
mojombo/chronic 0.86 0.86 0.85 0.85 0.85 0.86 0.86 0.86
mrniko/netty-socketio 0.27 0.27 0.27 0.27 0.23 0.23 0.24 0.23
powmedia/backbone-forms 0.54 0.59 0.59 0.59 0.59 0.59 0.59 0.59
psf/requests 0.64 0.63 0.63 0.63 0.65 0.65 0.65 0.67
pybrain/pybrain 0.29 0.29 0.29 0.29 0.29 0.29 0.29 0.29
serratus/quaggaJS 0.23 0.25 0.25 0.17 0.17 0.17 0.17 0.17
symfony/process 0.7 0.69 0.69 0.69 0.72 0.72 0.72 0.74
symfony/routing 0.79 0.79 0.78 0.79 0.79 0.82 0.78 0.81
symfony/var-dumper 0.65 0.63 0.65 0.69 0.68 0.68 0.67 0.68
Project/Version 17 18 19 20 21 22 23 24
BorisMoore/jsrender 0.91 0.91 0.91 0.91 0.92 0.92 0.92 0.92
MyCATApache/Mycat-Server 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.19
Shopify/liquid 0.27 0.27 0.28 0.28 0.28 0.28 0.28 0.28
Voog/wysihtml 0.41 0.41 0.4 0.41 0.41 0.36 0.36 0.36
alibaba/cobar 0.34 0.34 0.34 0.34 0.34 0.34 0.34 0.34
alibaba/jstorm 0.14 0.14 0.14 0.14 0.14 0.11 0.11 0.12
ankane/ahoy 0.33 0.33 0.33 0.33 0.32 0.32 0.32 0.31
bup/bup 0.66 0.66 0.66 0.66 0.66 0.66 0.65 0.65
chriskiehl/Gooey 0.28 0.29 0.3 0.28 0.29 0.29 0.29 0.29
cowbell/sharedrop 0.0 0.2 0.2 0.2 0.2 0.2 0.2 0.2
dataarts/dat.gui 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
fxsjy/jieba 0.72 0.76 0.8 0.8 0.77 0.75 0.73 0.73
hankcs/HanLP 0.11 0.11 0.11 0.17 0.11 0.16 0.16 0.12
httpie/httpie 0.9 0.93 0.93 0.0 0.0 0.93 0.93 0.93
idank/explainshell 0.22 0.22 0.22 0.22 0.22 0.22 0.22 0.22
jubos/fake-s3 0.32 0.32 0.32 0.32 0.32 0.32 0.33 0.33
julianshapiro/velocity 0.45 0.45 0.45 0.45 0.45 0.45 0.45 0.45
kennethreitz/grequests 0.99 0.97 0.94 0.94 0.94 0.98 0.98 0.98
lmenezes/elasticsearch-kopf 0.55 0.56 0.56 0.56 0.56 0.56 0.57 0.57
maxwellito/vivus 0.98 0.97 0.97 0.97 0.97 0.97 0.97 0.97
mleibman/SlickGrid 0.4 0.4 0.4 0.22 0.39 0.39 0.4 0.39
mojombo/chronic 0.92 0.92 0.92 0.95 0.95 0.95 0.14 0.14
mrniko/netty-socketio 0.23 0.23 0.04 0.02 0.02 0.02 0.02 0.02
powmedia/backbone-forms 0.59 0.6 0.6 0.6 0.6 0.6 0.59 0.6
psf/requests 0.67 0.67 0.67 0.68 0.69 0.69 0.69 0.69
pybrain/pybrain 0.29 0.29 0.29 0.28 0.28 0.28 0.28 0.29
serratus/quaggaJS 0.17 0.2 0.2 0.2 0.2 0.2 0.22 0.0
symfony/process 0.73 0.18 0.18 0.18 0.18 0.18 0.18 0.11
symfony/routing 0.78 0.87 0.87 0.87 0.86 0.92 0.92 0.92
symfony/var-dumper 0.67 0.68 0.68 0.67 0.68 0.7 0.7 0.71
Project/Version v1 v2 v3 v4 v5 v6
AnalyticalGraphicsInc/cesium 0.95 0.94 0.94 0.94 0.94 0.94
Leaflet/Leaflet 0.5 0.47 0.57 0.57 0.57 0.57
Marak/faker.js 0.86 0.85 0.86 0.85 0.86 0.85
Netflix/Hystrix 0.76 0.75 0.74 0.74 0.76 0.74
Pylons/pyramid 1.0 1.0 1.0 1.0 1.0 1.0
Yelp/mrjob 0.82 0.83 0.83 0.83 0.83 0.83
aframevr/aframe 0.24 0.75 0.79 0.86 0.86 0.86
ansible/ansible 0.05 0.05 0.06 0.06 0.06 0.06
bcit-ci/CodeIgniter 0.1 0.12 0.18 0.19 0.19 0.19
cakephp/cakephp 0.81 0.86 0.86 0.86 0.86 0.86
craftyjs/Crafty 0.69 0.7 0.73 0.73 0.73 0.73
cython/cython 0.9 0.9 0.91 0.91 0.91 0.91
dropwizard/dropwizard 0.61 0.65 0.66 0.66 0.66 0.66
dropwizard/metrics 0.75 0.75 0.74 0.74 0.74 0.74
fog/fog 0.66 0.66 0.66 0.51 0.67 0.67
gollum/gollum 0.45 0.83 0.83 0.83 0.82 0.86
jashkenas/backbone 0.97 0.97 0.98 0.98 0.97 0.97
jashkenas/underscore 0.97 0.97 0.97 0.97 0.97 0.97
kivy/kivy 0.09 0.09 0.28 0.28 0.28 0.28
loomio/loomio 0.22 0.21 0.13 0.13 0.0 0.13
matplotlib/matplotlib 0.56 0.57 0.58 0.57 0.58 0.57
mozilla/pdf.js 0.16 0.16 0.16 0.16 0.16 0.16
request/request 0.84 0.84 0.84 0.84 0.85 0.85
robolectric/robolectric 0.74 0.74 0.74 0.75 0.75 0.76
scipy/scipy 0.18 0.18 0.17 0.17 0.17 0.17
sensu/sensu 0.51 0.69 0.69 0.67 0.7 0.81
serverless/serverless 0.37 0.88 0.92 0.91 0.94 0.94
square/picasso 0.56 0.58 0.6 0.6 0.59 0.59
sympy/sympy 0.27 0.27 0.26 0.26 0.27 0.27
yiisoft/yii 0.29 0.32 0.33 0.33 0.38 0.4
APÊNDICE D -- DatasetCoveralls
Project/Version 1 2 3 4 5 6
vuejs/vue 0.96 0.95 0.94 0.94 0.94 0.94
facebook/react 0.87 0.87 0.95 0.88 0.37 0.76
twbs/bootstrap 0.89 0.89 0.89 0.89 0.89 0.89
flutter/flutter 0.67 0.7 0.71 0.71 0.72 0.72
iluwatar/java-design-patterns 0.86 0.85 0.85 0.86 0.83 0.85
nvbn/thefuck 0.92 0.92 0.91 0.91 0.9 0.9
webpack/webpack 0.84 0.87 0.88 0.88 0.89 0.89
chartjs/Chart.js 0.72 0.75 0.84 0.84 0.85 0.84
expressjs/express 1.0 1.0 1.0 1.0 1.0 1.0
bitcoin/bitcoin 0.59 0.41 0.4 0.48 0.95 0.41
ElemeFE/element 0.35 0.92 0.91 0.89 0.89 0.88
lodash/lodash 0.98 1.0 1.0 1.0 1.0 0.93
gin-gonic/gin 0.88 0.92 0.94 0.93 0.93 0.93
moment/moment 0.92 1.0 0.95 0.95 0.95 0.95
scikit-learn/scikit-learn 0.95 0.95 0.94 0.94 0.94 0.94
jekyll/jekyll 0.87 0.86 0.87 0.85 0.83 0.84
neovim/neovim 0.0 0.57 0.56 0.56 0.56 0.57
scrapy/scrapy 0.52 0.74 0.3 0.85 0.94 0.47
serverless/serverless 0.87 0.87 0.88 0.88 0.88 0.88
nestjs/nest 0.91 0.94 0.95 0.95 0.95 0.95
mermaid-js/mermaid 0.53 0.53 0.53 0.54 0.54 0.49
JuliaLang/julia 0.81 0.12 1.0 0.29 0.5 0.64
hexojs/hexo 0.48 0.92 0.94 0.34 0.95 0.95
gulpjs/gulp 0.93 1.0 1.0 1.0 1.0 1.0
huginn/huginn 0.88 0.88 0.88 0.88 0.34 0.34
Continued on next page
82
Project/Version 7 8 9 10 11 12
vuejs/vue 0.94 0.94 1.0 1.0 1.0 1.0
facebook/react 0.87 0.88 0.88 0.85 0.83 0.81
twbs/bootstrap 0.91 0.91 0.91 0.91 0.91 0.91
flutter/flutter 0.72 0.79 0.82 0.84 0.84 0.83
iluwatar/java-design-patterns 0.88 0.91 0.91 0.9 0.89 0.89
nvbn/thefuck 0.91 0.91 0.91 0.91 0.91 0.92
webpack/webpack 0.9 0.9 0.9 0.9 0.9 0.9
chartjs/Chart.js 0.87 0.88 0.9 0.91 0.91 0.92
expressjs/express 1.0 1.0 1.0 1.0 1.0 1.0
bitcoin/bitcoin 0.61 0.86 0.78 0.03 1.0 0.04
ElemeFE/element 0.88 0.88 0.88 0.87 0.87 0.87
lodash/lodash 1.0 0.99 1.0 0.99 1.0 1.0
gin-gonic/gin 0.93 0.94 0.93 0.94 0.94 0.94
moment/moment 0.95 0.95 0.95 0.95 0.94 0.88
scikit-learn/scikit-learn 0.94 0.94 0.94 0.95 0.95 0.95
jekyll/jekyll 0.87 0.28 0.93 0.43 0.95 1.0
neovim/neovim 0.05 0.62 0.62 0.63 0.63 0.64
scrapy/scrapy 0.87 0.8 0.85 0.71 0.85 0.52
serverless/serverless 0.88 0.89 0.89 0.89 0.87 0.88
nestjs/nest 0.94 0.95 0.95 0.95 0.95 0.94
mermaid-js/mermaid 0.49 0.45 0.47 0.45 0.45 0.45
JuliaLang/julia 0.72 0.95 0.92 0.78 0.81 0.81
hexojs/hexo 0.95 0.95 0.95 0.95 0.95 0.93
Continued on next page
85
1 d e f g e t _ p r o j e c t _ c o v e r a g e _ f r o m _ c l o v e r ( r o o t : ElementTree ) −> f l o a t :
coverage : f l o a t = 0
3 p r o j e c t : ElementTree = r o o t . f i n d ( ’ p r o j e c t ’ )
a l l _ f i l e s : L i s t [ ElementTree ] = l i s t ( p r o j e c t . i t e r ( " f i l e " ) )
5 d i c t _ f i l e s : D i c t [ s t r , D i c t ] = {}
#
7 for f i l e in a l l _ f i l e s :
f i l e n a m e : s t r = f i l e . g e t ( ’ path ’ ) o r f i l e . g e t ( ’ name ’ )
9 l i n e s : L i s t [ ElementTree ] = l i s t ( f i l e . i t e r ( ’ l i n e ’ ) )
d i c t _ l i n e s : D i c t [ i n t , b o o l ] = {}
11 #
for l i n e in l i n e s :
13 number : i n t = i n t ( l i n e . g e t ( ’num ’ ) )
type : s t r = l i n e . g e t ( ’ type ’ )
15 coverage_count : b o o l = F a l s e
i f ( type == ’ cond ’ ) :
17 coverage_count = i n t ( l i n e . g e t ( ’ f a l s e c o u n t ’ ) ) > 0 o r i n t (
l i n e . get ( ’ truecount ’ ) ) > 0
else :
19 coverage_count = i n t ( l i n e . g e t ( ’ count ’ ) ) > 0
#
21 i f number not i n d i c t _ l i n e s . k e y s ( ) :
d i c t _ l i n e s [ number ] = coverage_count
23 else :
d i c t _ l i n e s [ number ] = d i c t _ l i n e s [ number ] o r coverage_count
89
25
count_covered_lines : f l o a t = 0
27 #
for covered_line in dict_lines . values () :
29 i f covered_line :
count_covered_lines = count_covered_lines + 1
31
i f l e n ( l i n e s ) == 0 :
33 d i c t _ f i l e s [ filename ] = {
’ covered_lines ’ : 0 ,
35 ’ valid_lines ’ : 0 ,
’ coverage ’ : 1
37 }
else :
39 d i c t _ f i l e s [ filename ] = {
’ covered_lines ’ : count_covered_lines ,
41 ’ valid_lines ’ : len ( dict_lines ) ,
’ coverage ’ : count_covered_lines / len ( d i c t _ l i n e s )
43 }
45 count_valid_lines : f l o a t = 0
count_covered_lines : f l o a t = 0
47 for f i l e in d i c t _ f i l e s . values () :
count_covered_lines = count_covered_lines + f i l e [ ’ covered_lines ’ ]
49 count_valid_lines = count_valid_lines + f i l e [ ’ valid_lines ’ ]
#
51 coverage = count_covered_lines / count_valid_lines
return coverage
90
Neste apêndice está o algoritmo em R utilizado para extração das informações presen-
tes no csvs das coberturas dos projetos. Utilizamos o RScript (TEAM, 2020) para executar
esse algoritmo.
main <− f u n c t i o n ( ) {
2
i f ( l e n g t h ( a r g s ) == 2 ) {
6 r e q u i r e d P a c k a g e s = c ( " proxy " , " g g p l o t 2 " , "dtw" , " f a c t o e x t r a " , " d t w c l u s t " ,
" cluster ")
i n s t a l l _packpages ( r e q u i r e d P a c k a g e s )
8 c r e a t e_dtw ( a r g s [ 1 ] , a r g s [ 2 ] )
} else {
10 parameter_e r r o r ( )
}
12 }
c r e a t e_dtw <− f u n c t i o n ( f i l e n a m e , s e e d ) {
24
91
i n s t a n c e s <− r e a d . c s v ( f i l e = f i l e n a m e , h e a d e r = TRUE)
28
c a t ( "OK\n" )
30
cat ( paste0 ( paste ( " Setting seed " , seed ) , " . . . " ) )
32
c a t ( "OK\n" )
36
46 c l u s t e r s <− maxSE( f = gap_s t a t $Tab [ , " gap " ] , SE . f = gap_s t a t $Tab [ , "SE .
sim " ] )
parameter_e r r o r <− f u n c t i o n ( ) {
86 c a t ( "ERROR: Quantidade e r r a d a de e n t r a d a s ( Deve s e r 3 ) \n" )
c a t ( " Entrada 1 − Nome d e s t e a r q u i v o \n" )
88 c a t ( " Entrada 2 − Nome do a r q u i v o . c s v a s e r u t i l i z a d o \n" )
c a t ( " Entrada 3 − I n t e i r o com v a l o r da semente \n" )
90 c a t ( "Ex : R s c r i p t dtw .R n o c i_p r o j e c t s . c s v 123 \n" )
}
92
main ( )