exploração dinâmica em android - repositório aberto · approach is implemented as an extension...
TRANSCRIPT
FACULDADE DE ENGENHARIA DA UNIVERSIDADE DO PORTO
Exploração Dinâmica em Android
Jorge Miguel Rodrigues Ferreira
Mestrado Integrado em Engenharia Informática e Computação
Orientador: Ana Cristina Ramada Paiva
19 de Julho de 2019
Exploração Dinâmica em Android
Jorge Miguel Rodrigues Ferreira
Mestrado Integrado em Engenharia Informática e Computação
Aprovado em provas públicas pelo Júri:
Presidente: João Carlos Pascoal FariaArguente: João Alexandre Baptista Vieira Saraiva
Vogal: Ana Cristina Ramada Paiva
19 de Julho de 2019
Resumo
Vivemos numa altura onde os smartphones são indispensáveis para o nosso dia a dia. De facto,com a evolução destes dispositivos e com as facilidades dadas aos desenvolvedores de aplicações,tem-se verificado uma rápida expansão do número de aplicações disponíveis para eles. Incluídasneste número estão aplicações críticas, tais como aplicações de pagamentos. Por estes motivos, écada vez mais importante testar adequadamente estas aplicações. Contudo, o teste manual é com-plicado, uma vez que existem muitos dispositivos diferentes. Automatizar o teste de aplicaçõesmóveis torna-se, por isso, cada vez mais relevante.
Teste baseado em modelos é uma das técnicas para automatizar a geração de casos de testea partir de um modelo. No entanto, esta técnica tem alguns problemas como, por exemplo, oprocesso moroso que é a criação manual do modelo. Para resolver este problema, uma das pos-síveis soluções é a existência de um processo engenharia reversa dinâmico sustentado por umaexploração da aplicação, que pode extrair parte do modelo para a técnica de teste baseado emmodelos.
Existem abordagens dinâmicas para explorar aplicações móveis, mas estas abordagens pos-suem alguns desafios que necessitam de ser ultrapassados de forma a conseguirem obter bonsresultados, tais como conseguir ultrapassar os pontos de bloqueio (p. ex. um sistema de auten-ticação), escolher os dados de input apropriados, testar o comportamento dinâmico da aplicação,executar os vários gestos de interação existentes, entre outros.
Este documento apresenta uma abordagem de exploração dinâmica de aplicações móveis An-droid que visa superar alguns dos problemas identificados. Durante o processo de exploração, oalgoritmo constrói uma máquina de estados finita, onde cada estado representa um ecrã identifi-cado e as transições entre estes estados descrevem eventos que permitem a passagem de um ecrãpara outro. Esta abordagem encontra-se implementada como uma extensão da iMPAcT tool.
De forma a validar o algoritmo implementado, foram realizadas duas experiências com aplica-ções reais disponíveis na Google Play Store. Nestas experiências foram analisadas a cobertura decódigo e de eventos para avaliar o desempenho do novo algoritmo. Após analisar estes resultados,foi possível verificar que o algoritmo desenvolvido apresenta melhor desempenho que outros doisalgoritmos existentes no estado da arte.
Keywords: Exploração móvel, Exploração, Engenharia reversa, Exploração dinâmica, Teste deaplicações móveis
i
ii
Abstract
We live in a time where smartphones are indispensable for our daily life. In fact, with theevolution of these devices, and with the facilities that are given to the developers of applications, arapid expansion of the number of available applications for them is being verified. Included in thisnumber are critical applications, such as payment applications. For these reasons, it is increasinglyimportant to properly test these applications. However, manual testing is complicated since thereare many different devices. Automating the testing of mobile applications becomes, therefore,increasingly relevant.
Model-Based Testing is one of the techniques to automate the generation of test cases from amodel. However, this technique has some problems, such as the time-consuming process that is themanual creation of the model. To solve this problem, one of the possible solutions is the existenceof a dynamic reverse engineering process that is sustained by an exploration of the application thatcan extract part of the model for the MBT technique.
There are dynamic approaches to explore mobile applications, but these approaches have somechallenges that need to be overcome in order to achieve good results, such as overcoming blockingpoints (e. g. an authentication system), choosing appropriate input data, testing dynamic behaviourof the application, executing the different existing interaction gestures, among others.
This document presents a dynamic exploration approach of Android mobile applications thataims to overcome some of the identified problems. During the exploration process, the algorithmbuilds a Finite State Machine in which each state represents an identified screen and each transitionbetween these states describes an event that allows moving from one screen to another. Thisapproach is implemented as an extension of the iMPAcT tool.
In order to validate the implemented algorithm, two experiments were performed with realapplications available on Google Play Store. In these experiments, code and event coverage wereanalysed to assess the performance of the new algorithm. After analysing these results, it was pos-sible to verify that the developed algorithm presents better performance than two other algorithmsexistent in the state of the art.
Keywords: Mobile exploration, Crawling, Reverse engineering, Dynamic exploration, Mobiletesting
iii
iv
Agradecimentos
A elaboração desta dissertação de mestrado não seria possível sem o apoio, empenho e forçade várias pessoas, às quais gostaria de deixar algumas palavras de agradecimento.
Em primeiro lugar, gostaria de agradecer à professora Ana Paiva, pela sua amizade, dedicaçãonesta orientação, disponibilidade sempre mostrada e pelos conhecimentos transmitidos ao longodo desenvolvimento do trabalho.
Gostaria também de agradecer aos alunos de doutoramento presentes no laboratório de enge-nharia de software, João Pedro e Bruno Lima, pelo conhecimento partilhado e por estarem sempredisponíveis para me esclarecerem as dúvidas que surgiram ao longo da dissertação.
E porque dizem que os amigos são a família que escolhemos, gostaria de agradecer a todos osmeus amigos, por todas as palavras de incentivo durante esta jornada.
Por último, e porque sem eles nada disto era possível, gostaria de agradecer aos meus pais,Manuela Silva e António Ferreira, pelo seu amor, carinho e por estarem sempre ao meu lado, tantonos bons como nos maus momentos. Obrigado por me terem tornado quem sou hoje.
Jorge Miguel Rodrigues Ferreira
v
vi
“All our dreams can come true,if we have the courage to pursue them.”
Walt Disney
vii
viii
Conteúdo
1 Introdução 11.1 Contexto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Problema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.3 Motivação e objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.4 Contribuições . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.5 Estrutura do documento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2 Estado da arte 72.1 Testes a aplicações móveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.1.1 Automatização de testes a aplicações móveis . . . . . . . . . . . . . . . 72.1.2 Testes de caixa branca e testes de caixa preta . . . . . . . . . . . . . . . 92.1.3 Ferramentas de suporte . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2 Teste baseado em modelos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.3 Engenharia reversa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.4 Cobertura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152.5 Exploração dinâmica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172.6 Conclusões . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3 iMPAcT tool 233.1 Abordagem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.1.1 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.1.2 Fases do processo iterativo . . . . . . . . . . . . . . . . . . . . . . . . . 243.1.3 Modos de exploração . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253.1.4 Condição de paragem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.2 Catálogo de padrões . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263.2.1 Padrão side drawer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273.2.2 Padrão de orientação . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283.2.3 Padrão de dependência de recursos . . . . . . . . . . . . . . . . . . . . . 30
3.3 Artefactos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313.3.1 Relatório da exploração . . . . . . . . . . . . . . . . . . . . . . . . . . 313.3.2 Modelo do comportamento observado . . . . . . . . . . . . . . . . . . . 31
3.4 Contribuições da ferramenta para a comunidade . . . . . . . . . . . . . . . . . . 323.5 Conclusões . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4 Exploração dinâmica 354.1 Algoritmo de exploração . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354.2 Condições de paragem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394.3 Modos de exploração . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
ix
x CONTEÚDO
4.4 Tipos de eventos suportados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404.5 Critério de comparação de ecrãs . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.5.1 Identificação do elemento tabs . . . . . . . . . . . . . . . . . . . . . . . 424.5.2 Diferença entre elemento e widget . . . . . . . . . . . . . . . . . . . . . 43
4.6 Permissões do sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434.7 Deteção de crashes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444.8 Ficheiro de configuração . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454.9 Script de execução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.9.1 Modo de utilização . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464.9.2 Algoritmo de reprodução . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4.10 Conclusões . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
5 Experiências 515.1 Especificações técnicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515.2 Metodologia de teste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.2.1 Seleção do conjunto de aplicações . . . . . . . . . . . . . . . . . . . . . 535.2.2 Ferramentas de exploração . . . . . . . . . . . . . . . . . . . . . . . . . 535.2.3 Ferramenta de análise de cobertura de código . . . . . . . . . . . . . . . 54
5.3 Desempenho dos algoritmos de exploração . . . . . . . . . . . . . . . . . . . . 555.3.1 Cobertura de eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565.3.2 Cobertura de código . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
5.4 Impacto do aumento do tempo máximo de exploração na cobertura da aplicação . 595.5 Discussão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
5.5.1 QI 1: É possível explorar automaticamente o comportamento das aplica-ções Android através de uma análise dinâmica? . . . . . . . . . . . . . . 60
5.5.2 QI 2: É possível obter melhores resultados que outros algoritmos já exis-tentes no estado da arte? . . . . . . . . . . . . . . . . . . . . . . . . . . 60
5.5.3 QI 3: É a cobertura de eventos diretamente proporcional à cobertura decódigo? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.5.4 QI 4: Qual o efeito de aumentar o tempo máximo da exploração na cober-tura da aplicação? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.6 Conclusões . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
6 Conclusões e trabalho futuro 65
Referências 67
A Funções 73A.1 Criação do evento edit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
B Cobertura de código 77B.1 Passos necessários para a criação do relatório . . . . . . . . . . . . . . . . . . . 77
Lista de Figuras
1.1 Ecrã da aplicação Omni Notes com comportamento dinâmico . . . . . . . . . . . 31.2 Ecrã da aplicação Omni Notes que contém um widget com uma infinidade de eventos 3
3.1 Diagrama de componentes da abordagem implementada na iMPAcT tool [53] . . 243.2 Exemplo do padrão Side Drawer [22] . . . . . . . . . . . . . . . . . . . . . . . 283.3 Exemplo do padrão de Orientação. a) portrait e b) landscap [55] . . . . . . . . . 29
4.1 Aparecimento de novos elementos no ecrã após o clique no botão de pesquisa . . 364.2 Dois ecrãs com diferente tab selecionado . . . . . . . . . . . . . . . . . . . . . 424.3 Pedido de permissão para gravar áudio . . . . . . . . . . . . . . . . . . . . . . . 444.4 Exemplo de diferentes ecrãs de crash . . . . . . . . . . . . . . . . . . . . . . . . 454.5 Passos para iniciar a reprodução do script . . . . . . . . . . . . . . . . . . . . . 46
xi
xii LISTA DE FIGURAS
Lista de Tabelas
5.1 Conjunto final de aplicações selecionadas . . . . . . . . . . . . . . . . . . . . . 545.2 Características do ACVTool e do JaCoCo . . . . . . . . . . . . . . . . . . . . . 545.3 Resultados de cobertura de eventos . . . . . . . . . . . . . . . . . . . . . . . . . 575.4 Resultados de cobertura de código . . . . . . . . . . . . . . . . . . . . . . . . . 585.5 Resultados de cobertura de eventos para a aplicação Omni Notes com um tempo
máximo de exploração de 50 minutos . . . . . . . . . . . . . . . . . . . . . . . 595.6 Resultados de cobertura de código para a aplicação Omni Notes com um tempo
máximo de exploração de 50 minutos . . . . . . . . . . . . . . . . . . . . . . . 59
xiii
xiv LISTA DE TABELAS
Acrónimos
GUI Graphical User InterfaceUI User InterfaceGPS Global Positioning SystemNFC Near Field CommunicationMBT Model-Based TestingDOC Double Orientation ChangePBGT Pattern-Based GUI TestingAPI Application Programming InterfaceAPK Android Application PackageURI Uniform Resource IdentifierHTML HyperText Markup LanguageXML Extensible Markup LanguageSDK Software Development KitIDE Integrated Development EnvironmentSATG Static Activity Transition Graph
xv
Capítulo 1
Introdução
Este capítulo tem como objetivo fornecer uma visão geral sobre os temas abordados nesta
dissertação, que incluem uma breve descrição do contexto no qual a dissertação está inserida,
alguns desafios existentes, a sua motivação e objetivos e as principais contribuições do trabalho
realizado. No final será apresentada e descrita a estrutura do presente documento.
1.1 Contexto
Atualmente, os smartphones estão cada vez mais importantes na vida do ser humano. Esta im-
portância é, sobretudo, devido às suas capacidades que os fazem ser semelhantes a um computador
pessoal.
Com a evolução dos smartphones e com a facilidade cada vez maior de desenvolver aplicações
para dispositivos móveis, tem-se verificado uma rápida expansão do número destas aplicações.
Neste mercado, há duas plataformas que se destacam conforme indicam os dados do segundo
trimestre de 2018 [68]: Android, com uma quota de mercado de 88% e iOS, com uma quota de
mercado de 12%. Assim, verifica-se que o Android é a plataforma de eleição para os utilizadores
de smartphones entre as plataformas que se destacam.
No início de Novembro de 2018, o número de aplicações móveis disponíveis na Google
Play Store situava-se acima dos 2.5 milhões [11] e no ano de 2017 existiram aproximadamente
178.1 mil milhões de downloads de aplicações móveis [66], o que demonstra a importância dos
smartphones no dia-a-dia da população mundial.
A rivalidade associada ao número crescente de aplicações móveis, bem como a existência de
aplicações críticas, como aplicações de pagamentos, torna a tarefa de automatizar os testes nestas
aplicações muito importante para garantir que estas funcionam da melhor maneira possível. É
importante salientar que testar uma aplicação não vai garantir que esta não possui problemas, mas
vai aumentar a confiança na sua qualidade.
1
2 Introdução
Teste baseado em modelos (MBT) é uma das técnicas para geração automática de casos de
teste a partir de um modelo que descreve o sistema a testar. No entanto, esta técnica possui alguns
problemas, como a própria necessidade de um modelo, cuja construção manual é um processo
moroso e sujeito a erros [55]. Para contornar este problema, uma das possíveis soluções tem como
base um processo de engenharia reversa dinâmico sustentado por uma exploração automática da
aplicação, de modo a ser possível extrair parte do modelo para a técnica de MBT [52, 55, 63].
1.2 Problema
Atualmente, tem-se verificado um aumento da preocupação, por parte das empresas, no teste
às aplicações móveis introduzidas no mercado. No entanto, existem alguns desafios na realização
de testes a estas aplicações, sendo o tempo disponível um dos maiores no ano de 2017 [67].
O processo de exploração dinâmica, base de muitas ferramentas de testes automatizados, pos-
sui também desafios que podem impedir que esta exploração atinja todos os estados existentes na
aplicação em teste. Entre estes desafios, salientam-se os quatro seguintes:
• Possibilidade de existirem pontos de bloqueio como, por exemplo, um sistema de autenti-
cação que impedem que a exploração atinja outras funcionalidades da aplicação;
• A evolução do mundo das aplicações móveis pode levar à introdução de novos gestos de
interação não exercitados pelo algoritmo de exploração. Tendo em conta que certas partes
da aplicação apenas podem ser acessíveis através de gestos específicos, torna-se importante
que um algoritmo de exploração dinâmica seja atualizado de maneira a simular todas as
formas de interação possíveis;
• Identificação de ecrãs diferentes pois não é possível saber dinamicamente quando a aplica-
ção atinge um novo ecrã;
• Devido à natureza dinâmica das aplicações móveis, eventos que estavam disponíveis num
ecrã podem deixar de o estar quando se retorna a esse mesmo ecrã. Além disto, ainda devido
a esta natureza dinâmica, certas aplicações podem ter um número infinito de eventos num
ecrã, fazendo com que a exploração fique presa nesse estado. A Figura 1.1 e a Figura 1.2
ilustram casos onde existe um elevado número de eventos para executar num mesmo ecrã.
Na Figura 1.1, sempre que um item é adicionado à lista (“New item”), um novo elemento
da GUI surge imediatamente abaixo. Por esta razão, a lista de opções pode crescer de forma
infinita (ou até um certo limite ser atingido). A Figura 1.2 representa um widget calendário
com uma infinidade de eventos (datas). No entanto, interagir com todas as datas possíveis
não contribui para o aumento do conhecimento da aplicação.
As questões de investigação definidas nas quais esta dissertação está centrada são as seguintes:
QI 1 - É possível explorar automaticamente o comportamento das aplicações Android atra-
vés de uma análise dinâmica?
1.3 Motivação e objetivos 3
Figura 1.1: Ecrã da aplicação Omni Notes com comportamento dinâmico
Figura 1.2: Ecrã da aplicação Omni Notes que contém um widget com uma infinidade de eventos
QI 2 - É possível obter melhores resultados que outros algoritmos já existentes no estado da
arte?
QI 3 - É a cobertura de eventos diretamente proporcional à cobertura de código?
QI 4 - Qual o efeito de aumentar o tempo máximo da exploração na cobertura da aplicação?
Estas questões guiaram as experiências realizadas de forma a que, com base nos resultados
obtidos, elas fossem respondidas. Além disto, as respostas às questões ajudam a clarificar o real
desempenho do algoritmo implementado em comparação com outros dois já existentes no estado
da arte. Estas respostas podem ser encontradas na Secção 5.5.
1.3 Motivação e objetivos
Com o aumento da preocupação em testar as aplicações móveis, começaram a surgir fra-
meworks de teste não só oficiais como também não oficiais, que fornecem um conjunto de APIs
para a criação de testes à interface do utilizador e que interagem com a aplicação e com outros
serviços do sistema dinamicamente. Estas frameworks são a base de muitas das ferramentas de
testes às aplicações móveis existentes.
4 Introdução
A fase de exploração dinâmica das interfaces de uma aplicação móvel é uma tarefa muito
importante para muitas ferramentas de testes automatizados e prossupõe sempre uma condição
de paragem que identifica quando a exploração da aplicação deve terminar. Esta exploração tem
por base a simulação das interações de um utilizador na aplicação móvel, de forma a identificar e
percorrer todos os seus estados.
A exploração da aplicação está diretamente relacionada com a sua cobertura, ou seja, quanto
melhor for a exploração, maior será, teoricamente, o grau de cobertura dos testes na aplicação mó-
vel. Uma boa exploração da aplicação é aquela que consegue atingir todos os estados da aplicação,
exercitando todos os eventos disponíveis.
O foco deste trabalho de investigação está relacionado com a componente de exploração da
iMPAcT tool (Mobile PAtterns Testing) [49, 50, 51, 53, 54, 55]. Esta ferramenta foi desenvolvida
num trabalho de investigação anterior e tem como objetivo verificar se as diretrizes fornecidas pela
Google [23] para o desenvolvimento de aplicações Android estão implementadas corretamente.
O processo de teste é feito de forma totalmente automática combinando engenharia reversa, para
obter um modelo da aplicação, e identificação de UI Patterns. Caso algum padrão seja encontrado,
a ferramenta aplica os Test Patterns correspondentes. Após o teste, a exploração da aplicação
continua.
Assim, o principal objetivo desta dissertação consistiu em estender a iMPAcT tool, conce-
bendo um novo algoritmo de exploração de aplicações móveis Android, de forma a aumentar
a cobertura de código e de eventos nas suas execuções melhorando, consequentemente, os seus
resultados. Esta dissertação encontra-se dividida em quatro fases:
1. Revisão do estado da arte – Esta fase consistiu na recolha de informação sobre o estado
da arte dos tópicos envolvidos na dissertação. O resultado desta revisão é apresentado no
Capítulo 2;
2. Análise da iMPAcT tool – Após a revisão do estado da arte, foi necessário analisar a iM-
PAcT tool, ferramenta que é a base desta dissertação. Esta análise é apresentada no Capítulo
3 e inclui a abordagem de teste da ferramenta, o seu catálogo de padrões, os artefactos pro-
duzidos, entre outros;
3. Implementação – Esta fase consistiu na implementação do novo algoritmo de exploração.
O Capítulo 4 apresenta os detalhes desta implementação;
4. Validação – Finalmente, a última fase passou pela realização de duas experiências para
validar o algoritmo implementado. Estas experiências e os seus resultados encontram-se
apresentados no Capítulo 5.
1.4 Contribuições
As principais contribuições fornecidas por este trabalho de investigação são:
1.5 Estrutura do documento 5
1. Um algoritmo de exploração dinâmica de aplicações móveis que ajuda a resolver os proble-
mas identificados na Secção 1.2;
2. Um mecanismo que permite gravar uma exploração e reproduzi-la de forma a verificar se os
problemas identificados durante essa exploração ainda existem;
3. Um artigo com a descrição do algoritmo de exploração desenvolvido e dos resultados das ex-
periências realizadas. Este artigo foi submetido e aceite na conferência QUATIC a realizar-
se em setembro de 2019: J.M.R. Ferreira, A.C.R. Paiva. “Android Testing Crawler”. Em
12th International Conference on the Quality of Information and Communications Techno-
logy, Ciudad Real, Espanha, Setembro 11–13, 2019.
1.5 Estrutura do documento
Este documento está estruturado em seis capítulos. O presente e primeiro capítulo introduz
o tema trabalhado na dissertação, definindo o contexto, os problemas, a motivação e os objetivos
da mesma e, finalmente, as contribuições oferecidas por este trabalho. O Capítulo 2 apresenta
os resultados da pesquisa realizada relativamente ao estado da arte, que incluem ferramentas e
metodologias de testes, engenharia reversa, cobertura e exploração em aplicações móveis Android.
O Capítulo 3 descreve a ferramenta na qual esta dissertação se baseia. O Capítulo 4 descreve
os detalhes de implementação do novo algoritmo de exploração e do script de reprodução. O
Capítulo 5 apresenta os resultados das experiências realizadas para validação do algoritmo de
exploração desenvolvido. Finalmente, no Capítulo 6 são apresentadas as conclusões e o trabalho
futuro.
6 Introdução
Capítulo 2
Estado da arte
O presente capítulo é dividido em seis principais secções. Na Secção 2.1 é feita uma revisão
do estado da arte relativo ao processo de teste de aplicações móveis. Na Secção 2.2 é explicada
a técnica de teste baseado em modelos. Na Secção 2.3 é descrito o estado atual da engenharia
reversa com especial ênfase em dispositivos móveis. A Secção 2.4 sumaria o estado atual da arte
relativo a abordagens e ferramentas associadas à cobertura de aplicações móveis. Na Secção 2.5
é sintetizado o estado atual da exploração dinâmica de aplicações móveis. Finalmente, a última
secção serve como conclusão à revisão da literatura realizada.
2.1 Testes a aplicações móveis
Uma aplicação móvel é uma aplicação projetada para ser executada num dispositivo móvel,
como um smartphone ou tablet. Por norma, estas aplicações são pequenas e construídas de forma
a poderem usufruir de recursos especificas do dispositivo.
Com o rápido crescimento do número de aplicações móveis, torna-se essencial garantir o seu
correto funcionamento. Por esta razão, é importante a criação de técnicas que melhorem a auto-
matização do processo de teste. Atualmente, no que diz respeito a esta automatização, o foco das
abordagens existentes pode ser na geração de testes ou na sua execução. No entanto, a comunidade
tem vindo a dar especial atenção à automatização de geração de casos de teste devido à existência
de frameworks e ferramentas que facilitam o processo da sua execução [49]. Estas ferramentas
serão descritas com mais pormenor na Subsecção 2.1.3.
2.1.1 Automatização de testes a aplicações móveis
No seu estudo em 2012, Muccini et al. [56] identificaram diversas peculiaridades que fazem
do teste a aplicações móveis diferente do teste a aplicações tradicionais. Entre estas peculiaridades
destacam-se os recursos limitados, a baixa autonomia, os novos conceitos de desenvolvimento, a
diversidade de dispositivos móveis e das suas características e o facto de serem cientes do contexto,
7
8 Estado da arte
isto é, as aplicações móveis dependem de dados obtidos pelos provedores de contexto (como o
GPS, Wi-Fi, 3G, Sensor de luz, etc).
Além disso, Muccini et al. identificaram diferentes tipos de testes que devem ser realizados a
aplicações móveis:
• Performance and reliability testing – Validar o comportamento da aplicação relativamente
aos recursos disponíveis, qualidade da conectividade e a outros tipos de informação con-
textual. Berardinelli et al. [15] apresentaram uma framework para modelar e analisar o
desempenho de aplicações móveis cientes do contexto. Em 2018, Delia et al. [21] apre-
sentaram um estudo relativamente ao desempenho das abordagens usadas para desenvolver
aplicações móveis para Android e iOS. Neste estudo, os autores constatam ainda que o
desempenho de uma aplicação móvel afeta a preferência do utilizador para o seu uso.
• Memory and Energy testing – Verificar a existência de memory leaks. Este tipo de teste é
importante devido aos recursos limitados de memória e à pouca autonomia que, por norma,
caracterizam os dispositivos móveis. Palit et al. [60] apresentou uma metodologia para se-
lecionar casos de teste com o intuito de realizar avaliações do custo de energia de aplicações
móveis. Em 2018, Banerjee et al. [14] consideraram os problemas de eficiência de ener-
gia em aplicações móveis como bugs de energia. Neste estudo, os autores desenvolveram
o EnergyPatch, uma framework que faz uma análise híbrida para detetar, validar e reparar
bugs de energia em aplicações Android.
• Security testing – Controlar o acesso a informação sensível e privada (palavras-passe, loca-
lização, etc). A garantia de segurança e privacidade é crucial nas aplicações móveis não só
devido ao aumento do uso de aplicações críticas mas também devido à natureza móvel do
dispositivo que o pode fazer aceder a diferentes redes com diferentes níveis de segurança.
Em 2016, Keng et al. [36] apresentaram o MAMBA, um sistema de teste para análise de
privacidade em aplicações Android. O trabalho realizado por Knorr et al. [38] é outro exem-
plo deste tipo de teste. Neste trabalho, foi proposta uma abordagem para testar aplicações
Android na área da saúde que considerava possíveis cenários de ataque e vulnerabilidades
especificas do domínio.
• GUI testing – Garantir o correto comportamento da GUI de uma aplicação móvel. Este
tipo de teste é importante porque a GUI é o único canal de comunicação entre o utilizador
e a aplicação. Existem algumas abordagens, propostas por diversos autores, que têm como
objetivo encontrar falhas na GUI. A iMPAcT tool [49, 50, 51, 53, 54, 55], alvo desta disser-
tação, é um exemplo de uma ferramenta que testa a interface do utilizador e que se encontra
descrita no capítulo 3. Nu et al. [32] apresentaram uma abordagem para detetar bugs na
GUI de uma aplicação Android através da geração automática de casos de teste, execução
de eventos aleatórios e produção e análise de ficheiros com informações detalhadas sobre a
aplicação. Costa et al. [19] apresentaram uma abordagem de teste à GUI onde eram gerados
casos de teste a partir de um modelo baseado em padrões da aplicação.
2.1 Testes a aplicações móveis 9
• Product line testing – Garantir o correto funcionamento de uma aplicação em diferentes dis-
positivos. Estes testes são importantes devido às diferentes características dos dispositivos
móveis presentes no mercado, sobretudo quando nos referimos aos dispositivos Android.
No entanto, devido ao elevado número de dispositivos com diferentes características, torna-
se praticamente impossível testar uma aplicação móvel em todos estes dispositivos. Por
esta razão, Zhu et al. [17] propuseram uma abordagem para seleção de dispositivos móveis
de teste usando um algoritmo genético multiobjectivo. Esta seleção é feita tendo em conta
vários requisitos como: custo do teste, cobertura das plataformas e cobertura das caracterís-
ticas dos dispositivos.
Em 2014, Gal et al. [30] identificaram as principais infraestruturas de teste de aplicações
móveis:
• Emulation-based testing – Envolve o uso de um emulador, que cria uma máquina virtual do
dispositivo móvel no computador. Apesar de ser uma técnica com baixo custo, ela possui
várias limitações, tais como a sua ineficiência a avaliar a qualidade do serviço da aplicação.
• Device-based testing – Consiste na execução dos testes da aplicação num dispositivo real.
Envolve um custo maior que o baseado em emulação devido à necessidade de aquisição dos
dispositivos.
• Cloud testing – Baseado em dispositivos ou emuladores que são acessíveis através da cloud
nos quais as aplicações podem ser instaladas e os testes executados.
• Crowd-based testing – Baseado num conjunto de pessoas que usam a aplicação. Devido à
tendência emergente deste tipo de infraestrutura, Zhang et al. [78] propuseram uma aborda-
gem para melhorar o poder do público no teste de aplicações Android.
2.1.2 Testes de caixa branca e testes de caixa preta
Existem duas técnicas de teste de software principais para encontrar possíveis erros em apli-
cações:
• Testes de caixa branca – Nesta técnica o tester tem acesso ao código fonte e conhece a
estrutura interna da aplicação. Ela tem como principal objetivo revelar erros de implemen-
tação da aplicação em teste, analisando o seu funcionamento interno [28].
• Testes de caixa preta – Técnica na qual a funcionalidade da aplicação é testada sem ter
conhecimento da sua estrutura interna. Nesta técnica não existe acesso ao código fonte
da aplicação e apenas são verificadas as saídas geradas com base nas entradas que foram
fornecidas.
Existe ainda outra técnica que resulta da combinação das duas anteriores: testes de caixa cinza.
Esta técnica é usada para testar uma aplicação com conhecimento do seu mecanismo interno e
também com conhecimento dos requisitos fundamentais do sistema [28].
10 Estado da arte
2.1.3 Ferramentas de suporte
Nesta subsecção serão descritas algumas ferramentas de suporte a abordagens de teste de apli-
cações móveis Android.
2.1.3.1 UI Automator
O UI Automator [8] é uma framework de testes oficial da Google, cuja primeira versão surgiu
em novembro de 2012. Esta framework fornece um conjunto de APIs para a criação de testes à
interface do utilizador que interagem não só com as aplicações do utilizador, mas também com as
aplicações do próprio sistema. A framework é adequada para a criação de testes de caixa preta.
As suas principais funcionalidades incluem:
• Um visualizador capaz de obter e analisar os componentes da interface do utilizador, que
estão a ser mostrados no dispositivo nesse momento;
• Uma API para aceder e realizar operações no dispositivo Android no qual a aplicação está a
correr. Esta API permite também aceder às propriedades do dispositivo;
• Várias APIs que permitem escrever testes robustos à interface do utilizador de uma aplica-
ção. Estas APIs suportam a criação de testes cross-app.
As principais desvantagens desta framework são:
• Os dispositivos de destino devem ter a versão 4.3 ou acima do Android;
• Apenas suporta aplicações nativas.
2.1.3.2 Espresso
O Espresso [7] é uma framework oficial disponibilizada pela Google, tendo a sua versão 2.0
sido lançada em dezembro de 2014. Ela fornece um conjunto de APIs para a criação de testes
à interface do utilizador que testam casos de uso da aplicação. O estilo de teste do Espresso é
considerado de caixa branca e, por esta razão, ele é focado numa única aplicação. As principais
funcionalidades desta framework são:
• APIs capazes de aceder aos elementos presentes na interface do utilizador de forma a inte-
ragir com eles;
• Um conjunto de APIs que facilitam a automatização das interações na interface do utiliza-
dor;
• Sincronização no thread da interface do utilizador.
2.1 Testes a aplicações móveis 11
A maior vantagem do Expresso é a sua capacidade de sincronização automática das ações de
teste com a interface de utilizador da aplicação, isto é, não é necessário esperar tempo após as
interações para garantir que a interface respondeu. Outra das vantagens é a grande percentagem
de dispositivos que suporta, visto que apenas exige a versão 2.2 ou superior do Android. A maior
desvantagem desta framework é que ela apenas suporta aplicações nativas.
2.1.3.3 Robotium
O Robotium [62] é uma das frameworks de teste não oficiais mais populares no mundo An-
droid, tendo a sua primeira versão sido lançada em janeiro de 2010. Esta framework possui uma
API simples que facilita o processo de criação de testes automáticos à interface do utilizador.
Algumas das suas principais vantagens são:
• Suporte para o teste de aplicações nativas e híbridas;
• Grande percentagem de dispositivos suportado, visto que apenas necessita da versão 2.2 ou
superior do Android;
• Possui um estilo de teste caixa preta;
• Capacidade de gerir automaticamente várias atividades na aplicação;
• Pode ser integrado facilmente com o Maven, Gradle ou Ant para executar testes como parte
da integração contínua;
• Casos de teste são robustos devido ao binding em tempo real nas componentes da interface;
• Capacidade para aceder e modificar os serviços e os sensores do dispositivo.
No entanto, como em todas as frameworks existentes, ela possui também algumas desvanta-
gens que incluem [53]:
• O nome da atividade principal da aplicação em teste deve estar hard coded;
• Apenas é possível aceder aos serviços e sensores para os quais a aplicação em teste tem
permissão;
• Não é possível ler o conteúdo de um ecrã.
2.1.3.4 Appium
O Appium [12] é uma framework de automatização de testes open source que surgiu em abril
de 2013. As suas principais vantagens são:
• Tem suporte para o teste de aplicações nativas, híbridas e web;
12 Estado da arte
• É cross-platform, ou seja, permite escrever testes para várias plataformas, através da mesma
API;
• Não necessita de acesso ao código da aplicação em teste;
• Suporta diferentes linguagens e frameworks;
• Os testes podem ser executados num emulador ou num dispositivo real;
• Permite aceder e modificar o estado dos serviços e sensores do dispositivo;
• Nome do package da aplicação e o nome da sua atividade principal podem ser fornecidos
como input.
Contudo, o Appium possui também algumas desvantagens [53]:
• Não está ainda num estado estável, produzindo, por vezes, alguns erros inesperados;
• Não consegue ler os conteúdos do ecrã;
• Não é possível localizar um elemento pelo seu identificador.
2.1.3.5 Selendroid
O Selendroid [26] é também uma framework open source de automatização de testes à UI de
aplicações Android. Algumas das vantagens desta framework são:
• Suporte para o teste de aplicações nativas, híbridas e web;
• Pode ser usada em emuladores ou em dispositivos reais;
• Suporta praticamente todas as versões do Android;
• Não necessita de acesso ao código da aplicação em teste;
• Dispositivos externos podem ser conectados e desconectados do computador durante a exe-
cução do teste, sem este reiniciar ou parar;
• Suporta o reconhecimento dos elementos usando as suas propriedades;
• Tem incorporada uma ferramenta de inspeção que ajuda a identificar elementos da interface
da aplicação em teste.
As principais desvantagens do Selendroid são [53]:
• Não é possível aceder nem modificar o estado dos sensores e serviços do dispositivo;
• A ferramenta de inspeção não pode ser usada programaticamente porque esta não oferece
uma API.
2.2 Teste baseado em modelos 13
2.1.3.6 Calabash
Desenvolvido pela equipa do Xamarin, o Calabash [73] surgiu em 2012 e é uma framework de
teste open source que funciona tanto em Android como em iOS. Algumas das principais vantagens
desta framework são:
• É possível ter acesso e modificar o estado dos sensores e serviços do dispositivo;
• Possui uma sintaxe de fácil compreensão;
• É possível correr os testes em emuladores ou em dispositivos reais;
• Apresenta relatórios de desempenho do hardware do dispositivo;
• Tem suporte para o teste de aplicações nativas e híbridas.
Algumas das desvantagens do Calabash são [53]:
• Não é possível ler o conteúdo de um ecrã;
• Apenas é possível usar a linguagem de programação Ruby;
• O estilo de teste é caixa branca;
• A sua configuração é mais complicada que a do Appium.
2.2 Teste baseado em modelos
A técnica de teste baseado em modelos permite a geração automática de casos de teste [55, 37,
43, 47, 58, 71, 74]. Para isto, é necessário fornecer um modelo do comportamento da aplicação
e, a partir deste, são criados os casos de teste para execução. No entanto, esta técnica possui dois
problemas principais [55]:
• A necessidade de um modelo da aplicação como input, cujo processo de construção é mo-
roso e sujeito a erros;
• A explosão combinatória de casos de teste.
O primeiro problema pode ser resolvido por um processo de engenharia reversa da aplicação
em teste ou através do aumento do nível de abstração dos modelos. O segundo problema pode ser
resolvido escolhendo um conjunto dos testes para execução ou focando-se numa área específica
da aplicação [55].
O Pattern-Based GUI Testing (PBGT) [46, 48] é uma abordagem de teste baseado em modelos,
cujo principal objetivo é automatizar e sistematizar o processo de teste à interface do utilizador.
Nesta abordagem são resolvidos os principais problemas deste tipo de técnica. Em primeiro lu-
gar, o esforço de construção do modelo é reduzido comparado com outras técnicas de modelação
da GUI. Em segundo lugar, esta abordagem foca-se numa área especifica da aplicação, testando
apenas comportamento recorrente, isto é, UI Patterns.
14 Estado da arte
2.3 Engenharia reversa
A maior parte das abordagens de engenharia reversa existentes foca-se em aplicações web,
como é o caso do trabalho realizado por Maezawa et al. [42] que apresenta uma abordagem
estática para extrair todas as transições de estados possíveis descritas no código fonte da aplicação
web. Existem também abordagens a aplicações desktop, tais como o GUISurfer [64] que permite
extrair modelos de comportamentos de aplicações com GUI através de uma análise estática. No
entanto, com o aumento da importância e uso dos smartphones, tem-se verificado um crescimento
do número de abordagens de engenharia reversa a aplicações móveis.
No contexto desta dissertação, a pesquisa em engenharia reversa presente nesta secção está
associada a aplicações móveis Android.
As abordagens de engenharia reversa podem ser divididas em três tipos:
• Estática – Recolha de informação através da análise direta do código fonte da aplicação;
• Dinâmica – Obtenção de informação através da análise da aplicação em execução;
• Híbrida – Extração de informação através da análise da aplicação em execução e do seu
código fonte.
Devido à natureza dinâmica e baseada em eventos das aplicações móveis, quando o objetivo
de uma abordagem é testar o comportamento da aplicação, a análise estática não é a ideal [50, 53].
As abordagens de engenharia reversa em aplicações móveis podem servir de suporte tanto para
a construção de modelos, de forma a melhor compreender a aplicação, como para implementações
de abordagens de teste.
Em 2011, Amalfitano et al. divulgaram o A2T2 [1], uma ferramenta de crawling capaz de
testar uma aplicação para verificar a existência de crashes. Esta ferramenta é também capaz de
extrair o modelo da aplicação que é constituído pelas suas interfaces e a relação entre elas. Em
2012, eles desenvolveram o AndroidRipper [2]. Esta ferramenta faz uma análise dinâmica da
interface da aplicação em teste de forma a obter sequências de eventos que possam ser executados
através dos widgets da GUI e é capaz de extrair a árvore de interfaces e de testar a aplicação para
verificar a presença de crashes.
Yang et al. [75] apresentaram uma abordagem para extrair automaticamente um modelo de
uma aplicação móvel Android. Nesta abordagem é realizada uma análise estática para obter os
eventos suportados pela GUI da aplicação em teste. Após esta fase, é feita uma exploração dinâ-
mica da aplicação para obter o seu modelo.
De forma a analisar as vulnerabilidades associadas à segurança de uma aplicação, Dar e Parvez
[20] propuserem a implementação de um abordagem que começa por descompilar uma aplicação
Android e remover as permissões indesejadas. Após esta fase, é feita uma análise do código fonte
da aplicação para implementar as aprovações das permissões em tempo de execução. Finalmente,
o código é recompilado e, em tempo de execução, é perguntado ao utilizador se pretende fornecer
ou não as permissões necessárias.
2.4 Cobertura 15
Em 2016, Ting Su [69] propôs o FSMdroid, uma ferramenta que combina engenharia reversa
com a técnica de teste baseado em modelos para testar uma aplicação Android. O processo de
engenharia reversa inclui uma análise dinâmica para obter a máquina de estados da aplicação
e uma análise estática para identificar os eventos da interface que podem não ser encontrados
durante a análise dinâmica.
2.4 Cobertura
Para avaliar se os testes realizados a uma aplicação abrangem toda esta aplicação, é feita,
normalmente, uma análise de cobertura dos testes. Em particular, no que respeita a aplicações
móveis, existem duas análises de cobertura que podem ser realizadas:
• Cobertura de código – É uma medida que indica a quantidade do código da aplicação
que foi executado durante os testes. Esta análise inclui diversos tipos de cobertura como:
classes, métodos, linhas, entre outros.
• Cobertura de eventos – Devido à natureza baseada em eventos das aplicações móveis,
torna-se importante analisar também a quantidade de eventos que foram exercitados durante
os testes. Esta análise é particularmente útil quando se pretendem validar técnicas de análise
dinâmica de aplicações móveis.
Relativamente ao tipo de teste a executar, as técnicas de cobertura de código podem ser dividi-
das em dois tipos: 1) cobertura para testes de caixa branca; 2) cobertura para testes de caixa preta.
A maior parte das ferramentas de exploração a aplicações móveis enquadra-se neste segundo tipo.
De seguida, são apresentados alguns trabalhos recentes no que diz respeito a cobertura para
testes de caixa preta.
Em 2015, Yeh et al. apresentaram o CovDroid [76], uma ferramenta para medir a cobertura de
testes do estilo caixa preta em aplicações móveis Android. Esta ferramenta possui três módulos:
instrumentação, monitorização da execução e gestor de relatórios de cobertura. No módulo de
instrumentação, a aplicação em teste é descompilada para o formato Jasmin [35] usando o smali
[65], instrumentada ao nível da classe, recompilada e automaticamente instalada no dispositivo
Android. O módulo de monitorização analisa a execução da aplicação através do Android Debug
Bridge [6] produzindo o registo desta execução. Finalmente, o módulo gestor de relatórios de
cobertura analisa o registo produzido e calcula a cobertura para os casos de teste executados.
Zhauniarovich et al. propuseram o BBOXTESTER [79], uma framework para gerar relatórios
de cobertura de código no teste de aplicações Android. Tal como o CovDroid, esta framework é
constituída por três componentes principais: Instrumenter, Executor e Reporter. O Instrumenter
faz uso do apktool [10] para descompilar o APK e extrair os ficheiros .dex e o manifesto da
aplicação. De seguida, estes ficheiros .dex são processados com o dex2jar [25] para transformar o
bytecode Dalvik em bytecode Java que é posteriormente instrumentado com a ferramenta Emma
[29]. Após esta instrumentação, os ficheiros Java são recompilados em ficheiros .dex, e estes no
APK final utilizando novamente o apktool. O Executor instala a aplicação no dispositivo, inicia
16 Estado da arte
e termina a sua execução, extrai os resultados e desinstala a aplicação. Durante o início e o fim
da execução, o utilizador pode correr os seus próprios casos de testes ou explorar a aplicação
manualmente. Finalmente, o Reporter cria relatórios de cobertura com base nos dados gerados
durante a instrumentação e execução da aplicação. Nestes relatórios está presente informação de
cobertura ao nível da classe, método e bloco básico.
Huang et al. [33] reconheceram que, apesar da sua importância, a capacidade de cobertura
da maior parte de ferramentas de análise dinâmica é desconhecida. Desta forma, apresentaram
uma abordagem semelhante à presente no CovDroid e no BBOXTESTER que consiste em extrair
os ficheiros do APK e descompilá-los usando o smali. De seguida, através de um compilador
implementado pelos autores, é feito parse ao código dos ficheiros smali e é feita a sua instrumen-
tação. Este código de instrumentação é inserido de forma a dar informação de cobertura ao nível
da classe, método, bloco e linha. Finalmente, é feita a recompilação em ficheiros .dex (usando o
smali) e estes no ficheiro APK (usando o apktool). Nesta fase, a aplicação está pronta para ser
executada de forma a serem produzidos os resultados de cobertura.
Em 2017, Liu et al. apresentaram o InsDal [40], uma ferramenta para inserir instruções no
bytecode Dalvik de acordo com requisitos específicos do utilizador, como as instruções que devem
ser instrumentadas. A ferramenta possui três módulos: Disassembling and Repackaging, Analysis
e Instrumentation. O módulo Disassembling and Repackaging é responsável por extrair o bytecode
Dalvik do APK e por recompilar os ficheiros modificados num novo APK (usando o apktool). O
módulo Analysis é responsável por determinar que instruções serão inseridas de acordo com os
requisitos do utilizador. Por último, o módulo Instrumentation consiste em três fases: 1) procurar
registos seguros para o código instrumentado; 2) instrumentar as instruções de acordo com os
resultados do módulo Analysis; 3) otimizar o código instrumentado de forma a reduzir os recursos
necessários. De acordo com os autores, esta ferramenta pode ajudar a medir a cobertura de código
e a obter o trace de execução da aplicação.
Mais recentemente, Pilgun et al. apresentaram o ACVTool [61], uma ferramenta de instrumen-
tação de aplicações Android para medir a cobertura do código smali ao nível da classe, método
e instrução. Esta ferramenta possui três fases relativamente ao seu fluxo de trabalho: 1) offline,
2) online e 3) geração do relatório. A fase offline é responsável por todo o pré-processamento da
aplicação que inclui a descompilação, instrumentação, recompilação e assinatura. A fase online é
responsável pela instalação da aplicação no dispositivo e pela recolha dos dados de cobertura du-
rante os testes. A última fase consiste na produção do relatório de cobertura do código em formato
HTML e XML. Este relatório é produzido com base nos dados recolhidos na fase anterior e nos
que foram criados ao instrumentar a aplicação. Na avaliação realizada pelos autores, a ferramenta
foi capaz de instrumentar com sucesso 96.9% das aplicações utilizadas.
No que diz respeito à medição de cobertura a testes de caixa branca, existem já algumas
ferramentas disponíveis para uso. O restante desta secção apresenta duas das ferramentas mais
populares relativamente a este tipo de cobertura.
O Emma [29] é uma ferramenta open source de cobertura baseada em Java. Esta ferramenta
tem algumas vantagens como: 1) produção de um relatório detalhado com informação ao nível
2.5 Exploração dinâmica 17
da classe, método, bloco e linha; 2) está incorporada no Android SDK; 3) bom desempenho.
No entanto, esta ferramenta possui também alguns problemas como: 1) ausência de suporte para
instrumentação on-the-fly, ou seja, não é possível medir a cobertura de binários pré-compilados;
2) não possui cobertura ao nível do branch; 3) apenas suporta bytecode Java [76]; 4) é necessário
fazer pequenas alterações ao código fonte para que a ferramenta funcione; 5) relatório dos testes é
criado no dispositivo.
O JaCoCo [27] é também uma ferramenta popular de análise de cobertura open source. As
suas principais vantagens são: 1) fácil integração com vários IDEs; 2) produção de um relatório
detalhado com informação ao nível da classe, método, bloco, linha e branch; 3) bom desempenho;
4) suporta instrumentação on-the-fly e offline. Apesar disto, existem também alguns problemas
com a ferramenta como: 1) é necessário fazer pequenas alterações ao código fonte para que a
ferramenta funcione; 2) relatório dos testes é criado no dispositivo.
2.5 Exploração dinâmica
As técnicas de exploração dinâmica da interface são muito usadas no contexto de aplicações
móveis devido à sua natureza baseada em eventos. Estas técnicas podem fornecer suporte a pro-
cessos de engenharia reversa ou a processos de teste a estas mesmas aplicações.
As abordagens de exploração dinâmica de uma aplicação móvel podem seguir diferentes es-
tratégias:
• Aleatória – São gerados eventos aleatórios nas interfaces da aplicação;
• Heurística – A decisão do evento a ser executado é feita com base em heurísticas que guiam
todo o processo de exploração;
• Active Learning – O modelo é construído à medida que são feitos testes à aplicação. Com
base nesse modelo, é decidido que evento deve ser executado.
O restante desta secção descreve algumas ferramentas e trabalhos recentes na área de explora-
ção dinâmica em aplicações móveis.
O Monkey [9] é uma ferramenta da Google incorporada no Android SDK. Esta ferramenta é
capaz de gerar sequências de eventos pseudoaleatórios diretamente na interface de uma aplicação
Android de forma automática, sendo que o seu principal objetivo é detetar possíveis crashes na
aplicação em teste. Esta ferramenta permite ainda que uma execução seja reproduzida mais tarde,
bastando para isso que o valor da opção seed, usado para geração de números pseudoaleatórios,
seja o mesmo nas duas execuções.
Em 2014, Wang et al. [72] apresentaram uma abordagem que considerava a estrutura de uma
aplicação Android como uma árvore de interfaces, onde cada nó representa uma GUI e uma aresta
representa uma interação entre duas GUIs. Esta abordagem possui um algoritmo de exploração em
profundidade onde os eventos que são executados dependem da análise dinâmica feita à interface
atual da aplicação. Neste algoritmo são guardadas duas listas: 1) lista hierárquica que guarda os
18 Estado da arte
componentes, layout e descrições das interfaces e a 2) lista de eventos que guarda os eventos exe-
cutados em cada elemento. Nesta abordagem existe ainda uma técnica de rollback que é aplicada
para obter a próxima interface alvo (última interface ainda não totalmente explorada) quando a
exploração da lista hierárquica termina. Esta técnica de rollback consiste em: 1) parar a aplicação;
2) voltar a iniciar a aplicação; 3) executar os eventos na lista de eventos até ser atingida a próxima
interface alvo. Esta abordagem encontra-se implementada numa ferramenta, DroidCrawle.
Machiry et al. [41] propuseram o Dynodroid, um sistema para geração de sequências de
inputs relevantes numa aplicação Android. Neste trabalho, os autores reconheceram a necessidade
de introduzir inteligência humana para exercitar certas funcionalidades da aplicação que de forma
automática não seria possível. Desta forma, o sistema permite que o utilizador pause a geração
de eventos do sistema, introduza a sua sequência de eventos diretamente na interface da aplicação
móvel e retome novamente a geração de eventos do sistema. Este sistema é composto por três
componentes: 1) executor, responsável pela execução dos eventos selecionados pelo selector e
pela troca entre a geração automática e a geração manual de eventos; 2) observer, encarregue
de calcular o conjunto de eventos relevantes sempre que um evento é executado; 3) selector,
responsável por selecionar o evento a executar a partir do conjunto de eventos calculado pelo
observer.
Moran et al. [44, 45] apresentaram o CrashScope, uma ferramenta que explora dinamica-
mente uma aplicação Android e que extrai os componentes da interface à medida que estas são
exploradas. Durante a exploração, a ferramenta identifica os componentes que são clickable e
long-clickable e adiciona-os a uma stack dinâmica de componentes para serem executados. Ainda
durante esta fase, são também identificados os componentes de input de texto disponíveis. Para
estes componentes é detetado o tipo de texto esperado e, após esta deteção, é gerado este mesmo
texto de acordo com duas heurísticas: 1) esperada, que gera uma string de acordo com os pa-
râmetros do teclado, sem pontuação ou caracteres especiais e 2) não esperada, que gera strings
aleatórias com todos os caracteres permitidos. O seu objetivo é tentar detetar crashes devido ao
incorreto tratamento do texto de input no código da aplicação. Ao longo da execução, o CrashS-
cope guarda informação sobre a aplicação como os inputs, screenshots, exceções e crashes de
forma a serem produzidos relatórios e scripts para reprodução da execução.
Azim et al. [13] apresentaram o A3E, uma ferramenta que implementa uma estratégia de
exploração a aplicações Android baseada em modelos. Esta ferramenta possui dois modos de
exploração: 1) Depth-first Exploration, que tem como objetivo explorar a aplicação de modo se-
melhante a um utilizador, isto é, injetando uma sequência de eventos na interface da aplicação
Android; 2) Targeted Exploration, cujo objetivo é obter uma rápida exploração das atividades fa-
zendo uso de um SATG (Static Activity Transition Graph). Os autores reconheceram a existência
de atividades especiais, isto é, atividades que não podem ser invocadas com a interação do utiliza-
dor na aplicação e, por esta razão, implementaram o modo Targeted Exploration, capaz de listar
todas as atividades que podem ser chamadas sem a intervenção do utilizador e gerar chamadas que
invoquem estas mesmas atividades. Como resultado da exploração são criados relatórios com o
trace da execução e com informação de cobertura.
2.5 Exploração dinâmica 19
Em 2013, Choi et al. propuseram o SwiftHand [18], uma técnica automática que utiliza active
learning para construir o modelo da aplicação durante os testes. O algoritmo de exploração au-
tomática implementado nesta técnica faz uso do modelo da aplicação construído até ao momento
para selecionar o próximo evento a executar. Caso seja detetado um componente na interface com
o tipo EditText, é gerada uma string pré-definida ou aleatória de forma a melhorar o processo de
exploração. O SwiftHand tenta explorar todos os estados da aplicação que podem ser atingidos
pelo seu estado inicial de forma a reduzir o número de reinícios da aplicação e, por conseguinte,
reduzir o overhead introduzido por este reinício. Os autores reconhecem ainda que a única forma
fiável de reiniciar uma aplicação é através da sua desinstalação e posterior reinstalação, principal-
mente quando a aplicação em questão possui informação persistente.
AndroidRipper [2] é uma ferramenta desenvolvida por Amalfitano et al. que implementa es-
tratégias de exploração aleatória e sistemática à interface de uma aplicação móvel Android. Esta
ferramenta tem como objetivo detetar falhas na aplicação que podem depender de diversos fatores.
Por esta razão, o utilizador da ferramenta pode configurar previamente a estratégia de exploração
atribuindo valores aos seus parâmetros, como o tempo entre a execução de dois eventos consecuti-
vos, valores para os componentes de input nas interfaces, critério de exploração da interface, entre
outros. O funcionamento do AndroidRipper baseia-se em três fases. A primeira fase consiste em
atravessar a aplicação injetando eventos e extrair a máquina de estados que representa a aplicação.
A segunda fase consiste na geração das diferentes sequências de eventos. Finalmente, na terceira
fase os casos de teste são executados de forma a detetar falhas na aplicação em teste. Alguns anos
mais tarde, esta abordagem foi melhorada, surgindo o MobiGUITAR [3], uma ferramenta de testes
baseados em modelos.
Hao et al. [31] apresentaram o PUMA, uma framework programável que pode ser usada para
analisar dinamicamente certas propriedades de uma aplicação Android, tal como a segurança ou o
desempenho. Esta framework incorpora na sua análise dinâmica a estratégia básica de exploração
do Monkey que pode ser configurável de forma a guiar o processo de exploração da aplicação.
O PUMA recebe dois inputs do utilizador: 1) o binário da aplicação e 2) o código específico do
utilizador, escrito em linguagem PUMAScript. Este código fornecido como input contém diretivas
especificas da aplicação e diretivas especificas do Monkey. As diretivas especificas da aplicação
indicam que partes do código são importantes para análise e as ações a executar quando esse
código é atingido. As diretivas especificas do Monkey fornecem informação que guia o processo
de execução da aplicação pelo Monkey.
Stoat [70] é uma abordagem para executar testes estocásticos baseados em modelos a apli-
cações Android. O processo de operação da abordagem apresenta duas fases. A primeira fase
consiste na construção da máquina de estados finita estocástica, que descreve o comportamento
da aplicação, através de uma análise dinâmica e estática da aplicação. Na análise dinâmica, os
eventos são inferidos através da leitura da hierarquia das interfaces existentes na aplicação e é
criada uma prioridade para estes de forma a maximizar a cobertura de código. Na análise estática,
é analisado o código da aplicação para identificar eventos que não tenham sido encontrados pela
análise dinâmica. A segunda fase consiste, a partir do modelo construído na fase anterior, na gera-
20 Estado da arte
ção de testes de forma a criar diversas sequências de eventos a executar. Ao longo dos testes, são
também executados eventos do sistema de forma aleatória para melhorar a eficácia do processo de
teste. Esta abordagem é uma evolução ao FSMdroid [69].
Droidmate [34] é uma ferramenta automática para geração de testes através de uma explora-
ção dinâmica da aplicação Android em teste. Esta ferramenta efetua uma ligeira modificação ao
nível do bytecode Dalvik das aplicações para permitir a monitorização dos métodos das APIs do
Android SDK. Após a modificação, a aplicação é instalada no dispositivo e a sua atividade princi-
pal iniciada. Nesta fase, a ferramenta começa o processo de exploração da aplicação que consiste
em: 1) ler a interface do dispositivo em tempo de execução e verificar as chamadas aos métodos
das APIs do Android SDK; 2) decidir que evento executar com base na estratégia de exploração
configurada e nos dados recolhidos. Em 2018, a abordagem presente no Droidmate foi melho-
rada surgindo o Droidmate-2 [16]. Esta nova ferramenta estende o mecanismo de exploração do
Droidmate, com a inclusão de um conjunto de estratégias de exploração e de seletores que ajudam
a decidir o próximo evento a executar, com base no estado atual da aplicação.
Muslu et al. [39] propuseram uma abordagem de exploração de aplicações Android baseada
em Q-Learning. Esta abordagem é dividida em três fases diferentes. A primeira fase consiste na
execução de um conjunto de aplicações Android de treino através de uma estratégia de exploração
aleatória de forma a serem obtidos os seus modelos. Na segunda fase, os modelos obtidos são
usados para a construção da Q-Matrix relativamente a um objetivo específico. Este objetivo pode
ser detetar um crash ou aumentar a cobertura de atividades da aplicação móvel em teste. Final-
mente, na terceira fase, é possível testar uma aplicação Android através da execução das ações
fornecidas pela Q-Matrix. No final do processo de teste, é criado um modelo da aplicação para
facilitar a técnica de teste baseado em modelos. Esta abordagem encontra-se implementada na
ferramenta AndroFrame, juntamente com uma estratégia de exploração aleatória e uma estratégia
de exploração em profundidade.
Mais recentemente (2019), Amalfitano et al. [4] apresentaram o juGULAR, uma abordagem
de exploração híbrida que combina exploração automática da GUI com Capture and Replay. A
abordagem utiliza técnicas de Machine Learning para treinar classificadores que são usados para
detetar automaticamente a presença de uma Gate GUI (neste documento chamado de ponto de blo-
queio). Nesta situação, o utilizador pode intervir para desbloquear a Gate GUI detetada inserindo
uma sequência de inputs diretamente na interface da aplicação móvel. Esta interação do utiliza-
dor é gravada pelo juGULAR e reproduzida sempre que a mesma Gate GUI é detetada durante a
exploração. Neste estudo, foram consideradas duas classes de Gate GUIs: login e definições de
rede.
A iMPAcT tool é uma ferramenta que explora automaticamente uma aplicação móvel An-
droid de forma a identificar e testar comportamento recorrente (UI Patterns). Esta ferramenta será
descrita com mais pormenor no Capítulo 3.
2.6 Conclusões 21
2.6 Conclusões
Nos dias de hoje, o teste de aplicações móveis é um tema emergente devido à quantidade
deste tipo de aplicações disponíveis no mercado. Por esta razão, os investigadores têm-se focado
na automatização do processo de teste e têm criado diversas abordagens para garantir que estas
aplicações funcionam corretamente. Este processo de teste pode ser feito a vários níveis, tais como
desempenho, segurança, interface, entre outros.
A exploração dinâmica é uma técnica muito usada para garantir que uma aplicação funciona
corretamente obtendo informação dessa aplicação em tempo de execução através da sua interface.
Esta técnica assume ainda maior importância devido à natureza baseada em eventos das aplica-
ções móveis. No entanto, a maior parte das abordagens existentes falham na exploração total da
aplicação, ou porque não conseguem exercitar todos os eventos disponíveis, ou porque atingiram
um ponto de bloqueio que impede que a exploração prossiga para novos estados.
Existem diversas ferramentas baseadas em exploração dinâmica de aplicações móveis, no en-
tanto, muitas vezes a sua eficácia é desconhecida, isto é, não é possível ter informação sobre se
a ferramenta conseguiu analisar completamente a aplicação em questão. Por esta razão, torna-se
muito importante analisar a cobertura de código da aplicação de forma a conseguirmos avaliar
uma técnica de exploração dinâmica. Atualmente, existem abordagens de análise de cobertura
para testes do estilo caixa preta, isto é, testes que não requerem acesso direto ao código fonte e
abordagens de análise de cobertura para testes do estilo caixa branca que, por outro lado, requerem
acesso direto ao código fonte da aplicação.
22 Estado da arte
Capítulo 3
iMPAcT tool
A iMPAcT tool [49, 50, 51, 53, 54, 55] é uma ferramenta criada num trabalho de investigação
anterior cujo objetivo é automatizar o processo de teste das interfaces de aplicações móveis An-
droid. Esta ferramenta combina engenharia reversa com comportamento recorrente, isto é, padrões
da interface. Na sua fase de exploração, caso seja identificado um comportamento recorrente, este
é testado de acordo com os padrões de teste correspondentes. Caso não seja identificado nenhum
comportamento recorrente, a exploração da aplicação prossegue.
O presente capítulo está dividido em cinco secções. Na Secção 3.1 é sumariada a abordagem
geral de teste da ferramenta. Na Secção 3.2 são apresentados alguns padrões presentes no catá-
logo de padrões bem como os padrões de teste associados. A Secção 3.3 apresenta os artefactos
produzidos como resultado das execuções da ferramenta. A Secção 3.4 descreve as principais con-
tribuições que a iMPAcT tool fornece à comunidade. Finalmente, na Secção 3.5 são apresentadas
as conclusões da análise realizada à ferramenta.
3.1 Abordagem
Como já foi referido, o objetivo da abordagem presente na ferramenta é testar comportamento
recorrente (UI Patterns) existente nas aplicações móveis Android. A abordagem, suportada pela
iMPAcT tool, encontra-se ilustrada no diagrama de componentes da Figura 3.1.
3.1.1 Implementação
Os três componentes principais que constituem a abordagem são [51]:
• Patterns Catalogue – Contém o conjunto de UI Patterns, que devem ser identificados pela
ferramenta nas aplicações móveis, e os Test Patterns associados. O utilizador, no processo
de configuração do teste da aplicação, deve indicar que padrões, presentes neste catálogo,
23
24 iMPAcT tool
Figura 3.1: Diagrama de componentes da abordagem implementada na iMPAcT tool [53]
devem ser identificados e testados. A Secção 3.2 apresenta alguns exemplos de padrões
existentes neste catálogo.
• Tool – Este componente é dividido em: 1) Explorer responsável por explorar automati-
camente a aplicação móvel usando engenharia reversa; 2) Tester que contém os métodos
utilizados para testar os UI Patterns identificados durante a fase de exploração.
• Platform Adaptor – Responsável por fazer a ligação entre a Tool e a aplicação que se pre-
tende testar. Este componente é dividido em outros dois componentes: 1) Observer res-
ponsável por obter o estado da aplicação; 2) Interactor responsável por executar eventos na
aplicação móvel.
3.1.2 Fases do processo iterativo
A execução da iMPAcT tool segue um processo iterativo no qual cada iteração é constituída
pelas seguintes fases [53, 50, 54]:
3.1 Abordagem 25
1. Exploração da aplicação em teste;
2. Identificação de UI Patterns;
3. Teste dos UI Patterns encontrados.
A responsabilidade da primeira fase pertence ao Explorer presente na Figura 3.1. Nesta fase,
existe uma análise do estado atual da aplicação que consiste numa leitura recursiva dos diferentes
elementos presentes no seu ecrã. Após esta análise, são identificados todos os eventos que podem
ser executados. Por último, é decidido que evento executar e é realizada essa execução.
Na segunda fase, após o evento decidido na fase anterior ser executado, é verificada a presença
de padrões na interface da aplicação analisando novamente o estado atual da aplicação. Todos os
padrões analisados nesta fase estão presentes no catálogo da ferramenta.
A terceira e última fase apenas é iniciada quando um ou mais padrões são detetados na fase
anterior. Esta fase consiste em aplicar os Test Patterns, presentes no catálogo de padrões, cor-
respondentes aos UI Patterns identificados. Aplicar um Test Pattern consiste em verificar se a
pré-condição do teste é verdadeira e, caso seja, executar as ações necessárias fazendo, no final, um
conjunto de verificações.
Um fator importante na fase de exploração são os eventos que a ferramenta tem capacidade
para executar. Atualmente, os eventos da interface do utilizador que estão implementados na
ferramenta são: click, check, long click, edit e scroll [53].
No fim do processo de teste, são produzidos artefactos com informação sobre a execução da
ferramenta. Estes artefactos são descritos na Secção 3.3.
3.1.3 Modos de exploração
A ferramenta implementa diferentes modos relativamente à decisão do evento a executar na
fase de exploração. Para isto, o utilizador necessita de definir, na interface da ferramenta, o modo
que pretende que seja usado neste processo de decisão. Atualmente, existem quatros modos dis-
poníveis que são [53]:
• Execute once – Cada evento apenas é executado uma vez, ou seja, caso um evento já tenha
sido executado nunca mais será considerado para nova execução.
• Priority to not executed – Tal como o anterior, este modo dá prioridade a eventos que ainda
não tenham sido executados. Num dado estado, caso todos os eventos existentes tenham sido
executados, este começa a considerar os que possam levar a estados que contenham eventos
ainda não executados. Neste modo de exploração existe ainda um limite de execuções para
cada evento, de forma a evitar ciclos.
• Priority to not executed and list items – Semelhante ao modo anterior, apresentando apenas
duas diferenças: 1) os eventos que são executados em elementos que pertencem a uma lista
têm maior prioridade que os restantes eventos; 2) o evento “click on the App button” apenas
26 iMPAcT tool
é selecionado quando não existem mais eventos disponíveis para executar. O objetivo desta
estratégia é de tentar explorar ao máximo o conteúdo do ecrã atual antes de mudar para um
novo ecrã.
• All events – Este modo de exploração é um modo sem restrições. Por esta razão, não existe
prioridade nos eventos a escolher, pelo que a sua execução é feita de forma aleatória.
Os tempos de execução da iMPAcT tool dependem do modo de exploração que foi, inicial-
mente, configurado [50].
3.1.4 Condição de paragem
A iMPAcT tool irá explorar a aplicação iterativamente até uma das duas seguintes condições
se verificar [53]:
• O utilizador pressionar o botão Home do dispositivo móvel, decidindo quando terminar a
exploração;
• Quando, após pressionar o botão Back, surge o ecrã principal do dispositivo. Durante a
exploração, este botão é pressionado numa tentativa de voltar ao ecrã anterior.
3.2 Catálogo de padrões
Como já foi referido, o objetivo da ferramenta é verificar se os UI Patterns, encontrados du-
rante a exploração da aplicação Android, estão corretamente implementados. Para isto, caso seja
encontrado um UI Pattern este é testado usando a estratégia de teste associada. Desta forma, a
definição do catálogo de padrões é uma das partes mais importantes de toda a abordagem. Este
catálogo apenas necessita de ser definido uma vez e é composto por um conjunto de UI Patterns
que se pretendem identificar e pelas estratégias de teste correspondentes [49].
Tanto o UI Pattern como os Test Patterns associados podem ser formalmente definidos como
um conjunto de tuplos <Objetivo, V, A, C, P> nos quais [50]:
• Objetivo é o ID do padrão;
• V é um conjunto de pares que incluem uma variável e um valor e que relaciona os dados
fornecidos com as variáveis envolvidas;
• A é a sequência de ações a executar;
• C é o conjunto de verificações a realizar;
• P é a pré-condição booleana que define as condições nas quais o padrão deve ser aplicado.
Para um padrão ser aplicado, o utilizador da ferramenta deve fornecer o valor para cada va-
riável em V. Após esta etapa, aplicar um padrão consiste em analisar se a pré-condição (P) é
3.2 Catálogo de padrões 27
verdadeira, e em caso afirmativo executar uma sequência de ações (A) utilizando os valores for-
necidos na configuração (V). No fim desta execução são realizadas um conjunto de verificações
(C).
Relativamente à identificação de um UI Pattern, a pré-condição (P) fornece informação sobre
se a ferramenta deve ou não tentar identificar este padrão, enquanto que as verificações finais (C)
indicam se o padrão foi ou não encontrado. Por outro lado, ao aplicar um Test Pattern a pré-
condição (P) fornece informação sobre se a estratégia de teste deve ser aplicada, enquanto que as
verificações finais (C) indicam se o teste passou ou não, ou seja, fornecem informação sobre se o
UI Pattern correspondente está ou não bem implementado.
Os padrões que estão presentes atualmente no catálogo da ferramenta são os seguintes: padrão
side drawer, padrão de orientação, padrão de dependência de recursos, padrão de background
[59], padrão de back, padrão de up, padrão de action bar, padrão de tabs e padrão de chamadas
[57]. Estes padrões têm por base as diretrizes fornecidas pela Google de como desenvolver e testar
aplicações móveis Android [23]. De seguida, serão apresentados os três primeiros padrões da lista
anterior.
3.2.1 Padrão side drawer
O Side Drawer (também conhecido como Navigation Drawer) é um menu que mostra as
principais opções de navegação da aplicação no lado esquerdo do ecrã. Este menu apenas é visível
quando o utilizador da aplicação desliza o dedo a partir do lado esquerdo do ecrã (swipe) ou quando
clica no ícone da aplicação no lado esquerdo da Action Bar. A Figura 3.2 ilustra um exemplo deste
padrão.
O UI Pattern responsável por identificar a presença deste menu numa interface da aplicação é
definido como [49, 53]:
• Objetivo: “Existe um Side Drawer”
• V: {}
• A: [Ler o ecrã]
• C: {“O Side Drawer existe e não está visível”}
• P: {Verdadeiro}
O Test Pattern correspondente, responsável por verificar se o UI Pattern ocupa toda a altura
do ecrã é definido como [49, 53]:
• Objetivo: “Side Drawer ocupa toda a altura do ecrã”
• V: {}
• A: [Ler o ecrã, abrir o Side Drawer, ler o ecrã]
28 iMPAcT tool
Figura 3.2: Exemplo do padrão Side Drawer [22]
• C: {“O Side Drawer ocupa a altura toda do ecrã”}
• P: {“UI Pattern está presente && Side Drawer está disponível && Test Pattern não foi
aplicado na atividade atual”}
3.2.2 Padrão de orientação
Quando existe rotação de um dispositivo móvel, a interface da aplicação aberta nesse momento
atualiza a disposição dos seus elementos para se ajustar a esta mudança. No entanto, a adaptação
do layout apenas é possível se não existir bloqueio da orientação no manifesto da aplicação para a
respetiva atividade. Este padrão é ilustrado na Figura 3.3.
Com tudo isto, os desenvolvedores de aplicações devem ter especial atenção para dois aspetos
presentes nas diretrizes fornecidas pela Google [23]:
• Não deve ser perdido nenhum input do utilizador após a rotação do ecrã;
• Os widgets não devem desaparecer durante a rotação do ecrã.
Diversos estudos já foram feitos sobre os motivos de a orientação interferir com uma aplicação
móvel. Amalfitano et al. [5] testaram manualmente aplicações móveis usando double orientation
change (DOC) que consiste na sequência de duas mudanças consecutivas de orientação. Nos testes
realizados neste estudo, foi utilizado DOC porque aplicar apenas uma mudança de orientação
podia não ser suficiente para detetar falhas na interface do utilizador, visto que são aceitáveis
3.2 Catálogo de padrões 29
algumas diferenças entre as duas orientações possíveis. Após a segunda rotação, o layout e o
conteúdo da interface devem ser iguais ao estado inicial da aplicação, antes da primeira rotação,
de forma a não existir uma falha na GUI.
Figura 3.3: Exemplo do padrão de Orientação. a) portrait e b) landscap [55]
O UI Pattern que verifica se é possível realizar a rotação do ecrã é definido como [49, 53]:
• Objetivo: “Rotação é possível”
• V: {}
• A: []
• C: {“É possível rodar o ecrã”}
• P:{“Verdadeiro”}
Este padrão possui dois Test Patterns associados [53, 49]. O primeiro é responsável por veri-
ficar se os dados presentes no ecrã não são perdidos e é definido como:
• Objetivo: “Dados não alterados após a rotação do ecrã”
• V: {}
• A: [Ler ecrã, rodar ecrã, ler ecrã, scroll do ecrã, ler ecrã]
• C: {“Dados introduzidos pelo utilizador não foram perdidos”}
30 iMPAcT tool
• P: {“UI Pattern está presente && utilizador introduziu dados && Test Pattern não foi apli-
cado na atividade atual”}
O segundo Test Pattern é responsável por verificar se não houve perda de elementos na inter-
face. Este padrão é definido como:
• Objetivo: “Principais componentes da interface do utilizador continuam presentes”
• V: {}
• A: [Ler ecrã, rodar ecrã, ler ecrã, scroll do ecrã, ler ecrã]
• C: {“Principais componentes ainda estão presentes”}
• P: {“UI Pattern está presente && Test Pattern não foi aplicado na atividade atual”}
Aquando da rotação do ecrã, alguns elementos podem ser realocados em novas posições e,
desta forma, desaparecerem da parte visível da interface. Por esta razão, a ferramenta efetua scroll
ao ecrã para garantir o acesso total à árvore de elementos da interface.
3.2.3 Padrão de dependência de recursos
Uma aplicação móvel pode usufruir de recursos externos que o telemóvel possui e, assim, estar
dependente da disponibilidade destes recursos. Exemplo destes recursos são o Wi-Fi, o NFC, o
Bluetooth e o GPS. Torna-se importante, desta forma, verificar se a aplicação não têm problemas
quando estes recursos não estão disponíveis para utilização [23].
O UI Pattern que verifica se o recurso configurado está a ser utilizado pela aplicação móvel
em teste é definido como [49, 53]:
• Objetivo: “Recurso está em uso”
• V: {“resource”, nome_do_recurso}
• A: [Ler estado do recurso]
• C: {“Recurso a ser utilizado pela aplicação”}
• P: {“Verdadeiro”}
O Test Pattern associado, responsável por verificar se a aplicação móvel não falha quando o
recurso fica indisponível, é definido como [49, 53]:
• Objetivo: “A aplicação não falha quando o recurso fica indisponível”
• V: {“resource”, nome_do_recurso}
• A: [Ler ecrã, desativar o recurso, ler ecrã]
• C: {“Aplicação não falhou”}
• P: {“UI Pattern está presente && Test Pattern não foi aplicado na atividade atual”}
3.3 Artefactos 31
3.3 Artefactos
No fim do processo de exploração são criados dois artefactos principais [53]: 1) o relatório de
exploração e 2) o modelo do comportamento observado durante a exploração da aplicação. Estes
artefactos permitem compreender melhor o comportamento da aplicação e os resultados dos testes
realizados.
3.3.1 Relatório da exploração
O relatório final da exploração é dividido em duas partes: o registo da exploração e os resulta-
dos dos testes.
Registo da exploraçãoO registo da exploração é também dividido em duas partes:
• Identificação da aplicação em teste e dos parâmetros de exploração – Nesta secção é identi-
ficado o nome do package da aplicação em teste e os três parâmetros de exploração que são:
a) a versão do sistema operativo do dispositivo onde a aplicação foi testada; b) as dimensões
do ecrã do dispositivo; e c) a coordenada no qual a aplicação começa.
• Sequência de eventos executados durante a exploração – Os eventos executados na fase de
exploração são identificados como um tuplo <Event, Element, Executions>, onde o Event
identifica o evento que foi executado, o Element identifica o elemento associado ao evento
executado e o Executions indica o número de vezes que o evento foi executado no elemento.
Resultados dos testesO relatório da exploração inclui também os seguintes resultados:
• Número de eventos executados e identificados, bem como a sua percentagem;
• Informação sobre se cada um dos UI Patterns configurados foi detetado e, em caso afirma-
tivo, se estava bem implementado ou não;
• Duração da exploração.
Este relatório pode ser útil para o utilizador reproduzir manualmente a exploração, enquanto
reproduz também as falhas encontradas, facilitando assim a correção destas.
3.3.2 Modelo do comportamento observado
Para obter o modelo da interface do utilizador da aplicação, é realizado um processo de enge-
nharia reversa. Este modelo está representado como uma máquina de estados finita que contém
informação sobre o comportamento e sobre as transições dentro da aplicação.
Existem três tipos de estados representados neste modelo [53]:
32 iMPAcT tool
• Uma atividade da aplicação em teste, identificada como Screen<i>, onde o i é o id da
atividade. Esta identificação corresponde à ordem pela qual uma atividade é atingida, sendo
que o Screen<0> corresponde à atividade principal da aplicação;
• Uma falha da aplicação, identificada como crash Screen. Quando a aplicação falha, esta in-
formação é guardada e o estado correspondente é adicionado à máquina de estados. Apenas
pode existir um estado deste tipo no modelo, ou seja, se vários eventos levarem a falhas,
todos eles irão se ligar a este estado.
• Abandono da aplicação, identificado como out of AUT Screen. Quando um evento faz com
que a exploração saia da aplicação, é adicionado um estado ao modelo que represente esta
situação. Tal como no estado de falha da aplicação, apenas pode existir um estado deste tipo
no modelo.
O utilizador da ferramenta tem a opção, na janela de configuração, de substituir a representação
final dos estados pelos screenshots correspondentes, obtidos durante a fase de exploração.
O grande objetivo do modelo gerado, juntamente com o registo da exploração, é de ajudar
o utilizador a perceber que falhas existiram e onde ocorreram. Além disto, este modelo ajuda
também a compreender melhor a aplicação móvel [53].
3.4 Contribuições da ferramenta para a comunidade
A iMPAcT tool fornece várias vantagens para a área de investigação relacionada com o teste
de aplicações móveis e, em particular, para a comunidade de desenvolvedores e testers dessas
aplicações. De acordo com Morgado et al. [49], algumas dessas características são:
• Sem acesso ao código fonte – O código fonte nunca é acedido durante todo o processo e
não é necessária instrumentação do código;
• Esforço manual – Não é necessário esforço por parte do utilizador porque todo o processo
é feito de forma automática;
• Reutilização – Os UI Patterns definidos e presentes no catálogo de padrões podem ser reu-
tilizados sem ser necessário fazer qualquer modificação. Esta reutilização é possível porque
os UI Patterns são representações de comportamentos recorrentes presentes em várias apli-
cações;
• Manutenção e evolução – É possível adicionar facilmente novos padrões ao catálogo e a
estrutura de código da ferramenta facilita a adição de novos eventos de interação;
• Usabilidade – Para utilizar a ferramenta, o utilizador não precisa de ter qualquer conheci-
mento sobre a aplicação que quer testar nem sobre os padrões existentes;
• Inovação – Até ao momento, não existe conhecimento de uma ferramenta de teste de apli-
cações móveis que combine engenharia reversa com UI Patterns.
3.5 Conclusões 33
3.5 Conclusões
A iMPAcT tool é uma ferramenta que permite testar comportamento recorrente presente nas
aplicações móveis Android. Na abordagem implementada, existe um processo de engenharia re-
versa dinâmico para explorar automaticamente a aplicação em teste de forma a identificar UI
Patterns presentes no catálogo da ferramenta. Na presença de UI Patterns, as estratégias de teste
correspondentes são aplicadas. No final de todo o processo, são produzidos relatórios que forne-
cem os resultados dos testes ao utilizador. A ferramenta pode, desta forma, ajudar os desenvolve-
dores a garantir que as suas aplicações móveis Android seguem todas as diretrizes fornecidas pela
Google [23], criando assim aplicações mais robustas.
34 iMPAcT tool
Capítulo 4
Exploração dinâmica
Este capítulo tem como objetivo apresentar os detalhes de implementação da abordagem de
exploração dinâmica desenvolvida durante esta dissertação e está estruturado da seguinte forma.
A Secção 4.1 apresenta e descreve o pseudocódigo do algoritmo implementado. A Secção 4.2
apresenta as condições nas quais a exploração da aplicação termina. Na Secção 4.3 são descritos
os dois modos de exploração existentes. A Secção 4.4 apresenta os tipos de eventos suportados e
explica como é feita a deteção do tipo de input associado a um elemento EditText. Na Secção 4.5
é descrita a heurística usada na comparação de ecrãs. A Secção 4.6 explica o que são permissões
do sistema, como são detetados os ecrãs de pedido de permissões e a ação tomada caso surja um
destes ecrãs. A Secção 4.7 descreve como um ecrã de crash é detetado, assim como as ações que
podem ser executadas na presença deste tipo de ecrã. Na Secção 4.8 são apresentados os tipos
de dados que podem existir no ficheiro de configuração. A Secção 4.9 apresenta os passos que
são necessários realizar para iniciar o processo de reprodução de um script e descreve o algo-
ritmo implementado para esta reprodução. Finalmente, na Secção 4.10 são apresentadas algumas
conclusões sobre o trabalho desenvolvido.
4.1 Algoritmo de exploração
Explorar automaticamente uma aplicação móvel é um processo que simula eventos do utiliza-
dor, sem a sua intervenção, na interface da aplicação. Este processo pode ajudar a descobrir falhas
que seriam muito custosas de descobrir se uma exploração manual fosse realizada. O Algoritmo
1 contém o pseudocódigo que ilustra a nova abordagem de exploração implementada durante esta
dissertação. A variável que controla todo o processo iterativo do algoritmo é a finishExploration
que possui, inicialmente, o valor false para que a exploração inicie. Assim que uma das condições
de paragem mencionadas na Secção 4.2 se verifica, o valor desta variável passa a true fazendo
com que a exploração da aplicação termine.
35
36 Exploração dinâmica
O processo iterativo começa por ler o ecrã atual e por verificar se este já foi detetado anteri-
ormente, isto é, se pertence à lista de ecrãs já identificados. Se o ecrã já existir nesta lista, a sua
estrutura é atualizada com base na estrutura do ecrã lido. Caso contrário, o ecrã é adicionado à
lista de ecrãs mantida que representa o conjunto de estados da máquina de estados finita [54].
Na situação do ecrã já existir na lista, pode ser necessário adicionar novos elementos, que
tenham surgido devido ao comportamento dinâmico, à estrutura desse ecrã. Esta situação pode
fazer com que a exploração fique presa num ecrã se novos elementos surgirem sempre que se
executa um evento (Figura 1.1). Assim, para evitar que a exploração fique presa, foi definido um
número máximo de vezes que a estrutura de um ecrã pode receber novos elementos (chamado
de limite superior). Por outras palavras, os eventos associados a elementos que surgiram após o
limite superior não são considerados para execução nesse ecrã. O valor do limite superior pode ser
fornecido pelo utilizador no ficheiro de configuração (Secção 4.8), sendo que o seu valor padrão é
“5”.
De seguida, todos os eventos ainda válidos no ecrã atual são obtidos (na função getPossible-
Events()). Um evento é considerado válido pelo algoritmo se uma das seguintes condições se
verificar:
• Ainda não foi executado;
• Já foi executado, mas a sua execução deu origem a novos eventos que ainda não foram to-
talmente exercitados. Para esta situação, houve uma necessidade de introduzir um número
máximo de vezes que o evento pode ser executado pois um evento que tenha surgido anteri-
ormente pode não mais aparecer. Assim, com este número é possível garantir que o evento
não é considerado válido para sempre.
O segundo caso é necessário porque, devido ao comportamento dinâmico de várias aplicações,
novos elementos podem surgir no ecrã como resultado da execução de um evento (ilustrado na
Figura 4.1). Se estes elementos desaparecerem durante a exploração e o primeiro evento não
for executado novamente, não será possível exercitar os eventos associados aos novos elementos
porque estes não estão visíveis no ecrã.
Figura 4.1: Aparecimento de novos elementos no ecrã após o clique no botão de pesquisa
Sempre que surgem novos elementos num ecrã como resultado da execução de um evento,
este evento e o seu ecrã são guardados neles. Esta situação ocorre para ser possível relacionar os
eventos associados a estes novos elementos com o evento executado que lhes deu origem. Assim,
para verificar se um evento ainda é válido (tendo em conta a segunda condição e sem considerar
o número de vezes que o evento foi executado) basta analisar se os eventos associados aos novos
elementos estão ou não todos executados.
4.1 Algoritmo de exploração 37
Caso ainda existam eventos válidos para execução no ecrã atual, estes são adicionados à lista
de eventos identificados mantida no ecrã (se ainda não existirem) e é escolhido um deles de forma
aleatória para ser exercitado. Se este evento for exercitado com sucesso, ele é adicionado à lista de
eventos executados presente no seu ecrã e o ecrã que surgiu após a sua execução é atribuído como
ecrã de destino deste evento (linha 7 do Algoritmo 1). Por outro lado, caso não existam eventos
válidos, o ecrã atual é marcado como explorado e o foco da exploração é alterado para o próximo
ecrã presente na lista ainda não marcado como explorado. Nesta fase, o algoritmo de Dijkstra é
executado com base na máquina de estados finita construída ao longo do processo de exploração
de forma a calcular a sequência de eventos mais curta entre o ecrã atual e o próximo ecrã a ser
explorado. Na execução deste algoritmo, todos os eventos possuem o mesmo peso e apenas são
considerados os eventos válidos, isto é, eventos que ainda estão presentes nos ecrãs.
Algoritmo 1 Algoritmo de exploração
1: f inishExploration← false2: while ! f inishExploration do3: dealWithOutOfApp()4: currentScreen← readScreen()5: currentScreenOnList← updateScreen(currentScreen)6: if executedEvent then7: executedEvent.setNextScreen(currentScreenOnList)8: end if9: events← currentScreen.getPossivelEvents()
10: if events then11: executedEvent← chooseAndFireEvent(events)12: else13: currentScreenOnList.setExplored(true)14: destinationScreen← getNextScreenNotExplored(screens)15: eventsPath← getShortestPath(currentScreenOnList,destinationScreen,screens)16: if eventsPath then17: executedEvent← executePath(eventsPath)18: else19: executedEvent← new Event(BACK)20: executeEvent(executedEvent)21: if isOutOfTheApplication() then22: startApplication()23: destinationScreen.setExplored(true)24: end if25: end if26: end if27: if allScreensExplored(screens) or timeExpired() or homePressed() then28: f inishExploration← true29: end if30: end while
Se não existir um caminho entre os dois ecrãs, o evento back é executado numa tentativa de
voltar ao ecrã anterior. Após a execução deste evento, se a aplicação fechar, ela é reiniciada e o
38 Exploração dinâmica
ecrã de destino marcado como explorado pois não existe nenhum caminho que nos leve novamente
a atingir este ecrã. Caso contrário, se existir um caminho entre os ecrãs, a sequência de eventos é
executada (função executePath() no Algoritmo 2).
Em cada iteração do algoritmo de exploração, são analisados os ecrãs de destino dos eventos
exercitados ainda válidos presentes no ecrã atual. Os ecrãs de destino destes eventos que estive-
rem marcados como explorados, mas ainda tiverem eventos por exercitar são marcados como não
explorados pois surgiu um novo caminho que nos permite atingir estes ecrãs. Da mesma forma,
quando é executado um evento que nos leva a um ecrã que está marcado como explorado, mas que
ainda tem eventos por exercitar, este é marcado como não explorado. Estas situações são possíveis
porque, em cada iteração, é guardada informação no ecrã atual sobre se os seus eventos estão ou
não todos exercitados para distinguir um ecrã que foi assinalado como explorado por todos os seus
eventos estarem exercitados de um ecrã assinalado como explorado por não haver um caminho
que o atinja.
Algoritmo 2 Executar um caminho de eventos1: procedure EXECUTEPATH(eventPath)2: for i← 0 to eventPath.size() - 1 do3: event← eventPath.get(i)4: screen← readScreen()5: events← screen.getAllEvents()6: if !events.contains(event) then7: event.setAvailable(false)8: return null9: end if
10: executeEvent(event)11: expectedScreen← event.getNextScreen()12: screen← readScreen()13: if expectedScreen.isDifferent(screen) then14: return event15: end if16: end for17: return null18: end procedure
Devido à natureza dinâmica das aplicações móveis, um evento que foi executado anteriormente
num ecrã pode deixar de existir ou a sua execução pode levar a um ecrã que é diferente do atingido
na execução anterior. Por estes motivos, a função executePath() verifica se o evento existe no ecrã
atual da aplicação e se o ecrã atingido é ou não o esperado. Se o evento não existir, ele é marcado
como inválido para prevenir que seja usado novamente na próxima execução do Dijkstra. Se o
ecrã atingido pela execução de um evento for diferente do esperado, o ecrã de destino do evento é
atualizado para o novo ecrã.
Durante a exploração, podem ocorrer situações de saída da aplicação, sendo estes casos trata-
dos pela função dealWithOutOfApp(). Existem três tipos de saída da aplicação considerados:
4.2 Condições de paragem 39
• Crashes da aplicação – O diálogo associado ao crash é fechado e a aplicação reiniciada.
Esta situação encontra-se detalhada na Secção 4.7;
• Pedidos de permissão ao utilizador – O botão “Allow” do diálogo de permissões é pressio-
nado. A Secção 4.6 explica detalhadamente este cenário;
• Outros tipos de saída, como o click num link que abre outra aplicação – O evento back é
executado numa tentativa de voltar à aplicação em teste.
No caso de se verificar um crash na aplicação, o algoritmo cria um ecrã que representa esse
estado e adiciona-o à lista de ecrãs. Da mesma forma, caso se verifique um pedido de permissão
ou outro tipo de saída, um ecrã que representa esta situação é criado e adicionado à lista. No
entanto, estes ecrãs não são considerados pelo algoritmo de Dijkstra para que não exista nenhum
caminho de eventos cuja execução passe por eles.
4.2 Condições de paragem
A exploração da aplicação pode terminar:
• Automaticamente, quando todos os ecrãs identificados estiverem marcados como explora-
dos ou se o tempo máximo de exploração, que pode ser configurado, for atingido;
• Manualmente, caso o utilizador pressione o botão “home” do dispositivo.
4.3 Modos de exploração
A escolha do evento a executar a partir do conjunto de eventos válidos é feita de forma aleató-
ria. No entanto, existem dois modos de exploração possíveis para o algoritmo implementado, cuja
principal diferença assenta na prioridade de eventos. Os dois modos são os seguintes:
• Modo sem prioridade (Crawling) – Todos os eventos considerados válidos num ecrã podem
ser executados;
• Modo com prioridade (Crawling with priority) – A prioridade de eventos é a seguinte: even-
tos de ciclo de vida > eventos associados a novos elementos que surgiram no ecrã (Figura
4.1) > eventos de elementos do tipo EditText ou CheckBox > todos os outros eventos. Os
eventos de elementos do tipo EditText e CheckBox possuem maior prioridade que os restan-
tes para que, no processo de exploração, se um ecrã de login surgir, os seus campos sejam
preenchidos e apenas depois o botão para avançar clicado.
O modo de exploração pode ser definido pelo utilizador no ficheiro de configuração. A Secção
4.8 explica com mais pormenor que informação pode conter este ficheiro.
40 Exploração dinâmica
4.4 Tipos de eventos suportados
A execução de vários tipos de eventos possibilita que a exploração atinja mais estados da
aplicação e, consequentemente, obtenha uma maior cobertura da aplicação em teste. Os eventos
podem ser divididos em dois tipos: 1) eventos de interface; 2) eventos de sistema. Os eventos de
interface exercitados pelo algoritmo são os seguintes: click, long click, check, edit, scroll, swipe,
pinch e drag. Relativamente aos de sistema, existem os seguintes eventos: back e home_and_back.
Este último é um evento específico para cobrir os métodos do ciclo de vida do Android que consiste
em carregar no botão “home” para minimizar a aplicação e de seguida carregar no botão “recent
apps” para abrir o menu de aplicações abertas em segundo plano, fazer um swipe vertical para que
a aplicação em teste surja no centro do ecrã e, por fim, efetuar um clique no centro do ecrã para
voltar a abrir a aplicação.
Embora a exploração execute o evento scroll, ele apenas é executado uma vez por elemento
em cada ecrã de forma a evitar que a execução fique presa num ecrã com scroll infinito.
Um elemento EditText possui sempre um tipo de input associado dentro de vários possíveis.
No entanto, o elemento não possui informação direta sobre este tipo de input pois a classe Accessi-
bilityNodeInfo, que representa um nó no ecrã, apenas contém um inteiro que resulta da combinação
de várias flags. De forma a analisar o tipo input associado a um elemento, o algoritmo analisa as
várias flags incluídas no inteiro fornecido pela classe AccessibilityNodeInfo. No entanto, existem
flags que nada acrescentam e que fazem com que o número de tipos de input aumente exponen-
cialmente (devido à sua combinação com outras flags). Por esta razão, as flags auto_complete,
auto_correct e no_suggestions são removidas e, posteriormente, é verificado num switch o tipo de
input a que corresponde o inteiro sem estas flags. A função responsável por detetar o tipo de input
associado a um elemento e por criar o evento edit encontra-se na Secção A.1.
De momento, são distinguidos os seguintes tipos de input: password, password de números,
email, assunto de email, número de telemóvel, endereço, tempo, data, tempo e data, número,
número com sinal, número com casas decimais, nome de pessoa, mensagem longa, mensagem
curta, texto, texto em maiúsculas, texto com letra maiúscula na primeira letra de cada palavra,
texto com letra maiúscula na primeira letra de cada frase, URI, pronúncia fonética, filtragem de
texto e texto multilinha.
4.5 Critério de comparação de ecrãs
A identificação de diferentes ecrãs é um desafio porque não é possível saber dinamicamente
quando a aplicação atinge um novo ecrã. Assim, uma das formas de classificar dois ecrãs como
diferentes é através de heurísticas pré-definidas. Existem dois tipos de heurísticas tendo em conta
a sua complexidade:
• Heurística básica – consiste em comparar os elementos existentes nos dois ecrãs. Se um
elemento de um ecrã não existir no outro, então estamos na presença de diferentes ecrãs.
4.5 Critério de comparação de ecrãs 41
• Heurística complexa – consiste em analisar características chave da estrutura interna dos
ecrãs. Desta forma, dois ecrãs podem não ser considerados diferentes se existirem pequenas
diferenças entre os elementos que constituem os ecrãs.
A heurística implementada e usada pelo algoritmo de exploração para distinguir ecrãs é uma
heurística complexa. Esta baseia-se em cinco aspetos:
1. O primeiro aspeto consiste em verificar se o navigation drawer existe nos dois ecrãs. Se um
dos ecrãs possuir este componente e o outro não, então os dois ecrãs são considerados dife-
rentes. A heurística usada para detetar o navigation drawer encontrava-se já implementada
na iMPAcT tool [53];
2. Em segundo lugar, são analisadas as dimensões dos ecrãs para verificar se algum ecrã é
pop-up. Caso apenas um ecrã seja pop-up, então os dois ecrãs são considerados diferentes.
Tal como no aspeto anterior, a heurística que define um ecrã como pop-up já se encontrava
implementada na ferramenta [53];
3. Em terceiro lugar, é analisada a presença de tabs nos ecrãs. A heurística implementada para
detetar se este componente existe num ecrã encontra-se detalhada na Subsecção 4.5.1. Nesta
fase, os dois ecrãs são considerados diferentes se:
• O número de tabs identificados nos dois ecrãs é diferente;
• Os dois ecrãs possuem o mesmo número de tabs mas os elementos que constituem
estes tabs são diferentes;
• Os dois ecrãs possuem os mesmos tabs mas o tab selecionado é diferente.
4. O quarto aspeto consiste em analisar a action bar. Esta análise apenas é feita se não existir
navigation drawer em nenhum dos ecrãs. Caso apenas um dos ecrãs tenha action bar, então
os dois ecrãs são considerados diferentes;
5. Em quinto lugar, é feita uma comparação dos widgets dos dois ecrãs que não pertençam à
action bar. A Subsecção 4.5.2 explica detalhadamente quando um elemento é considerado
widget. Se os dois ecrãs tiverem navigation drawer, apenas os widgets que lhe pertencem
são comparados. Neste situação, ao contrário dos aspetos anteriores, os dois ecrãs são
considerados iguais se:
• Existir pelo menos um widget igual nos dois ecrãs, não tendo em conta as suas propri-
edades modificáveis (text, checked, selected, focused, clickable e scrolled);
• Todos os widgets forem iguais entre os dois ecrãs, não tendo em conta as suas propri-
edades modificáveis nem a sua posição.
Existem algumas aplicações que possuem tabs sem que nenhum dos seus elementos tenha a
propriedade selected a true. Por esta razão, dois ecrãs que possuam os mesmos tabs mas com
diferente tab visivelmente selecionado seriam considerados iguais pelo quinto ponto da heurística,
42 Exploração dinâmica
visto que existe pelo menos um widget igual nos dois ecrãs que é o próprio tab. Para resolver
este problema, a solução encontrada passou por remover todos os widgets pertencentes aos tabs
da comparação final para que esta comparação de widgets se centre apenas no ecrã principal.
Esta nova heurística é semelhante à que já se encontrava implementada na iMPAcT tool, com
exceção do terceiro ponto relativo aos tabs. Com a introdução deste ponto, existe uma tentativa
de distinguir ecrãs diferentes, ao contrário da heurística já existente que tenta distinguir atividades
diferentes. Uma comparação de ecrãs baseada em atividades não é o melhor tipo de comparação
pois pode levar à perda de informação importante para que todos os estados da aplicação sejam
corretamente explorados.
A Figura 4.2 ilustra dois ecrãs com diferentes tabs selecionados e que, segundo numa compa-
ração baseada em atividades, seriam considerados como o mesmo ecrã. Por outro lado, segundo
a heurística de comparação usada no algoritmo de exploração implementado, estes dois ecrãs são
considerados diferentes permitindo uma exploração mais eficaz da aplicação.
Figura 4.2: Dois ecrãs com diferente tab selecionado
Existem estudos que mostram a importância da correta distinção entre os diferentes ecrãs de
uma aplicação de modo a aumentar a eficácia da técnica de teste baseado em modelos [77].
4.5.1 Identificação do elemento tabs
Na comparação de ecrãs, um dos pontos de distinção tem por base a presença ou não de tabs
nestes. No entanto, a identificação do elemento root dos tabs foi um aspeto desafiante porque
nada fornece esta informação de forma explicita. Assim, esta identificação foi obtida através da
4.6 Permissões do sistema 43
definição de uma heurística que identifica um elemento como root dos tabs se seguir um dos
seguintes aspetos:
• A sua classe é do tipo “HorizontalScrollView” ou “TabWidget”;
• A sua classe é do tipo “LinearLayout” ou “FrameLayout” e possui as seguintes característi-
cas:
– Tem pelo menos um descendente direto;
– Não ocupa a totalidade do ecrã;
– Começa no lado esquerdo do ecrã e termina no seu lado direito;
– O limite inferior corresponde à altura do dispositivo;
– Ocupa no máximo 15% da altura do dispositivo;
– Em nenhum dos seus elementos ascendentes é possível fazer scroll.
4.5.2 Diferença entre elemento e widget
Na comparação de ecrãs existe o conceito de widget sendo que, por esta razão, se torna im-
portante definir a diferença entre um elemento e um widget. A definição de widget usada nesta
dissertação tem por base a definição que já se encontrava implementada na iMPAcT tool [53]. As-
sim, um elemento é um componente básico pertencente à estrutura do ecrã no qual pode ou não ser
possível interagir (click, long click, etc). Por outro lado, um widget é um elemento visível, como
um botão, texto ou imagem, ou um elemento de estrutura, como um Layout no qual é possível
interagir.
4.6 Permissões do sistema
De acordo com a documentação do Android [24], as permissões do sistema podem ser dividi-
das em dois tipos:
• Permissões normais – são permissões concedidas automaticamente pelo sistema que não
colocam em risco a privacidade do utilizador da aplicação nem o normal funcionamento
do dispositivo. A conexão à internet, a utilização do bluetooth e a criação de atalhos no
launcher do dispositivo são exemplos deste tipo de permissões.
• Permissões perigosas – devem ser concedidas explicitamente pelo utilizador. Ao contrá-
rio das anteriores, este tipo de permissão pode potencialmente por em risco a privacidade
do utilizador e o funcionamento do dispositivo. A leitura e escrita para o armazenamento
externo, o acesso à câmara e a gravação de áudio são exemplos de permissões perigosas.
Se o dispositivo estiver a executar o Android 5.1.1 ou inferior, ou a targetSdkVersion (nível
máximo da API para o qual a aplicação será distribuída) da aplicação for 22 ou inferior, as per-
missões perigosas necessárias são pedidas em tempo de instalação. Caso as permissões não sejam
44 Exploração dinâmica
aceites, a aplicação não é instalada. Se o dispositivo estiver a executar a versão 6.0 ou superior do
Android e a targetSdkVersion da aplicação for 23 ou superior, a aplicação deve pedir ao utilizador
para lhe conceder as permissões perigosas em tempo de execução.
Por esta razão, durante o processo de exploração da aplicação podem surgir diálogos de sis-
tema para que o utilizador conceda permissão ao uso de determinado recurso. Se a permissão não
for concedida, a exploração pode falhar ao explorar certas partes da aplicação para o qual não
tem acesso. Existe a necessidade, portanto, que durante a exploração sejam aceites as permissões
pedidas.
A identificação de um ecrã de pedido de permissão é feita verificando se o package name lido
pela framework UI Automator é "com.android.packageinstaller". Este package name foi confir-
mado através da execução de um conjunto de aplicações Android que necessitavam de permissões
perigosas. A Figura 4.3 ilustra um ecrã com um pedido de permissão ao utilizador.
Figura 4.3: Pedido de permissão para gravar áudio
No caso de estarmos na presença de um ecrã de pedido de permissão, o botão “Allow”, presente
no diálogo, é clicado e a exploração da aplicação prossegue.
4.7 Deteção de crashes
Tal como nos outros modos de exploração já existentes na iMPAcT tool, a deteção de crashes é
feita verificando se o ecrã atual é um pop-up e se o seu package name é “android”. Nesses modos
já existentes, sempre que surgia um crash na aplicação, o botão “Ok” era clicado. No entanto, com
4.8 Ficheiro de configuração 45
base em testes feitos a dispositivos executando diferentes versões do Android, é possível verificar
que existem vários tipos de ecrãs que representam crashes. A Figura 4.4 ilustra esta situação.
Quando um crash é detetado, existem três ações que podem realizadas dependendo do tipo de
ecrã:
• Se existir um botão com o texto “Ok”, este é clicado e a aplicação reiniciada;
• Se o botão anterior não existir, é verificado se o botão “Close app” existe e, em caso afirma-
tivo, este é clicado. Após o clique, a aplicação é reiniciada;
• Se nenhum dos botões anteriores existir, é feito o clique no botão “Open app again”.
(a) Crash no Android 6.0 (b) Crash no Android 7.0
Figura 4.4: Exemplo de diferentes ecrãs de crash
4.8 Ficheiro de configuração
De forma a auxiliar o processo de exploração, o utilizador pode definir alguns dados num
ficheiro de configuração. Estes dados são divididos em dois tipos:
• Dados da exploração – informação para o algoritmo de exploração que inclui: a) tempo
máximo de exploração, de forma a limitar o tempo total da execução; b) número máximo de
adições a um ecrã (limite superior), para evitar que a exploração fique presa num ecrã com
um número infinito de eventos; c) prioridade, que indica se a exploração deve ser feita com
ou sem prioridade de eventos.
46 Exploração dinâmica
• Dados de input – contém os vários tipos de input detetáveis pelo algoritmo (p. ex. pas-
sword) associados a elementos EditText e o valor que o utilizador pretende que seja inserido
associado a cada tipo.
Caso o utilizador não forneça o ficheiro de configuração ou se alguma informação estiver em
falta neste ficheiro, a ferramenta irá usar os valores padrão pré-estabelecidos.
4.9 Script de execução
Durante a execução do processo de exploração, podem ser identificados problemas na apli-
cação móvel em teste, tais como crashes ou outro tipo de comportamento não esperado. Após
a correção destes erros, os passos da exploração realizada anteriormente devem ser feitos nova-
mente de forma a verificar se estes problemas ainda existem. Por esta razão, há uma necessidade
de existir um script para cada exploração realizada que contenha os eventos executados ordenados
cronologicamente e que irão guiar o processo de reprodução da exploração.
4.9.1 Modo de utilização
Para que o script seja criado, a checkbox “Record Exploration Script”, presente na interface
da iMPAcT tool, deve ser selecionada. No fim da exploração, o ficheiro é criado na pasta da ferra-
menta e inclui no seu nome o timestamp verificado no momento, de forma a distinguir diferentes
explorações.
Por outro lado, para iniciar o processo de reprodução de um script já existente, o utilizador
necessita de realizar os seguintes passos: 1) clicar na dropbox de escolha do tipo de exploração;
2) escolher o modo “REPEAT_SCRIPT”; 3) procurar o caminho para o script, clicando no botão
“Search” que surgiu ao escolher o modo; 4) introduzir o package name da aplicação e selecionar
o dispositivo onde se pretende fazer a reprodução; 5) iniciar o processo, clicando no botão “Run”.
A Figura 4.5 ilustra um sumário desta sequência de passos.
Figura 4.5: Passos para iniciar a reprodução do script
4.9 Script de execução 47
O ficheiro criado no final de uma exploração, necessário para que a sua reprodução seja possí-
vel, é do tipo json e contém três tipos de informação:
• package_name: Identifica a aplicação explorada. Esta informação é necessária para garantir
que a reprodução da exploração está a ser feita na mesma aplicação;
• resolution: Resolução do dispositivo. Esta informação é indispensável porque a posição
de um elemento no ecrã é usada na sua identificação. Assim, não é possível realizar a
reprodução de um script num dispositivo com resolução diferente do utilizado inicialmente
na exploração;
• execution_trace: Contém uma lista com informação sobre os eventos executados na explo-
ração, ordenada cronologicamente. A informação presente em cada elemento desta lista
ajuda a que o evento seja recriado, em tempo de execução, durante a reprodução. O action
é uma informação obrigatória e designa a ação do evento (p. ex. click, long click, edit, entre
outros). Todos os outros dados dependem do tipo de ação do evento. O element contém
uma string que identifica o elemento na interface da aplicação (se for um evento de UI). O
input_type identifica o tipo de input do elemento (se este for EditText). O values contém o
valor introduzido no elemento (se a ação for edit).
De seguida, é possível visualizar a parte inicial de um script de execução criado durante uma
exploração à aplicação “aMetro” num dispositivo com a resolução de 1794x1080.
1 {
2 "package_name": "org.ametro",
3 "resolution": "1794x1080",
4 "execution_trace": [
5 {
6 "action": "click",
7 "element": "class:android.widget.EditText;id:org.ametro:id\/
search_src_text;content:;bounds:Rect(168, 87 − 966, 182)",
8 "input_type": "Text"
9 },
10 {
11 "action": "edit",
12 "element": "class:android.widget.EditText;id:org.ametro:id\/
search_src_text;content:;bounds:Rect(168, 87 − 966, 182)",
13 "input_type": "Text",
14 "values": "teste"
15 },
16 ...
17 }
48 Exploração dinâmica
4.9.2 Algoritmo de reprodução
O primeiro passo do algoritmo consiste em fazer a leitura do script, isto é, do ficheiro que
contém a sequência de eventos executada numa exploração anterior. Após a leitura, o algoritmo
entre numa fase iterativa que apenas termina quando pelo menos uma das condições de paragem
se verifica. O processo iterativo da reprodução inicia por ler o ecrã atual da aplicação e, numa fase
seguinte, verifica se o evento a reproduzir é um evento do sistema ou um evento associado a um
elemento da interface. Se o evento for de sistema, este é criado para ser executado. Caso contrário,
se o evento for de UI, é feita uma análise aos elementos existentes na estrutura do ecrã atual para
verificar se o elemento associado ao evento a reproduzir existe no ecrã e, em caso afirmativo, o
evento é criado.
Após a conclusão das etapas anteriores, se o evento tiver sido criado este é executado e a va-
riável eventNumber, que controla o número de eventos executados, incrementada. Caso contrário,
a variável waitedTimes, que controla o número de iterações de espera por um elemento, é incre-
mentada e é esperado um certo tempo para que o ecrã acabe de carregar os possíveis elementos
que ainda não surgiram.
A reprodução do script apenas pode ser terminada automaticamente, sendo que a variável que
controla este processo é a finishExploration. Assim, a execução da reprodução pode terminar
quando:
• A variável eventNumber possui o mesmo valor que o tamanho da lista de eventos do script,
indicando que todos os eventos foram executados com sucesso;
• A variável waitedTimes atinge o número limite de tentativas de espera por um elemento que
ainda não existe no ecrã. Esta condição foi criada para prevenir que a execução fique presa
se o elemento associado ao evento a reproduzir não existir na interface da aplicação. Em
cada iteração, se o elemento não existir, é esperado um tempo fixo para que o ecrã acabe
de carregar e, posteriormente, a reprodução avança para uma nova iteração (sem incremen-
tar a variável eventNumber). Caso o elemento não surja nas duas próximas iterações, a
reprodução termina.
O Algoritmo 3 apresenta o pseudocódigo implementado para a reprodução de um script de
execução.
4.10 Conclusões
Neste capítulo foi apresentada uma nova abordagem de exploração desenvolvida como uma
extensão da iMPAcT tool. Durante o processo de exploração, quando é detetado que todos os
eventos do ecrã atual estão exercitados, o algoritmo de Dijkstra é executado de forma a encontrar
o caminho de eventos mais curto entre ecrã atual e o próximo ecrã a ser explorado (primeiro ecrã
presente na lista ainda não marcado como explorado).
Como mencionado no Capítulo 1, existem vários desafios que podem fazer com que uma
exploração dinâmica falhe a explorar totalmente uma aplicação. Entre estes desafios salientam-se:
4.10 Conclusões 49
Algoritmo 3 Reprodução do script de execução1: traceEvents← readExecutionTraceFile()2: eventNumber← 03: f inishExploration← false4: waitedTimes← 05: while ! f inishExploration do6: currentScreen← readScreen()7: eventIn f ormation← traceEvents.get(eventNumber)8: if isSystemEvent(eventIn f ormation) then9: event← createSystemEvent(eventIn f ormation)
10: else11: elements← currentScreen.getElements() . Obter todos os elementos do ecrã atual12: for i← 0 to elements.size() do13: element← elements.get(i)14: if eventIn f ormation.get(“element”) = element then . Se o elemento existe15: event← createElementEvent(element, eventIn f ormation)16: break17: end if18: end for19: end if20: if event then21: if executeEvent(event) then . Se o evento foi corretamente executado22: eventNumber← eventNumber+123: waitedTimes← 024: end if25: else26: waitedTimes← waitedTimes+127: waitForStableScreen() . Esperar um tempo fixo para que o ecrã termine de carregar28: end if29: if eventNumber = traceEvents.size() or waitedTimes = 3 then30: f inishExploration← true31: end if32: end while
• Pontos de bloqueio;
• Introdução de novos gestos de interação;
• Identificação de ecrãs diferentes;
• Comportamento dinâmico das aplicações móveis.
Relativamente ao primeiro desafio, o algoritmo implementado consegue detetar o tipo de input
dos elementos EditText. Além disto, o utilizador pode indicar num ficheiro de configuração o
valor que pretende que seja inserido associado a cada tipo de input. Desta forma, caso sejam
detetados elementos EditText do tipo email, password, text, entre outros, o valor associado presente
no ficheiro de configuração é usado.
50 Exploração dinâmica
Para o segundo desafio, foram implementados novos gestos de interação ainda não existentes
na ferramenta, tais como o swipe, pinch e drag. Além do mais, o algoritmo é totalmente extensível
permitindo a inclusão de novos eventos que possam surgir no futuro.
Em relação ao terceiro desafio, foi implementada uma nova heurística de comparação de ecrãs
que visa tentar distinguir ecrãs diferentes, ao contrário da heurística que já existia na iMPAcT tool
que tenta distinguir atividades diferentes.
Para o último desafio, de forma a evitar que a exploração fique presa num ecrã se novos
elementos surgirem sempre que se executa um evento, foi definido um número máximo de vezes
no qual podem ser adicionados novos elementos à estrutura de um ecrã. Além disto, para tentar
executar o maior número de eventos possível, um evento já executado pode voltar a ser considerado
para execução se os eventos a que deu origem no mesmo ecrã ainda não estão todos exercitados.
De forma a validar o algoritmo de exploração implementado, foram realizadas várias experiên-
cias com aplicações disponíveis na loja oficial da Google. Estas experiências e os seus resultados
podem ser encontrados no próximo capítulo.
Capítulo 5
Experiências
Este capítulo tem como principal objetivo apresentar os resultados das experiências realizadas
para validar o algoritmo de exploração implementado como uma extensão da iMPAcT tool. Nestas
experiências, os dois modos de exploração associados ao novo algoritmo são considerados dois
algoritmos distintos e a análise de cobertura de código é feita ao nível da instrução.
Este capítulo está estruturado da seguinte forma. A Secção 5.1 apresenta as especificações
técnicas do emulador e dos computadores usados nas experiências. A Secção 5.2 apresenta e
descreve a metodologia de teste definida. Os resultados das experiências realizadas encontram-se
nas Secções 5.3 e 5.4. A Secção 5.5 contém as respostas às questões de investigação. Finalmente,
as conclusões deste capítulo são apresentadas na Secção 5.6.
5.1 Especificações técnicas
Todas as experiências apresentadas neste capítulo para validar a abordagem implementada
foram realizadas em dois computadores executando um emulador Android com as mesmas es-
pecificações. Foram utilizados dois computadores de maneira a diminuir para metade o tempo
total das experiências realizadas. As principais especificações técnicas dos computadores são as
seguintes:
Computador portátil Asus ROG GL552VW
• Sistema operativo: Windows 10
• RAM: 8 GB
• CPU: Intel R© CoreTM i5-6300HQ
• GPU: NVIDIA GeForce GTX 960M
• Chipset: Intel R© HM170
51
52 Experiências
Computador fixo personalizado
• Sistema operativo: Windows 10
• RAM: 8 GB
• CPU: Intel R© CoreTM i5-4690K
• GPU: NVIDIA GeForce GTX 960
• Chipset: Intel R© B85
As principais especificações do emulador que foi executado nos computadores previamente
indicados são as seguintes:
Nexus 5X
• Sistema operativo: Android 6.0
• RAM: 2 GB
• Número de núcleos do CPU: 2
• Gráficos: Hardware - GLES 2.0
5.2 Metodologia de teste
Para garantir que os resultados obtidos nas experiências são fiáveis, é importante definir uma
metodologia de teste correta. Por esta razão, a metodologia definida tem em conta a aleatoriedade
da escolha do evento a executar e a existência de outros algoritmos e ferramentas de exploração
dinâmica. Esta metodologia é constituída pelas seguintes fases:
1. Seleção das aplicações móveis Android às quais serão feitas as explorações;
2. Análise e escolha de um pequeno conjunto de ferramentas de exploração dinâmica disponí-
veis no estado da arte;
3. Instrumentação das aplicações móveis selecionadas de forma a ser possível obter resultados
de cobertura de código. Este acesso ao código fonte da aplicação é feito apenas para validar
a abordagem desenvolvida;
4. Execução da exploração em cada uma das aplicações selecionadas usando os algoritmos
implementados e as ferramentas escolhidas para comparação;
5. Recolha dos resultados de cobertura e tempo de execução das explorações;
6. Comparação dos resultados obtidos por cada uma das ferramentas;
7. Discussão e conclusão sobre os resultados obtidos.
5.2 Metodologia de teste 53
5.2.1 Seleção do conjunto de aplicações
A primeira fase da metodologia de teste consistiu em fazer uma seleção consistente, mas ao
mesmo tempo diversificada de aplicações Android. Para que isto fosse possível, as aplicações
foram selecionadas de várias categorias disponíveis na Google Play Store garantindo assim que
possuíam diferentes características. Para além disto, existiam outros requisitos que cada aplicação
tinha de cumprir de maneira a ser escolhida para as experiências:
• Ser compatível com os dispositivos especificados;
• Ser uma aplicação nativa;
• Não depender de outras aplicações para ser executada;
• Possível de ser lida pelo UI Automator;
• Estar disponível na Google Play Store e ser gratuita;
• Ter pelo menos 10.000 transferências;
• Ter pelo menos 4.0 como classificação na loja;
• Ser open source;
• Usar Gradle para simplificar a sua build;
• Ser puramente escrita em Java;
• Ter como idioma uma linguagem da Europa Ocidental.
O conjunto final de aplicações selecionadas encontra-se disponível na Tabela 5.1.
Tanto no algoritmo de exploração implementado como nos já existentes na iMPAcT tool, existe
um fator de aleatoriedade associado à escolha do evento a executar que pode influenciar os resulta-
dos das experiências. Assim, de forma a obter resultados mais fiáveis, cada aplicação foi explorada
três vezes por cada algoritmo de exploração usado, sendo que os resultados apresentados neste ca-
pítulo são a média dos resultados dessas execuções.
5.2.2 Ferramentas de exploração
Para validar a abordagem implementada, torna-se importante comparar os resultados obtidos
na sua execução com os resultados de outras ferramentas de exploração existentes no estado da
arte. Relativamente à cobertura de código, esta comparação apenas pode ser considerada válida
se for usado o mesmo método que reporta este tipo de cobertura nas execuções de todas as fer-
ramentas. As seguintes ferramentas foram analisadas para verificar se era possível executá-las:
Dynodroid, PUMA, AndroidRipper, Monkey e iMPAcT tool (algoritmo de exploração já exis-
tente).
54 Experiências
Tabela 5.1: Conjunto final de aplicações selecionadas
Aplicação Versão Categoria Número deinstruções
aMetro 2.0.1.6 Mapas e navegação 19.681Chroma Doze 3.7.1 Música e áudio 23.780Debatekeeper 1.3-dev Utilitários 15.868
Easy xkcd 7.3.2 Banda desenhada 28.483Omni Notes 6.0.0 Beta 9 Produtividade 38.325RedReader 1.9.10 Notícias e revistas 77.918RGB Tool 2.0.0-SNAPSHOT Utilitários 11.114
Sound Recorder 1.3.0 Utilitários 3.204Timber Music Player 1.6-debug Música e áudio 55.480
Unit Converter Ultimate 5.4 Utilitários 5.967
No entanto, apenas o Monkey e o algoritmo já existente na iMPAcT tool foram usados na com-
paração, visto que todas as outras ferramentas apresentaram problemas. Os links disponíveis para
download do Dynodroid já não se encontram válidos. O PUMA falhava no início do processo de
execução, informando que um ficheiro estava em falta no diretório. Por último, o AndroidRipper
formatava o emulador no final do seu processo de exploração, fazendo com que os resultados de
cobertura de código fossem apagados.
Relativamente ao algoritmo já existente na iMPAcT tool, foi escolhido o Priority to not exe-
cuted and list items porque, segundo o autor, este proporciona uma exploração mais completa
identificando mais eventos e executando uma maior percentagem de eventos [50].
5.2.3 Ferramenta de análise de cobertura de código
Existem várias ferramentas para análise de cobertura de código a testes caixa branca e a caixa
preta, como verificado na revisão literária apresentada no Capítulo 2. No entanto, muitas das fer-
ramentas de análise a testes caixa preta não se encontram disponíveis para uso. Relativamente à
análise de cobertura a testes caixa branca, o Emma foi excluído das opções pois já não é atualizado
desde 2005. Por estas razões, a escolha da ferramenta de análise de cobertura de código ficou li-
mitada a duas opções, o ACVTool e o JaCoCo. A Tabela 5.2 apresenta as principais características
destas duas tecnologias que influenciaram a escolha final.
Tabela 5.2: Características do ACVTool e do JaCoCo
Características ACVTool JaCoCoApós surgir um crash na aplicação, a cobertura de
código continua a ser acumuladaX
Acumula cobertura de várias execuções daaplicação se esta não for desinstalada
X X
Não necessita de acesso direto ao código fonte XÉ possível reinstalar a aplicação sem se perder acobertura das execuções feitas até esse momento
X
5.3 Desempenho dos algoritmos de exploração 55
Analisando as principais características destas duas tecnologias, é possível verificar que o
JaCoCo é o mais completo. Esta tecnologia foi escolhida porque, apesar de necessitar de acesso ao
código fonte da aplicação, ela permite que a cobertura de código continue a ser acumulada mesmo
após se verificar um crash. Relativamente ao ACVTool, quando surge um crash na aplicação, os
dados de cobertura da execução realizada até ao momento são perdidos.
A sequência de passos que foram necessários realizar em cada aplicação para que o JaCoCo
criasse o relatório de cobertura de código das explorações encontra-se disponível na Secção B.1.
5.3 Desempenho dos algoritmos de exploração
A experiência apresentada nesta secção tem como objetivos verificar se é possível explorar di-
namicamente aplicações Android, analisar o desempenho dos algoritmos de exploração e verificar
se a cobertura de eventos influencia a cobertura de código, isto é, ela foi feita para responder às
questões de investigação 1 (É possível explorar automaticamente o comportamento das aplicações
Android através de uma análise dinâmica?), 2 (É possível obter melhores resultados que outros
algoritmos já existentes no estado da arte) e 3 (É a cobertura de eventos diretamente proporcional
à cobertura de código?).
Esta experiência consiste em executar os quatros algoritmos de exploração no conjunto de
aplicações selecionadas durante 30 minutos. Relativamente à execução nos modos implementados
nesta dissertação, esta foi feita usando os valores padrão para os diferentes tipos de input de
elementos EditText e o valor 5 para o limite superior, isto é, para o limite de vezes que um ecrã pode
receber novos elementos. Quanto ao Monkey, este foi executado com um delay entre eventos de
um segundo e meio para que a taxa de execução de eventos se assemelhasse aos outros algoritmos
de exploração.
O Monkey não apresenta resultados sobre a cobertura de eventos porque não existe informa-
ção sobre o número de eventos que foram identificados nem sobre o número de eventos distintos
que foram efetivamente executados. Consequentemente, apenas os algoritmos Priority to not exe-
cuted and list items, Crawling e Crawling with priority surgem na Subsecção 5.3.1 que apresenta
os resultados de cobertura de eventos. Por outro lado, como em todos os algoritmos é possível
analisar a cobertura de código, todos eles surgem na Subsecção 5.3.2 que apresenta os resultados
desta cobertura.
Tal como já tinha sido mencionado anteriormente neste capítulo, cada um dos algoritmos foi
executado três vezes em cada aplicação de forma a minimizar o efeito da aleatoriedade associado
à escolha do evento a executar. Os resultados apresentados são a média dos resultados obtidos
nestas três execuções. Nas tabelas presentes ao longo desta secção, C, CWP, PNE e M são abre-
viaturas para Crawling, Crawling with priority, Priority to not executed and list items e Monkey
respectivamente.
56 Experiências
5.3.1 Cobertura de eventos
A Tabela 5.3 apresenta os resultados de cobertura de eventos obtidos após a execução dos
algoritmos de exploração nas aplicações selecionadas. Os dados presentes nestes resultados são:
• Algoritmo de exploração - o algoritmo usado na execução (Priority to not executed and
list items; Crawling; Crawling with priority);
• Tempo de execução - tempo médio de execução das várias execuções realizadas com o
algoritmo de exploração;
• Eventos identificados – número máximo de eventos identificados nas execuções do algo-
ritmo de exploração;
• % eventos – percentagem média de eventos executados sobre os eventos identificados em
cada execução;
• % eventos sobre o máximo local – percentagem média de eventos executados sobre o
número máximo de eventos identificados nas execuções do mesmo algoritmo de exploração;
• % eventos sobre o máximo global – percentagem média de eventos executados sobre o
número máximo de eventos identificados pelas execuções dos vários algoritmos de explora-
ção.
Após a análise da tabela, é possível verificar que:
1. O algoritmo Priority to not executed and list items apenas não atingiu o tempo máximo da
exploração na aplicação Chrome Doze;
2. O algoritmo Crawling with priority possui igual ou maior percentagem de eventos executa-
dos sobre o máximo local em 7 das 10 aplicações selecionadas. Relativamente ao máximo
global, este algoritmo possui igual ou maior percentagem de eventos executados em 8 das
10 aplicações;
3. Apenas na aplicação RGB Tool, o algoritmo Priority to not executed and list items pos-
sui maior percentagem de eventos executados sobre o máximo global que os outros dois
algoritmos;
4. Apesar de muito próximos, o algoritmo Crawling possui um tempo médio de execução total
inferior ao Crawling with priority;
5. Apenas nas aplicações aMetro, RGB Tool e DebateKeeper, o algoritmo Priority to not exe-
cuted and list items conseguiu identificar mais eventos que os outros dois algoritmos usados
nesta comparação.
5.3 Desempenho dos algoritmos de exploração 57
Tabela 5.3: Resultados de cobertura de eventos
Algoritmo deexploração
Tempo deexecução
Eventosidentificados
%eventos
% eventos sobreo máximo local
% eventos sobreo máximo global
aMetroPNE 30m 13s 422ms 275 41.8 27.2 27.2
C 8m 36s 742ms 133 63.6 55.1 26.7
CWP 12m 46s 968ms 126 82.4 79.4 36.4Chroma Doze
PNE 1m 33s 858ms 36 83.8 81.5 37.1
C 7m 6s 538ms 79 97.7 91.1 91.1
CWP 7m 5s 646ms 79 94.8 91.6 91.6Debatekeeper
PNE 30m 6s 852ms 232 47.2 29.2 29.2
C 15m 2s 263ms 172 73.6 66.9 49.6
CWP 12m 50s 887ms 150 77.5 69.6 45.0Easy xkcd
PNE 30m 7s 72ms 253 68.7 66.8 56.5
C 30m 3s 351ms 299 64.3 55.5 55.5
CWP 30m 5s 581ms 292 73.1 69.4 67.8Omni Notes
PNE 30m 9s 669ms 228 70.4 64.0 39.2
C 27m 5s 830ms 356 69.5 65.4 62.6
CWP 30m 6s 712ms 372 80.4 72.7 72.7RedReader
PNE 30m 11s 680ms 412 35.8 33.7 30.0
C 30m 11s 310ms 329 48.2 44.9 31.8
CWP 30m 2s 20ms 464 53.0 38.4 38.4RGB Tool
PNE 30m 4s 212ms 654 51.6 34.0 34.0
C 30m 2s 361ms 590 35.8 27.2 24.5
CWP 30m 2s 223ms 414 51.2 39.6 25.1Sound Recorder
PNE 30m 7s 354ms 3 100.0 100.0 12.5
C 3m 4s 728ms 24 100.0 100.0 100.0
CWP 2m 59s 8ms 24 100.0 100.0 100.0Timber Music Player
PNE 30m 37s 79ms 229 78.3 72.5 53.0
C 30m 23s 542ms 313 65.8 61.3 61.3
CWP 30m 2s 280ms 286 70.6 69.3 63.4Unit Converter Ultimate
PNE 30m 1s 453ms 77 54.4 50.6 26.9
C 11m 2s 193ms 120 73.1 70.8 58.6
CWP 12m 27s 270ms 145 78.9 66.2 66.2
58 Experiências
5.3.2 Cobertura de código
Os resultados de cobertura de código obtidos nas explorações realizadas ao conjunto de apli-
cações selecionadas podem ser encontrados na Tabela 5.4.
Tabela 5.4: Resultados de cobertura de código
Nome da aplicação C CWP PNE MaMetro 67.3% 66.6% 62.4% 65.3%
Chroma Doze 76.7% 77.1% 69.4% 70.1%
Debatekeeper 52.8% 52.5% 43.3% 53.6%
Easy xkcd 49.5% 52.9% 50.2% 37.7%
Omni Notes 35.9% 33.8% 27.0% 14.9%
RedReader 48.8% 48.7% 43.3% 45.4%
RGB Tool 41.8% 42.9% 35.9% 37.4%
Sound Recorder 33.5% 33.6% 27.2% 63.7%
Timber Music Player 40.0% 45.0% 29.3% 38.4%
Unit Converter Ultimate 78.4% 78.0% 57.4% 77.3%
x 52.5% 53.1% 44.5% 50.4%
Analisando os resultados da tabela, é possível verificar que:
1. O Monkey apenas obtém maior cobertura de código que os restantes algoritmos nas aplica-
ções Sound Recorder e Debatekeeper;
2. Tal como o algoritmo Crawling, o Crawling with priority apresenta maior percentagem de
cobertura de código em 4 das 10 aplicações selecionadas. Combinados, estes algoritmos
apresentam maior cobertura em 8 destas 10 aplicações;
3. Os algoritmos Crawling e Crawling with priority apresentam valores de cobertura de código
semelhantes entre si para as mesmas aplicações, sendo que a maior diferença foi de 5% e
verificou-se na aplicação Timber Music Player;
4. O Priority to not executed and list items foi o algoritmo de exploração que obteve piores
resultados, não conseguindo ter maior percentagem de cobertura de código que os restantes
algoritmos em nenhuma aplicação;
5. A percentagem média de cobertura de código foi maior no algoritmo Crawling with priority,
seguindo-se o Crawling, o Monkey e, finalmente, o Priority to not executed and list items.
5.4 Impacto do aumento do tempo máximo de exploração na cobertura da aplicação 59
5.4 Impacto do aumento do tempo máximo de exploração na cober-tura da aplicação
Na experiência apresentada na Secção 5.3, os algoritmos de exploração foram executados du-
rante 30 minutos para limitar o tempo total da exploração. Um dos fatores que afeta os resultados
obtidos é este tempo máximo da exploração. Por esta razão, é importante analisar qual o efeito do
aumento deste tempo na cobertura de eventos e de código obtida.
O objetivo desta experiência é estudar como os resultados de cobertura de código e de eventos
são influenciados pelo tempo máximo de exploração definido, isto é, responder à questão de inves-
tigação 4 (Qual o efeito de aumentar o tempo máximo da exploração na cobertura da aplicação?).
Esta experiência consiste em executar os quatros algoritmos de exploração na aplicação Omni
Notes durante 50 minutos. Tal como na experiência anterior, os valores usados no ficheiro de
configuração para a execução dos algoritmos implementados são os valores padrão e o Monkey
foi executado com um delay entre eventos de um segundo e meio para que todos os algoritmos de
exploração tivessem uma taxa de execução de eventos semelhante. Da mesma forma, o Monkey
apenas possui resultados da cobertura de código.
A Tabela 5.5 apresenta os resultados de cobertura de eventos das execuções dos vários al-
goritmos de exploração na aplicação Omni Notes e a Tabela 5.6 apresenta os seus resultados de
cobertura de código.
Tabela 5.5: Resultados de cobertura de eventos para a aplicação Omni Notes com um tempomáximo de exploração de 50 minutos
Algoritmo deexploração
Tempo deexecução
Eventosidentificados
%eventos
% eventos sobreo máximo local
% eventos sobreo máximo global
PNE 50m 16s 601ms 229 66.9 61.1 27.7
C 43m 8s 618ms 497 68.4 65.9 64.7
CWP 50m 5s 213ms 506 83.9 72.9 72.9
Tabela 5.6: Resultados de cobertura de código para a aplicação Omni Notes com um tempo má-ximo de exploração de 50 minutos
C CWP PNE M39.8% 43.4% 28.1% 28.6%
Ao analisar os resultados das duas tabelas, é possível verificar que:
1. O algoritmo Crawling with priority foi o que apresentou maior percentagem de cobertura
de código nas suas execuções;
2. O Monkey e o Priority to not executed and list items apresentam uma percentagem de co-
bertura de código semelhante;
60 Experiências
3. O Crawling foi o único algoritmo que parou automaticamente a sua execução antes do tempo
limite ser atingido;
4. Os algoritmos Crawling e Crawling with priority identificaram muitos mais eventos do que
o Priority to not executed and list items;
5. O Crawling with priority foi o algoritmo que obteve a maior percentagem de execução de
eventos, de execução de eventos sobre o máximo local e de execução de eventos sobre o
máximo global.
5.5 Discussão
Esta secção discute brevemente os resultados obtidos nas experiências realizadas e responde
às questões de investigação definidas no primeiro capítulo.
5.5.1 QI 1: É possível explorar automaticamente o comportamento das aplicaçõesAndroid através de uma análise dinâmica?
De forma a responder a esta questão de investigação, foi realizada a experiência apresentada na
Secção 5.3. Esta experiência consistiu na execução de quatro algoritmos de exploração dinâmica
num conjunto de dez aplicações Android diferentes. Destes quatro algoritmos executados, dois
foram implementados durante esta dissertação.
Com base nos resultados obtidos na experiência, podemos verificar que os algoritmos de ex-
ploração dinâmica foram executados com sucesso em todas as aplicações selecionadas. Assim, é
possível concluir que os dois algoritmos de exploração implementados como uma extensão da iM-
PAcT tool conseguem efetivamente explorar aplicações Android de forma automática e dinâmica.
5.5.2 QI 2: É possível obter melhores resultados que outros algoritmos já existentesno estado da arte?
A experiência apresentada na Secção 5.3 também pode ser usada para responder a esta questão
de investigação. Os resultados obtidos nesta experiência incluem a percentagem de cobertura
de código e de eventos. Relativamente à cobertura de eventos, esta é tanto maior quanto maior
for a percentagem de eventos executados, sendo que esta percentagem não considera o número
de eventos que pode ser executado, mas o número de eventos distintos que foram identificados
durante as execuções dos algoritmos. Assim, com base na cobertura de código e de eventos, é
possível analisar o desempenho dos algoritmos de exploração executados, exceto para o Monkey
onde apenas é possível analisar o seu desempenho através da cobertura de código.
Os resultados de cobertura de código mostram que os dois novos algoritmos combinados pos-
suem uma percentagem superior aos restantes algoritmos em 8 das 10 aplicações selecionadas.
Em relação aos outros dois algoritmos, o Monkey tem uma percentagem superior aos restantes em
5.5 Discussão 61
apenas 2 aplicações e o Priority to not executed and list items não consegue obter maior cobertura
de código em nenhuma das aplicações.
No que diz respeito aos resultados de cobertura de eventos, é possível verificar que os dois
algoritmos implementados identificam mais eventos que o Priority to not executed and list items
em 6 das 10 aplicações selecionadas. Dos três algoritmos usados nesta comparação, o Crawling
with priority é o que possui uma maior percentagem de eventos executados sobre o máximo local,
com um valor igual ou superior aos restantes em 7 das 10 aplicações e sobre o máximo global,
com um valor igual ou superior aos restantes em 8 destas aplicações.
Analisando estes resultados, é possível responder afirmativamente a esta questão de investiga-
ção, isto é, os novos algoritmos de exploração conseguem obter melhores resultados que outros
algoritmos já existentes no estado da arte, como o Priority to not executed and list items (presente
na iMPAcT tool) e o Monkey.
5.5.3 QI 3: É a cobertura de eventos diretamente proporcional à cobertura de có-digo?
Tal como nas duas questões de investigação anteriores, os resultados da experiência descrita
na Secção 5.3 podem ajudar a responder a esta questão.
Analisando os resultados para a aplicação RGB Tool, é possível verificar que o algoritmo
Priority to not executed and list items conseguiu identificar mais eventos e teve uma maior percen-
tagem de eventos executados sobre o máximo global do que os restantes algoritmos. No entanto,
este algoritmo dos quatro executados foi o que obteve pior percentagem de cobertura de código
com 35.9%, enquanto que os algoritmos Crawling with priority e Crawling, apesar de terem iden-
tificado menos eventos e de apresentaram uma menor percentagem de eventos executados sobre o
máximo global, obtiveram 42.9% e 41.8% de cobertura de código, respetivamente.
Relativamente à aplicação Unit Converter Ultimate, o algoritmo Crawling with priority identi-
ficou mais eventos, obteve uma maior percentagem de eventos executados e de eventos executados
sobre o máximo global. Contudo, este algoritmo de exploração obteve menos 0.4% de cobertura
de código que o Crawling.
Os resultados obtidos nesta experiência permitem-nos responder negativamente a esta questão
de investigação, isto é, nem sempre a cobertura de eventos é diretamente proporcional à cobertura
de código.
5.5.4 QI 4: Qual o efeito de aumentar o tempo máximo da exploração na coberturada aplicação?
A experiência apresentada na Secção 5.4 foi realizada para que os seus resultados combinados
com os da experiência da Secção 5.3 possam ser usados para responder a esta questão de inves-
tigação. Esta segunda experiência consistiu na execução dos quatro algoritmos de exploração na
aplicação Omni Notes com um tempo máximo de exploração de 50 minutos.
62 Experiências
Nos algoritmos Crawling with priority e Crawling, com o aumento de 20 minutos no tempo
máximo de exploração, o número de eventos identificados aumentou 134 e 141, respetivamente.
No entanto, nestes dois algoritmos, a percentagem de eventos executados sobre o máximo local e
sobre o máximo global praticamente não se alterou.
Relativamente à percentagem de cobertura de código, os algoritmos Crawling with priority,
Crawling, Priority to not executed and list items e Monkey apresentaram subidas de 9.6, 3.9, 1.1
e 13.7 valores, respetivamente. Com base nestes dados, é possível concluir que o Priority to not
executed and list items é o algoritmo cuja percentagem de cobertura de código menos altera com
o aumento do tempo máximo da exploração.
Em conclusão, é possível verificar que, nos algoritmos implementados, quando o tempo má-
ximo de exploração aumentou para 50 minutos, o número de eventos identificados aumentou tam-
bém. Já os valores da percentagem de eventos executados sobre o máximo local e sobre o máximo
global permaneceram semelhantes aos valores obtidos nas execuções realizadas com o tempo má-
ximo de 30 minutos. Em relação à percentagem de cobertura de código, o seu valor aumentou
com o aumento do tempo máximo de exploração.
5.6 Conclusões
Neste capítulo foram descritas as duas experiências realizadas para validar a abordagem de-
senvolvida e analisados os seus resultados, respondendo às questões de investigação. A primeira
experiência consistiu na execução de 4 algoritmos de exploração diferentes durante 30 minutos
num conjunto de 10 aplicações Android previamente selecionadas. Esta experiência tinha como
objetivo responder à primeira, segunda e terceira questões de investigação. A segunda experiên-
cia consistiu na execução dos mesmos algoritmos, mas apenas na aplicação Omni Notes e com o
tempo máximo de exploração definido para 50 minutos. Assim, foi possível verificar o impacto
do aumento deste tempo na cobertura de eventos e de código da aplicação, permitindo assim a
responder à última questão de investigação.
Na Secção 5.5 foram discutidos os resultados e dadas respostas às questões de investigação.
Relativamente à primeira questão de investigação (É possível explorar automaticamente o com-
portamento das aplicações Android através de uma análise dinâmica?), foi concluído que é pos-
sível explorar automaticamente o comportamento das aplicações Android através de uma análise
dinâmica. Com base nos resultados da primeira experiência, foi verificado que os novos algorit-
mos de exploração conseguem obter melhores resultados que o Monkey e que o Priority to not
executed and list items, respondendo assim à segunda questão de investigação (É possível obter
melhores resultados que outros algoritmos já existentes no estado da arte?). No que diz respeito
à terceira questão de investigação (É a cobertura de eventos diretamente proporcional à cobertura
de código?), foi verificado que nem sempre a cobertura de eventos é diretamente proporcional à
cobertura de código. Finalmente, para a última questão de investigação (Qual o efeito de aumentar
o tempo máximo da exploração na cobertura da aplicação?) foi possível concluir que, nos dois
algoritmos implementados, quando o tempo máximo da exploração é aumentado para 50 minutos,
5.6 Conclusões 63
a percentagem de cobertura de código e o número de eventos identificados aumentam também.
No entanto, as percentagens de eventos executados sobre o máximo local e sobre o máximo global
permanecem semelhantes relativamente às execuções realizadas com o tempo máximo definido
para 30 minutos.
64 Experiências
Capítulo 6
Conclusões e trabalho futuro
Atualmente, tem-se verificado um aumento da consciencialização para o teste de aplicações
móveis devido ao enorme número destas aplicações disponíveis no mercado. Por esta razão, os
investigadores têm-se focado na criação de ferramentas automáticas de teste para estas aplicações
a vários níveis, tais como memória, desempenho, interface, segurança, entre outros.
A exploração dinâmica à interface de uma aplicação móvel é uma técnica que pode dar suporte
a abordagens de teste ou de engenharia reversa. No entanto, existem alguns desafios que podem
impedir que a exploração consiga obter bons resultados, entre os quais se salientam: 1) possibili-
dade de existirem pontos de bloqueio; 2) não exercitação de todos os gestos de interação possíveis;
3) comportamento dinâmico das aplicações móveis; e 4) identificação de ecrãs diferentes.
O algoritmo apresentado neste documento tem como objetivo superar os problemas identifica-
dos anteriormente. Relativamente ao primeiro desafio, o utilizador pode indicar num ficheiro de
configuração o valor que pretende que seja inserido associado a cada tipo de input dos elementos
EditText (p. ex. password). Desta forma, caso seja detetado um ecrã de autenticação, os seus
campos irão ser preenchidos com os dados fornecidos pelo utilizador nesse ficheiro. No que diz
respeito ao segundo desafio, foram implementados os gestos de interação swipe, pinch e drag, que
ainda não eram exercitados pelos outros algoritmos da ferramenta. Além disto, o novo algoritmo
é extensível, permitindo assim a inclusão de novos gestos que possam surgir no futuro. Para o
terceiro desafio, de forma a evitar que a exploração fique presa num ecrã com eventos infinitos,
isto é, num ecrã onde novos elementos surgem sempre que se executa um evento, foi definido um
número máximo de vezes (limite superior) dentro do qual podem ser adicionados novos elementos
a um ecrã. Este número pode ser definido pelo utilizador no ficheiro de configuração. Em relação
ao último desafio, foi implementada uma nova heurística para comparação de ecrãs.
Durante a exploração, o algoritmo constrói uma máquina de estados finita que representa o
comportamento baseado em eventos da aplicação. Neste modelo, cada estado representa um ecrã
da aplicação e cada transição representa um evento executado. Na exploração da aplicação, quando
o algoritmo deteta que o ecrã atual tem todos os seus eventos exercitados, ele executa o algoritmo
65
66 Conclusões e trabalho futuro
de Dijkstra para encontrar o caminho de eventos mais curto entre o ecrã atual e o próximo ecrã a
ser explorado, fazendo uso da máquina de estados finita. Este processo de exploração da aplicação
é totalmente automático e dinâmico.
De forma a validar a abordagem implementada, foram realizadas duas experiências com apli-
cações disponíveis na Google Play Store. Estas experiências encontram-se descritas no Capítulo
5. Nesse capítulo foram ainda apresentadas as questões de investigação que surgiram ao longo do
desenvolvimento da dissertação, discutidos os resultados obtidos e dadas respostas a estas ques-
tões.
Com base nos resultados das experiências realizadas, foi possível concluir que o algoritmo im-
plementado como uma extensão da iMPAcT tool tem melhor desempenho que o melhor algoritmo
já existente nesta ferramenta. Além disto, é importante mencionar que o novo algoritmo consegue
também superar a cobertura de código do Monkey em 8 das 10 aplicações selecionadas.
O principal aspeto do trabalho futuro é o aumento do número de gestos de interação que são
exercitados visto que, quantos mais gestos forem exercitados, melhor será a exploração e maior
será, teoricamente, a cobertura da aplicação. De momento, apenas estão a ser executados os
seguintes eventos associados a elementos da interface: click, long click, check, edit, scroll, swipe,
pinch e drag. Um possível novo evento a ser adicionado ao algoritmo é o double click. Além
disto, a configuração do algoritmo também pode ser melhorada, passando a definição dos dados
do ficheiro de configuração para a interface da iMPAcT tool de forma a que seja mais intuitiva
para o utilizador.
Por último, como as experiências foram realizadas num pequeno conjunto de aplicações e
usando apenas mais duas ferramentas para comparação dos resultados, seria interessante, no fu-
turo, realizar as experiências a mais aplicações e usando um maior número de ferramentas de
exploração dinâmica disponíveis no estado da arte.
Referências
[1] D. Amalfitano, A.R. Fasolino, e P. Tramontana. A GUI Crawling-Based Technique for An-droid Mobile Application Testing. Em Proceedings - 4th IEEE International Conference onSoftware Testing, Verification, and Validation Workshops, ICSTW 2011, páginas 252–261,2011.
[2] D. Amalfitano, A.R. Fasolino, P. Tramontana, S. De Carmine, e A.M. Memon. Using GUIripping for automated testing of Android applications. Em 2012 27th IEEE/ACM Interna-tional Conference on Automated Software Engineering, ASE 2012 - Proceedings, páginas258–261, 2012.
[3] D. Amalfitano, A.R. Fasolino, P. Tramontana, B.D. Ta, e A.M. Memon. MobiGUITAR:Automated Model-Based Testing of Mobile Apps. IEEE Software, 32(5):53–59, 2015.
[4] D. Amalfitano, V. Riccio, N. Amatucci, V.D. Simone, e A.R. Fasolino. Combining Automa-ted GUI Exploration of Android apps with Capture and Replay through Machine Learning.Information and Software Technology, 105:95–116, 2019.
[5] D. Amalfitano, V. Riccio, A.C.R. Paiva, e A.R. Fasolino. Why does the orientation changemess up my Android application? From GUI failures to code faults. Software Testing Verifi-cation and Reliability, 28(1), 2018.
[6] Android Developers. Android Debug Bridge. [Online]. Disponível em: https://developer.android.com/studio/command-line/adb. [Acedido: 31-Jan-2019].
[7] Android Developers. Espresso. [Online]. Disponível em: https://developer.android.com/training/testing/espresso/. [Acedido: 03-Jan-2019].
[8] Android Developers. UI Automator. [Online]. Disponível em: https://developer.android.com/training/testing/ui-automator. [Acedido: 03-Jan-2019].
[9] Android Developers. UI/Application Exerciser Monkey. [Online]. Disponível em: https://developer.android.com/studio/test/monkey. [Acedido: 27-Dez-2018].
[10] Apktool. A tool for reverse engineering 3rd party, closed, binary Android apps. [Online].Disponível em: https://ibotpeaches.github.io/Apktool/. [Acedido: 31-Jan-2019].
[11] AppBrain. Number of Android applications on the Google Play store. [Online]. Disponívelem: https://www.appbrain.com/stats/number-of-android-apps. [Acedido:26-Dez-2018].
[12] Appium. Appium. [Online]. Disponível em: http://appium.io/. [Acedido: 03-Jan-2019].
67
68 REFERÊNCIAS
[13] T. Azim e I. Neamtiu. Targeted and Depth-first Exploration for Systematic Testing of An-droid Apps. Em Proceedings of the Conference on Object-Oriented Programming Systems,Languages, and Applications, OOPSLA, páginas 641–660, 2013.
[14] A. Banerjee, L.K. Chong, C. Ballabriga, e A. Roychoudhury. EnergyPatch: Repairing Re-source Leaks to Improve Energy-Efficiency of Android Apps. IEEE Transactions on Soft-ware Engineering, 44(5):470–490, 2018.
[15] Luca Berardinelli, Vittorio Cortellessa, e Antinisca Di Marco. Performance Modeling andAnalysis of Context-Aware Mobile Software Systems. Em David S Rosenblum e GabrieleTaentzer, organizadores, Fundamental Approaches to Software Engineering, páginas 353–367. Springer Berlin Heidelberg, 2010.
[16] Nataniel P. Borges Jr., Jenny Hotzkow, e Andreas Zeller. DroidMate-2: A Platform forAndroid Test Generation. Em Proceedings of the 33rd ACM/IEEE International Conferenceon Automated Software Engineering, ASE 2018, páginas 916–919. ACM, 2018.
[17] J. Cheng, Y. Zhu, T. Zhang, C. Zhu, e W. Zhou. Mobile compatibility testing usingmulti-objective genetic algorithm. Em Proceedings - 9th IEEE International Symposiumon Service-Oriented System Engineering, IEEE SOSE 2015, volume 30, páginas 302–307,2015.
[18] W. Choi, G. Necula, e K. Sen. Guided GUI Testing of Android Apps with Minimal Restartand Approximate Learning. Em Proceedings of the Conference on Object-Oriented Pro-gramming Systems, Languages, and Applications, OOPSLA, páginas 623–639, 2013.
[19] P. Costa, A.C.R. Paiva, e M. Nabuco. Pattern based GUI testing for mobile applications.Em Proceedings - 2014 9th International Conference on the Quality of Information andCommunications Technology, QUATIC 2014, páginas 66–74, 2014.
[20] M.A. Dar e J. Parvez. Enhancing security of Android & IOS by implementing need-basedsecurity (NBS). Em 2014 International Conference on Control, Instrumentation, Communi-cation and Computational Technologies, ICCICCT 2014, páginas 728–733, 2014.
[21] L. Delia, N. Galdamez, L. Corbalan, P. Pesado, e P. Thomas. Approaches to mobile ap-plication development: Comparative performance analysis. Em Proceedings of ComputingConference 2017, volume 2018-Janua, páginas 652–659, 2018.
[22] Material Design. Navigation drawer. [Online]. Disponível em: https://material.io/design/components/navigation-drawer.html. [Acedido: 27-Dez-2018].
[23] Android Developers. Core app quality. [Online]. Disponível em: https://developer.android.com/docs/quality-guidelines/core-app-quality. [Acedido: 02-Jan-2019].
[24] Android Developers. Request App Permissions. [Online]. Disponível em: https://developer.android.com/training/permissions/requesting. [Acedido: 03-Jun-2019].
[25] Dex2jar. Tools to work with android .dex and java .class files. [Online]. Disponível em:https://code.google.com/p/dex2jar. [Acedido: 31-Jan-2019].
[26] eBay software foundation. Selenium for Android. [Online]. Disponível em: http://selendroid.io/. [Acedido: 04-Jan-2019].
REFERÊNCIAS 69
[27] EclEmma. JaCoCo Java Code Coverage Library. [Online]. Disponível em: https://www.jacoco.org/jacoco/. [Acedido: 31-Jan-2019].
[28] Mohd Ehmer e Farmeena Khan. A Comparative Study of White Box, Black Box and GreyBox Testing Techniques. International Journal of Advanced Computer Science and Appli-cations, 3, 2012.
[29] EMMA. A free Java code coverage tool. [Online]. Disponível em: http://emma.sourceforge.net/. [Acedido: 31-Jan-2019].
[30] J. Gao, X. Bai, W.-T. Tsai, e T. Uehara. Mobile application testing: A tutorial. Computer,47(2):46–55, 2014.
[31] Shuai Hao, Bin Liu, Suman Nath, William G J Halfond, e Ramesh Govindan. PUMA:Programmable UI-automation for Large-scale Dynamic Analysis of Mobile Apps. Em Pro-ceedings of the 12th Annual International Conference on Mobile Systems, Applications, andServices, MobiSys ’14, páginas 204–217. ACM, 2014.
[32] C. Hu e I. Neamtiu. Automating GUI testing for Android applications. Em Proceedings -International Conference on Software Engineering, páginas 77–83, 2011.
[33] C.-Y. Huang, C.-H. Chiu, C.-H. Lin, e H.-W. Tzeng. Code Coverage Measurement for An-droid Dynamic Analysis Tools. Em Proceedings - 2015 IEEE 3rd International Conferenceon Mobile Services, MS 2015, páginas 209–216, 2015.
[34] Konrad Jamrozik e Andreas Zeller. DroidMate: A Robust and Extensible Test Generator forAndroid. Em Proceedings of the International Workshop on Mobile Software Engineeringand Systems - MOBILESoft ’16, páginas 293–294. IEEE, Piscataway, NJ, USA, 2016.
[35] Jasmin. Jasmin. [Online]. Disponível em: http://jasmin.sourceforge.net/. [Ace-dido: 31-Jan-2019].
[36] J.C.J. Keng, L. Jiang, T.K. Wee, e R.K. Balan. Graph-Aided Directed Testing of Android Ap-plications for Checking Runtime Privacy Behaviours. Em Proceedings - 11th InternationalWorkshop on Automation of Software Test, AST 2016, páginas 57–63, 2016.
[37] Antti Kervinen, Mika Maunumaa, Tuula Pääkkönen, e Mika Katara. Model-Based TestingThrough a GUI. Em Wolfgang Grieskamp e Carsten Weise, organizadores, 5th Internatio-nal Workshop on Formal Approaches to Testing of Software (FATES 2005), páginas 16–31.Springer Berlin Heidelberg, 2006.
[38] Konstantin Knorr e David Aspinall. Security testing for Android mHealth apps. Em2015 IEEE 8th International Conference on Software Testing, Verification and ValidationWorkshops, ICSTW 2015 - Proceedings, páginas 1–8, 2015.
[39] Y. Koroglu, A. Sen, O. Muslu, Y. Mete, C. Ulker, T. Tanriverdi, e Y. Donmez. QBE:QLearning-Based Exploration of Android Applications. Em Proceedings - 2018 IEEE 11thInternational Conference on Software Testing, Verification and Validation, ICST 2018, pági-nas 105–115, 2018.
[40] J. Liu, T. Wu, X. Deng, J. Yan, e J. Zhang. InsDal: A safe and extensible instrumentation toolon Dalvik byte-code for Android applications. Em SANER 2017 - 24th IEEE InternationalConference on Software Analysis, Evolution, and Reengineering, páginas 502–506, 2017.
70 REFERÊNCIAS
[41] A. Machiry, R. Tahiliani, e M. Naik. Dynodroid: an input generation system for Androidapps. Em 2013 9th Joint Meeting of the European Software Engineering Conference and theACM SIGSOFT Symposium on the Foundations of Software Engineering, ESEC/FSE 2013 -Proceedings, páginas 224–234, 2013.
[42] Y. Maezawa, H. Washizaki, e S. Honiden. Extracting interaction-based stateful behaviorin Rich Internet Applications. Em Proceedings of the European Conference on SoftwareMaintenance and Reengineering, CSMR, páginas 423–428, 2012.
[43] Tiago Monteiro e Ana C R Paiva. Pattern based GUI testing modeling environment. Em IEEE6th International Conference on Software Testing, Verification and Validation Workshops,ICSTW 2013, páginas 140–143, 2013.
[44] K. Moran, M. Linares-Vasquez, C. Bernal-Cardenas, C. Vendome, e D. Poshyvanyk. Au-tomatically Discovering, Reporting and Reproducing Android Application Crashes. EmProceedings - 2016 IEEE International Conference on Software Testing, Verification andValidation, ICST 2016, páginas 33–44, 2016.
[45] K. Moran, M. Linares-Vasquez, C. Bernal-Cardenas, C. Vendome, e D. Poshyvanyk. CrashS-cope: A Practical Tool for Automated Testing of Android Applications. Em Proceedings -2017 IEEE/ACM 39th International Conference on Software Engineering Companion, ICSE-C 2017, páginas 15–18, 2017.
[46] R.M.L.M. Moreira e A.C.R. Paiva. PBGT tool: An integrated modeling and testing envi-ronment for pattern-based GUI testing. Em ASE 2014 - Proceedings of the 29th ACM/IEEEInternational Conference on Automated Software Engineering, páginas 863–866, 2014.
[47] Rodrigo M L M Moreira, Ana C R Paiva, e Atif Memon. A pattern-based approach for GUImodeling and testing. Em 2013 IEEE 24th International Symposium on Software ReliabilityEngineering, ISSRE 2013, páginas 288–297, 2013.
[48] Rodrigo M. L. M. Moreira, Ana C. R. Paiva, Miguel Nabuco, e Atif Memon. Pattern-basedGUI testing: Bridging the gap between design and quality assurance. Softw. Test., Verif.Reliab., 27(3), 2017.
[49] I.C. Morgado e A.C.R. Paiva. The iMPAcT tool: Testing UI patterns on mobile applications.Em Proceedings - 2015 30th IEEE/ACM International Conference on Automated SoftwareEngineering, ASE 2015, páginas 876–881, 2015.
[50] I.C. Morgado e A.C.R. Paiva. Impact of Execution Modes on Finding Android Failures. EmProcedia Computer Science, volume 83, páginas 284–291, 2016.
[51] I.C. Morgado e A.C.R. Paiva. Mobile GUI testing. Software Quality Journal, 26(4):1553–1570, 2018.
[52] I.C. Morgado, A.C.R. Paiva, J.P. Faria, e R. Camacho. GUI reverse engineering with ma-chine learning. Em 2012 1st International Workshop on Realizing AI Synergies in SoftwareEngineering, RAISE 2012 - Proceedings, páginas 27–31, 2012.
[53] Inês Coimbra Morgado. Automated Pattern-Based Testing of Mobile Applications. Tese dedoutoramento, Faculdade de Engenharia da Universidade do Porto, 2017.
[54] Inês Coimbra Morgado e Ana C. R. Paiva. The iMPAcT Tool for Android Testing. Proc.ACM Hum.-Comput. Interact., 3(EICS):4:1–4:23, 2019.
REFERÊNCIAS 71
[55] Ines Coimbra Morgado e Ana C.R. Paiva. Testing approach for mobile applications throughreverse engineering of UI patterns. Em Proceedings - 2015 30th IEEE/ACM InternationalConference on Automated Software Engineering Workshops, ASEW 2015, páginas 42–49,2015.
[56] H. Muccini, A. Di Francesco, e P. Esposito. Software testing of mobile applications: Chal-lenges and future research directions. Em 2012 7th International Workshop on Automationof Software Test, AST 2012 - Proceedings, páginas 29–35, 2012.
[57] A. C. R. Paiva, M. A. Gonçalves, e A. R. Barros. Testing Android Incoming Calls. Em2019 12th IEEE Conference on Software Testing, Validation and Verification (ICST), páginas441–448. IEEE, 2019.
[58] Ana C R Paiva, João C P Faria, Nikolai Tillmann, e Raul A M Vidal. A Model-to-Implementation Mapping Tool for Automated Model-Based GUI Testing. Em Kung-KiuLau e Richard Banach, organizadores, Formal Methods and Software Engineering, páginas450–464. Springer Berlin Heidelberg, 2005.
[59] Ana C. R. Paiva, Joao M. E. P. Gouveia, Jean-David Elizabeth, e Marcio E. Delamaro.Testing When Mobile Apps Go to Background and Come Back to Foreground. Em 2019IEEE International Conference on Software Testing, Verification and Validation Workshops(ICSTW), páginas 102–111. IEEE, 2019.
[60] R. Palit, R. Arya, K. Naik, e A. Singh. Selection and execution of user level test casesfor energy cost evaluation of smartphones. Em Proceedings - International Conference onSoftware Engineering, páginas 84–90, 2011.
[61] Aleksandr Pilgun, Olga Gadyatskaya, Stanislav Dashevskyi, Yury Zhauniarovich, e ArtsiomKushniarou. An Effective Android Code Coverage Tool. Em Proceedings of the 2018 ACMSIGSAC Conference on Computer and Communications Security, CCS ’18, páginas 2189–2191. ACM, 2018.
[62] Robotium. Robotium. [Online]. Disponível em: https://github.com/RobotiumTech/robotium. [Acedido: 03-Jan-2019].
[63] C. Sacramento e A. C. R. Paiva. Web Application Model Generation through Reverse Engi-neering and UI Pattern Inferring. Em Machado R J Brito M A da Silva A.R. da Silva A.R.,organizador, 2014 9th International Conference on the Quality of Information and Commu-nications Technology, páginas 105–115. IEEE, 2014.
[64] João Carlos Silva, Carlos Silva, Rui D Gonçalo, João Saraiva, e José Creissac Campos. TheGUISurfer Tool: Towards a Language Independent Approach to Reverse Engineering GUICode. Em Proceedings of the 2Nd ACM SIGCHI Symposium on Engineering InteractiveComputing Systems, EICS ’10, páginas 181–186. ACM, 2010.
[65] Smali. smali. [Online]. Disponível em: http://baksmali.com. [Acedido: 31-Jan-2019].
[66] Statista. Annual number of mobile app downloads worldwide 2022. [On-line]. Disponível em: https://www.statista.com/statistics/271644/worldwide-free-and-paid-mobile-app-store-downloads/. [Acedido: 26-Dez-2018].
72 REFERÊNCIAS
[67] Statista. Mobile and multi-channel application testing challenges 2013-2017. [On-line]. Disponível em: https://www.statista.com/statistics/500630/worldwide-mobile-and-multichannel-application-testing-challenges/.[Acedido: 26-Dez-2018].
[68] Statista. Mobile OS market share 2018. [Online]. Disponí-vel em: https://www.statista.com/statistics/266136/global-market-share-held-by-smartphone-operating-systems. [Ace-dido: 26-Dez-2018].
[69] T. Su. FSMdroid: Guided GUI Testing of Android Apps. Em Proceedings - InternationalConference on Software Engineering, páginas 689–691, 2016.
[70] Ting Su, Guozhu Meng, Yuting Chen, Ke Wu, Weiming Yang, Yao Yao, Geguang Pu, YangLiu, e Zhendong Su. Guided, stochastic model-based GUI testing of Android apps. EmZisman A., Bodden E., Schafer W., e van Deursen A., organizadores, 11th Joint Meeting ofthe European Software Engineering Conference and the ACM SIGSOFT Symposium on theFoundations of Software Engineering, ESEC/FSE 2017, volume Part F1301, páginas 245–256. Association for Computing Machinery, 2017.
[71] Mark Utting e Bruno Legeard. Practical Model-Based Testing: A Tools Approach. MorganKaufmann Publishers Inc., San Francisco, CA, USA, 2007.
[72] P. Wang, B. Liang, W. You, J. Li, e W. Shi. Automatic Android GUI Traversal with HighCoverage. Em Proceedings - 2014 4th International Conference on Communication Systemsand Network Technologies, CSNT 2014, páginas 1161–1166, 2014.
[73] Xamarin. Calaba.sh - Automated Acceptance Testing for iOS and Android Apps. [Online].Disponível em: https://calaba.sh/. [Acedido: 04-Jan-2019].
[74] Qing Xie. Developing cost-effective model-based techniques for GUI testing. Em 28thinternational conference on Software engineering - (ICSE 2006), volume 2006, páginas 997–1000, 2006.
[75] Wei Yang, Mukul R Prasad, e Tao Xie. A Grey-Box Approach for Automated GUI-ModelGeneration of Mobile Applications. Em Vittorio Cortellessa e Dániel Varró, organizado-res, Fundamental Approaches to Software Engineering, páginas 250–265. Springer BerlinHeidelberg, 2013.
[76] C.-C. Yeh e S.-K. Huang. CovDroid: A Black-Box Testing Coverage System for Android.Em Proceedings - International Computer Software and Applications Conference, volume 3,páginas 447–452, 2015.
[77] Young-Min Baek e Doo-Hwan Bae. Automated model-based Android GUI testing usingmulti-level GUI comparison criteria. 2016 31st IEEE/ACM International Conference onAutomated Software Engineering (ASE). Proceedings, 2016.
[78] Xin Zhang, Zhenyu Chen, Chunrong Fang, e Zicong Liu. Guiding the crowds for Androidtesting. Em Proceedings of the 38th International Conference on Software Engineering Com-panion - ICSE ’16, páginas 752–753. IEEE, Piscataway, NJ, USA, 2016.
[79] Y. Zhauniarovich, A. Philippov, O. Gadyatskaya, B. Crispo, e F. Massacci. Towards BlackBox Testing of Android Apps. Em Proceedings - 10th International Conference on Availa-bility, Reliability and Security, ARES 2015, páginas 501–510, 2015.
Anexo A
Funções
O presente anexo contém o código da função implementada para detetar o tipo de input asso-
ciado a um elemento e para criar um evento edit.
A.1 Criação do evento edit
A função abaixo apresentada situa-se na classe que representa um elemento e tem como obje-
tivo a criação de um evento edit que depende do tipo de input detetado para esse mesmo elemento.
Para isto, a função analisa o valor da propriedade INPUT_TYPE do elemento, retira as f lags des-
necessárias e verifica o tipo de input num switch, guardando-o na variável key. Ao mesmo tempo,
é atribuído um valor padrão que também depende do tipo de input detetado. Por fim, é analisado
o ficheiro de configuração para verificar se o utilizador introduziu um valor para a key detetada e,
em caso afirmativo, este é usado para a criação do evento. Caso contrário, o valor padrão é usado.
1 /**
2 * Gets the event that can be applied on this edit element based on his
inputType
3 * @return the edit event to be executed
4 */
5 private Event getEditEvent() {
6 if((int)properties.get(INPUT_TYPE) == 0) //No value for input type so there
is no need to create an edit event
7 return null;
8
9 //removing some not necessary flags
10 int type = (int)properties.get(INPUT_TYPE) & ~IT_AUTO_COMPLETE & ~
IT_AUTO_CORRECT & ~IT_NO_SUGGESTIONS;
11 String defaultValue;
12 String key;
13
73
74 Funções
14 switch (type) {
15 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_VARIATION_PASSWORD): //Password or Confirm Password Text
16 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_VARIATION_VISIBLE_PASSWORD): //Password or Confirm
Password Text Visible
17 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_VARIATION_WEB_PASSWORD): //Web Password
18 defaultValue = "pass123";
19 key = "password";
20 break;
21 case (InputType.TYPE_CLASS_NUMBER | InputType.
TYPE_NUMBER_VARIATION_PASSWORD): //Password or Confirm Password
Number
22 defaultValue = "123321";
23 key = "password_number";
24 break;
25 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_VARIATION_EMAIL_ADDRESS): //Email
26 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS): //Web Email Address
27 defaultValue = "[email protected]";
28 key = "email";
29 break;
30 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_VARIATION_EMAIL_SUBJECT): //Email Subject
31 defaultValue = "Email Subject";
32 key = "email_subject";
33 break;
34 case InputType.TYPE_CLASS_PHONE: //Phone Number
35 defaultValue = "00351911111111";
36 key = "phone_number";
37 break;
38 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_VARIATION_POSTAL_ADDRESS): //Address
39 defaultValue = "85 Brynglas Road, Glengyle";
40 key = "address";
41 break;
42 case (InputType.TYPE_CLASS_DATETIME | InputType.
TYPE_DATETIME_VARIATION_TIME): //Time
43 defaultValue = "10:22";
44 key = "time";
45 break;
46 case (InputType.TYPE_CLASS_DATETIME | InputType.
TYPE_DATETIME_VARIATION_DATE): //Date
47 SimpleDateFormat dt = new SimpleDateFormat("yyyy-MM-dd");
48 defaultValue = dt.format(new Date());
49 key = "date";
50 break;
A.1 Criação do evento edit 75
51 case (InputType.TYPE_CLASS_DATETIME | InputType.
TYPE_DATETIME_VARIATION_NORMAL): //DateTime
52 SimpleDateFormat dt1 = new SimpleDateFormat("yyyy-MM-dd hh:mm");
53 defaultValue = dt1.format(new Date());
54 key = "date_time";
55 break;
56 case InputType.TYPE_CLASS_NUMBER: //Number
57 defaultValue = "5";
58 key = "number";
59 break;
60 case (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED):
//Number Signed
61 defaultValue = "-10";
62 key = "number_signed";
63 break;
64 case (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL)
: //Number Decimal
65 defaultValue = "10.0";
66 key = "number_decimal";
67 break;
68 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_VARIATION_PERSON_NAME): //Person Name
69 defaultValue = "Nicole Oliver";
70 key = "person_name";
71 break;
72 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_VARIATION_LONG_MESSAGE): //Long Message
73 defaultValue = "Lorem ipsum nisi taciti porttitor tempus purus ante
vulputate nunc, elementum ut dui consequat tellus aliquam
massa dui tristique";
74 key = "long_message";
75 break;
76 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_VARIATION_SHORT_MESSAGE): //Short Message
77 defaultValue = "Hello. How are you?";
78 key = "short_message";
79 break;
80 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_FLAG_CAP_CHARACTERS): //Text with capitalization of all
chars
81 defaultValue = "HELLO. HOW ARE YOU?";
82 key = "text_cap_chars";
83 break;
84 case (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_WORDS):
//Text with capitalization of the first char of every word
85 defaultValue = "Hello. How Are You?";
86 key = "text_cap_words";
87 break;
76 Funções
88 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_FLAG_CAP_SENTENCES): //Text with capitalization of the
first char of every sentence
89 defaultValue = "Hello. How are you?";
90 key = "text_cap_sentence";
91 break;
92 case (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI):
//Text URI
93 defaultValue = "https://sigarra.up.pt";
94 key = "uri";
95 break;
96 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_VARIATION_PHONETIC): //Phonetic Pronunciation
97 defaultValue = "Phonetic text";
98 key = "phonetic_pronunciation";
99 break;
100 case (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_FILTER)
: //Text filtering
101 defaultValue = "Filter text";
102 key = "filter";
103 break;
104 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_VARIATION_WEB_EDIT_TEXT): //Web Text
105 case (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL)
: //Text
106 defaultValue = "text";
107 key = "text";
108 break;
109 case (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE):
//Text MultiLine
110 case (InputType.TYPE_CLASS_TEXT | InputType.
TYPE_TEXT_FLAG_IME_MULTI_LINE): //Text IME MultiLine
111 defaultValue = "Example line 1.\nexample line 2.\nexample line 3.";
112 key = "text_multiline";
113 break;
114 default: //Unidentified Field
115 return new Event(this, EventName.EDIT, "Text");
116 }
117
118 String input;
119 try {
120 input = Constants.editTextInputData.getString(key).equals("") ?
defaultValue : Constants.editTextInputData.getString(key);
121 } catch (Exception e) {
122 input = defaultValue;
123 }
124
125 return new Event(this, EventName.EDIT, input);
126 }
Anexo B
Cobertura de código
O presente anexo contém a sequência de passos que foram necessários realizar em cada apli-
cação para que fosse possível obter a cobertura de código usando o JaCoCo nas experiências
realizadas.
B.1 Passos necessários para a criação do relatório
1. Inserir o seguinte código no ficheiro “build.gradle” do módulo da aplicação:
1 apply plugin: ’jacoco’
2
3 android {
4 jacoco {
5 version "0.8.3"
6 }
7 sourceSets {
8 main {
9 resources.includes = [’**/jacoco-agent.properties’]
10 }
11 }
12 buildTypes {
13 debug {
14 testCoverageEnabled true
15 }
16 }
17 }
18
19 task jacocoTestReport(type:JacocoReport) {
20 group = "Reporting"
21 description = "Generate Jacoco coverage reports"
22 // exclude auto-generated classes and tests
77
78 Cobertura de código
23 def fileFilter = [’**/R.class’, ’**/R$*.class’,
24 ’**/BuildConfig.*’, ’**/Manifest*.*’,
25 ’android/**/*.*’]
26 def debugTree = fileTree(dir:
27 "${project.buildDir}/intermediates/javac/debug/
compileDebugJavaWithJavac/classes",
28 excludes: fileFilter)
29
30 def mainSrc = "${project.projectDir}/src/main/java"
31 sourceDirectories = files([mainSrc])
32 classDirectories = files([debugTree])
33 additionalSourceDirs = files([
34 "${buildDir}/generated/source/buildConfig/debug",
35 "${buildDir}/generated/source/r/debug"
36 ])
37 executionData = fileTree(dir: project.projectDir, includes:
38 [’**/*.exec’, ’**/*.ec’])
39 reports {
40 xml.enabled = true
41 xml.destination = file("${buildDir}/jacocoTestReport.xml")
42 csv.enabled = false
43 html.enabled = true
44 html.destination = file("${buildDir}/reports/jacoco")
45 }
46 }
Nota 1: Ter em atenção que algumas das configurações mencionadas em cima podem já existir
no ficheiro do projeto.
Nota 2: Os caminhos presentes na task jacocoTestReport devem ser alterados de acordo com
o projeto em questão.
2. Configurar o agente JaCoCo.
2.1. Criar a pasta “resources” dentro de app\src\main (este caminho pode variar).
2.2. Criar um ficheiro com o nome “jacoco-agent.properties”.
2.3. No ficheiro criado inserir o seguinte código:
1 destfile=/storage/sdcard/coverage.exec
3. Inserir o código para que a cobertura possa ser guardada.
3.1. Ir à atividade principal da aplicação e, no final do método onStop(), inserir o seguinte
código:
1 String coverageFilePath = Environment.getExternalStorageDirectory() + File.
separator + "coverage.exec";
2 File coverageFile = new File(coverageFilePath);
3
B.1 Passos necessários para a criação do relatório 79
4 if(BuildConfig.DEBUG) {
5 try {
6 Class<?> emmaRTClass = Class.forName("com.vladium.emma.rt.RT");
7 Method dumpCoverageMethod = emmaRTClass.getMethod("dumpCoverageData",
coverageFile.getClass(),boolean.class,boolean.class);
8 dumpCoverageMethod.invoke(null, coverageFile,true,false);
9 } catch(Exception e) {
10 throw new RuntimeException("Is emma jar on classpath?", e);
11 }
12 }
3.2. Inserir as permissões necessárias no manifesto da aplicação:
1 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3.3. Da versão 6.0 do Android para cima é necessário pedir ao utilizador permissão para que
a aplicação possa escrever em memória. Para isto, deve ser inserido o seguinte código no método
onCreate() da atividade principal:
1 String[] permission = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
2 if(!hasPermissions(this, permission)) {
3 ActivityCompat.requestPermissions(Map.this, permission, 1);
4 }
3.4. Inserir a função hasPermissions() na classe da atividade principal:
1 public static boolean hasPermissions(Context context, String... permissions) {
2 if (context != null && permissions != null) {
3 for (String permission : permissions) {
4 if (ActivityCompat.checkSelfPermission(context, permission) !=
PackageManager.PERMISSION_GRANTED) {
5 return false;
6 }
7 }
8 }
9 return true;
10 }
4. Caso a aplicação crash a análise de cobertura não é escrita e, desta forma, não é possível
analisar a cobertura de código da aplicação. Por esta razão, deve ser criado um handler para as
exceções de modo a que a cobertura possa ser gravada quando a aplicação crasha.
4.1. Ir à classe que extende Application (caso não exista, esta classe deve ser criada) e inserir
o seguinte membro privado:
80 Cobertura de código
1 private Thread.UncaughtExceptionHandler _androidUncaughtExceptionHandler;
4.2. Inserir o seguinte código no fim do método onCreate() desta classe:
1 _androidUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
2
3 Thread.setDefaultUncaughtExceptionHandler(
4 (thread, e) -> {
5 String coverageFilePath = Environment.getExternalStorageDirectory() +
File.separator + "coverage.exec";
6 File coverageFile = new File(coverageFilePath);
7
8 if(BuildConfig.DEBUG) {
9 try {
10 Class<?> emmaRTClass = Class.forName("com.vladium.emma.rt.RT");
11 Method dumpCoverageMethod = emmaRTClass.getMethod("
dumpCoverageData",coverageFile.getClass(),boolean.class,
boolean.class);
12 dumpCoverageMethod.invoke(null, coverageFile,true,false);
13 } catch(Exception ex) {
14 Log.e("EMMA", ex.getMessage());
15 }
16 }
17 _androidUncaughtExceptionHandler.uncaughtException(thread, e);
18 });
Nota: Este código apanha uma exceção e escreve num ficheiro a informação sobre a cobertura
existente até ao momento. Após esta fase, é chamado o handler padrão.
5. Fazer build para ser criado o APK.
6. Instalar o APK num emulador ou dispositivo.
7. Fazer os testes manuais/automáticos à aplicação.
8. Após os testes, é necessário criar o relatório de cobertura.
8.1. Dar pull ao ficheiro “coverage.exec” criado no dispositivo executando o seguinte co-
mando no terminal do Android Studio (alterar o segundo caminho de acordo com o projeto):
1 adb pull /sdcard/coverage.exec app/build/outputs/coverage.exec
8.2. Criar o relatório de cobertura executando nesse mesmo terminal:
1 gradlew jacocoTestReport
9. Aceder a app\build\reports\jacoco (este caminho pode variar) e abrir o ficheiro “in-
dex.html”.