Tapsterbot - Montagem e Utilização
Durante o período em que estive trabalhando em Berlim, participei de algumas das edições do Hackathon da empresa onde trabalhava, que ocorria duas vezes ao ano e era tradicional na área de TI. Na edição de Outubro de 2018, o head da área de QA perguntou-me se tinha algum projeto em mente, já que havia participado na edição anterior e sabia do meu interesse em participar dos próximos. Neste instante, fui apresentado ao projeto do Tapsterbot, um projeto open-source criado e mantido por Jason Huggins, uma das mentes por trás de ferramentas como Selenium e Appium.
Os vídeos chamaram bastante a minha atenção, pelo fato de ver um robô em ação, efetuado testes em devices físicos. Alguns dos vídeos disponíveis na Internet mostram o Tapsterbot jogando Angry Birds, ou tocando piano em um dueto de robôs. Mas estava especialmente curioso em ver o robô em ação, executando testes em um aplicativo mobile.
Pesquisa e impressão das peças
Já traçado o objetivo para o Hackathon, fui pesquisar mais a respeito do Tapsterbot e tornar viável a sua construção durante o período do desafio, que seria em dois dias - Sexta-feira e Sábado, com apresentação na Segunda-feira seguinte. Para isso antecipei-me com a impressão 3D, pois sabia que isso tomaria a maior parte do tempo. A impressão de todas as peças devou em torno de 40 horas e ficaram prontas somente no Sábado ao final do dia, mas as principais peças da estrutura já estavam impressas um dia antes, o que já adiantava bastante do que poderia ser montado e o necessário para a efetivação dos primeiros testes.Primeiros testes do hardware
Todos os itens de hardware já estavam disponíveis na Sexta-feira pela manhã, e como ainda faltavam peças a serem impressas, decidi iniciar com a configuração do Arduíno Uno e fazer alguns testes da futura movimentação dos braços, acoplando o servo shield e ligando a ele os servo motors.- Baixar e instalar o Arduino IDE: http://arduino.cc/en/Guide/HomePage
- Utilizar o script de testes "Blink", para verificar o funcionamento do Arduino
- Ainda no Arduino IDE, carregar o script "Firmata":
File -> Open -> Examples > Firmata > StandardFirmata.
- Configurar o servidor Node.js, instalando as dependências:
cd software/node; npm install
- Iniciar o servidor:
node src/bot.js.
- No mesmo terminal aonde foi iniciado o servidor, enviar um comando para testar a movimentação dos braços:
go(0,0,-140)
Montagem
Com algumas das peças já impressas, já era possível iniciar o processo de montagem do Tapsterbot. Seguindo as instruções presentes no link https://www.instructables.com/howto/?sort=none&q=tapsterbot, ficou claro como seria a montagem das partes mais complicadas:- Fixação dos suportes aos servo motors;
- Fixação dos servo motors ao topo do Tapsterbot;
- Montagem dos braços robóticos.
Um fato importante citado nas instruções de montagem: a polaridade dos magnetos devem ser sempre as mesmas, pois se os mesmos forem colocados lado a lado com as polaridades invertidas, existe uma grande tendência das bolinhas de aço não se fixarem corretamente aos braços e ao suporte do "Stylus pen" (ou caneta de tablet).
E falando no Stylus Pen, não consegui encontrar o modelo especificado na lista de materiais. Por isso, acabei por improvisar. Serrei a ponta de uma caneta de tablet grande, e fixei a mesma ao suporte utilizando cola quente.
E para energizar o Stylus Pen, foi soldado um pedaço de fio à ponta da caneta, e a outra ponta ligada a um dos conectores de terra do servo shield. Esta energização é necessária para que exista o contato da caneta com a tela do Smartphone.
O resultado ao final da montagem foi bem animador!
Implementação dos testes
O servidor Node.js expõe três endpoints REST: go, circle e arc. Isso possibilita a utilização de qualquer framework de testes, bastando apenas a implementação das requisições. Para isso, utilizei o JUnit para orquestrar os testes, e RestAssured para efetuar as requests. Um exemplo de implementação da request "POST /go":
private void go(Integer x, Integer y, Integer z) {Uma vez implementada, a requisição "POST /go" posiciona o braço de acordo com a coordenada X, Y e Z informadas. Assim, torna-se possível a implementação de um comando para efetuar um clique em uma tela, chamando por três vezes o método "go()": uma para posicionar o braço, outra para descer, outra para subir o braço:
given()
.contentType(ContentType.JSON)
.body(buildCoordinates(x, y, z))
.when()
.post("http://localhost:8080/go")
.then()
.assertThat().statusCode(HTTP_OK);
}
private CoordinatesDTO buildCoordinates(Integer x, Integer y, Integer z) {
return CoordinatesDTO.builder()
.x(x)
.y(y)
.z(z)
.build();
}
public void tapOnScreen(Integer x, Integer y) {Estes métodos foram implementados em uma classe de suporte, bastando apenas a sua declaração em uma classe Java.
Integer lower_z = HIGHER_Z - 15;
go(x, y, HIGHER_Z);
go(x, y, lower_z);
go(x, y, HIGHER_Z);
}
Outro fator importante a ser considerado: O Tapsterbot não tem a inteligência de saber qual a tela que está sendo exibida no momento, nem quais são os seus componentes. Para tal, utilizei o Appium como driver. Assim, a implementação do teste passou a utilizar uma mescla de comandos do Appium com comandos do Tapsterbot, aonde o Appium é responsável por subir a aplicação, esperar e capturar objetos de tela, e também efetuar digitações de teclado, uma vez que o posicionamento de teclas pode variar de acordo com o layout do teclado. Já o Tapsterbot passa a ser responsável por efetuar ações de clique e drag-and-drop.
A implementação dos comandos do Tapsterbot pode ser feita em classes de PageObjects, aonde as ações de clique do Appium são substituídas pelos métodos do Tapsterbot. Um exemplo abaixo:
@AndroidFindBy(id = "com.vistrav.whiteboard:id/canvas")Por fim, uma implementação do método de teste fica extremamente legível e simples, com poucas linhas:
private RemoteWebElement canvas;
public WhiteboardScreen drawEyesAndMouth() {
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOf(canvas));
tapsterbotService.drawCircle(-20, 10, 6);
tapsterbotService.drawCircle(0, 10, 6);
tapsterbotService.drawArc(-5, 0);
return this;
}
@BeforeEstes e outros exemplos podem ser encontrados no seguinte repositório: https://github.com/sfrubio/tapsterbot
public void setUp() {
driver = getAndroidDriver(device);
indexScreen = new IndexScreen(driver);
whiteboardScreen = new WhiteboardScreen(driver);
}
@Test
public void drawSmile() {
indexScreen.startDrawing();
whiteboardScreen.drawEyesAndMouth();
}
Segue abaixo alguns vídeos do Tapsterbot em ação, testando uma aplicação real:
Pontos de Melhoria
Após algumas execuções, pude observar que a movimentação dos braços é feita de forma linear. Ou seja, não existe algum parâmetro que possa limitar a movimentação dos braços de uma forma mais "suave", o que faz com que Tapsterbot perca sua precisão em algumas execuções. A implementação de funções não-lineares para a movimentação dos braços ajudaria neste sentido.Outro ponto a se considerar é a calibragem dos devices utilizados nos testes. A utilização de devices físicos em testes mobile traz a complexidade do hardware a ser utilizado como fator na sua execução, aonde tamanho e resolução de tela influenciam no resultado. Como o Tapsterbot não tem a inteligência de descobrir o device que está em teste, caberia a um app de calibragem auxiliar a traduzir as coordenadas de tela para coordenadas de movimento dos braços.
Conclusão
A utilização da robótica para a execução de testes em devices físicos, em um primeiro momento, não se mostra tão efetiva quanto a utilização de drivers como Appium, Espresso ou XCUITest. Isso se deve ao fato de não existir um framework dedicado a executar comandos do Tapsterbot, e também por não ter algum software para efetuar a calibragem. Com uma evolução do projeto neste sentido, os primeiros resultados efetivos da utilização do Tapsterbot seriam obtidos. E, é óbvio, quem não gosta de ver um robô físico efetuando testes automatizados?
Links úteis
https://github.com/hugs/tapsterbot/wiki/Getting-Started-With-Tapster
https://www.instructables.com/howto/?sort=none&q=tapsterbot
https://speakerdeck.com/pylapp/why-not-tapster?slide=47
https://www.testdevlab.com/blog/2017/07/how-we-built-a-robot-for-automated-manual-mobile-testing/