• Nenhum resultado encontrado

Teste de Programas de Processamento de Grandes Volumes de Dados

A confiabilidade de programas de processamento de grandes volumes de dados se torna importante dada a grande quantidade de recursos computacionais necessários para que esse tipo de programa possa ser executado, fazendo com que falhas em programas deste tipo possam gerar grandes prejuízos (GARG; SINGLA; JANGRA, 2016). Nesse contexto, o teste de software torna-se uma importante ferramenta no processo de desen- volver programas de processamento de grande volumes de dados com maior qualidade e com menor propensão a falhar em produção. Os estudos apresentados em (CAMARGO; VERGILIO, 2013b) e (MORÁN; RIVA; TUYA, 2019) mostram que trabalhos sobre teste nesse contexto têm despertado interesse nos últimos anos, mas também revelam que pou- cas técnicas sistemáticas e ferramentas foram desenvolvidas até o momento e que, em sua maioria, não atingiram um certo nível de maturidade. Além disso, a maioria dos traba- lhos existentes tem se concentrado em programas que seguem exclusivamente o modelo MapReduce (MORÁN; RIVA; TUYA, 2019), evidenciando que o teste de programas de processamento de grandes volumes de dados ainda é uma área de pesquisa em aberto. Nessa seção apresentamos o estado da arte do teste funcional de programas de processa- mento de grandes volumes de dados.

A revisão sistemática apresentada em (MORÁN; RIVA; TUYA, 2019) identificou 54 trabalhos relacionados ao processo de validação e verificação de programas MapRe- duce. Esse estudo revelou que a maioria dos esforços na área são focados no desempenho de execução do programa, identificando 32 (59%) trabalhos relacionados com teste de desempenho, enquanto que apenas 12 (22%) trabalhos são focados no teste funcional, o que evidencia a lacuna existente na área. A seguir vamos apresentar os principais traba- lhos que buscam verificar o comportamento funcional de programas de processamento de grandes volumes de dados.

2.3.1

Teste de Programas MapReduce

O trabalho apresentado em (CSALLNER; FEGARAS; LI, 2011) é focado em verificar a comutatividade das operações de redução de programas MapReduce. Nele, os autores utilizam uma técnica de execução simbólica para procurar defeitos e gerar casos de teste. A técnica consiste em extrair do programa expressões algébricas que representam as condições que levam o programa a diferentes caminhos de execução. A partir disso, são derivados caminhos de execução codificados com condições de correção (que verificam a comutatividade). Então, um solucionador de restrições é utilizado para inferir valores de entrada que violam as condições de correção. Esses valores são, então, convertidos em casos de teste para o programa. Os autores apresentam uma implementação da sua técnica para programas MapReduce no sistema Hadoop. Uma abordagem similar foi aplicada em (LI et al., 2013) para testar programas Pig Latin (OLSTON et al., 2008), uma linguagem de script para programas de processamento de dados que são executados no Hadoop. Os autores expandem a técnica apresentada em (CSALLNER; FEGARAS; LI, 2011) para extrair caminhos de teste explorando as diferentes operações do Pig Latin. Em (XU et al., 2013) é apresentada uma técnica que testa propriedades em ope- rações de programas de fluxo de dados com a linguagem SPL (HIRZEL et al., 2013), uma linguagem para processamento de fluxo contínuo de dados (stream processing). Os auto- res buscam verificar propriedades que são importantes para a confiabilidade e otimização desse tipo de programa, que são: não-determinismo, seletividade, bloqueio (blocking), statefulness, não-comutatividade e interferência de partição (partition-interference). A técnica utiliza geração aleatória de dados para verificar de forma dinâmica (com execu- ção) se essas propriedades são verificadas ou não nas operações.

Em (MORÁN; RIVA; TUYA, 2014) os autores apresentam o MRTree, uma clas- sificação hierárquica de defeitos em programas MapReduce. Os defeitos apresentados na classificação são divididos em defeitos relacionados a operação de redução (Reduce) e sua etapa intermediária de combinação (Combine3), como, por exemplo, o defeito da operação não ser comutativa e poder gerar resultados diferentes caso os dados sejam processados em ordens diferentes, e defeitos relacionados com os dados de chave/valor, como incon- sistências entre a chave e o valor ou a emissão de um par chave/valor incorreto. Para cada defeito, os autores propõem diretivas de teste ad-hoc para mitigá-los. O mesmo grupo de pesquisa apresenta em (MORÁN; RIVA; TUYA, 2015) o MRFlow, uma técnica que deriva um grafo de fluxo de dados das operações de mapeamento (Map) e redução (Reduce) e a partir desse grafo são gerados casos de teste com a utilização de técnicas de

3 A operação de combinação (Combine) é uma operação intermediária que pode ser executada após uma

operação de mapeamento (Map) como uma forma de pré-processar e reduzir a quantidade de dados que serão processados com a operação de redução (Reduce) no modelo MapReduce. Essa operação não é obrigatória e, além disso, mesmo que tenha sido definida pelo programador não é garantido que ela será executada (HADOOP, 2019).

teste baseado em grafos (AMMANN; OFFUTT, 2017). Os autores não apresentam uma ferramenta para dar suporte a sua técnica.

O método apresentado em (MATTOS, 2011) faz uso de técnicas de busca meta- heurística para gerar dados de teste de forma dinâmica. O autor avaliou dois algoritmos, o algoritmo genético e o algoritmo bacteriológico e concluiu que este último gerava dados de teste melhores. Para avaliar o seu trabalho, o autor aplicou o teste de mutação com três operadores de mutação que ele propôs para o MapReduce, um operador que insere uma operação Combine com o mesmo comportamento da operação Reduce, quando ela não tiver sido definida, um operador que remove o Combine e um operador que altera o número de processos que executam o Reduce. Esses operadores procuram simular defeitos semânticos em relação ao entendimento do modelo MapReduce. O autor conclui que o algoritmo bacteriológico apresenta bom desempenho na geração de dados de teste e que pode contribuir para a identificação de defeitos funcionais, mas que não contribuiu para a identificação de defeitos relacionados com o mau entendimento do modelo MapReduce. Em (LI et al., 2015) é apresentado um framework de teste para programas de processamento de grandes volumes de dados que extrai dados de teste a partir de conjuntos de dados reais. O objetivo é extrair um subconjunto de dados de teste a partir do próprio conjunto de dados que será processado, utilizando, para isso, técnicas de particionamento do espaço de entrada (AMMANN; OFFUTT, 2017). Dessa forma, o framework obtém um subconjunto de dados representativos com base no conjunto de dados original. Esse subconjunto de dados de teste é, então, aplicado no processo de validação do programa sob teste.

2.3.2

Verificação Estática de Programas MapReduce

Alguns trabalhos optaram por fazer a verificação de programas MapReduce sem envolver a execução do programa, como é feito no processo de teste, fazendo uso de métodos formais e análises estáticas. O trabalho apresentado em (CHEN et al., 2015) faz uso de métodos formais para verificar a comutatividade de operações de redução (redutor) de programas MapReduce. Uma vez que esse tipo de programa é executado em um ambiente de computação paralela e distribuída, é importante que operações de agregação sejam comutativas e associativas para que seu resultado seja determinístico, uma vez que não é possível determinar a ordem em que os valores serão processados (CHEN et al., 2017). O método apresentado em (CHEN et al., 2015) extrai do redutor uma série de assertivas e propriedades que devem ser verificadas através de um programa externo, como um verificador de modelo (model checker ), para atestar que a operação de redução é comutativa.

Em (DÖRRE; APEL; LENGAUER, 2011) é proposto um método para análise estática de tipos em programas MapReduce. O objetivo dos autores é identificar incom-

patibilidades de tipos na emissão de pares chave/valor nas operações de mapeamento, combinação e redução do programa. Essa análise estática é feita de forma automática com a ferramenta SNITCH (StatIc Type Checking for Hadoop) proposta pelos autores. Em (ONO et al., 2011) a correção de programas MapReduce é verificada de maneira for- mal utilizando o Coq (BERTOT; CASTRAN, 2010), um provador de teoremas interativo.

2.3.3

Teste de Programas de Fluxo de Dados

Com relação ao teste de programas nos sistemas Apache Spark, DryadLINQ, Apache Beam e Apache Flink, que utilizam um modelo baseado em fluxo de dados, é possível encontrar suporte para a implementação de testes de unidade com bibliotecas externas ou do próprio sistema. As bibliotecas (KARAU, 2015) e (OTTO GROUP, 2016) oferecem uma série de classes utilitárias para o teste de unidade de programas no Apache Spark e Apache Flink, respectivamente, já para o Apache Beam e DryadLINQ é possível encontrar de forma nativa suporte ao teste de unidade. Esse suporte fornece meios para que as entradas do programa possam ser definidas, automatiza a execução do programa e fornece meios para que os resultados do programa possam ser verificados (oráculos de teste). Apesar dessas bibliotecas serem importantes para a implementação e execução dos testes, elas não oferecem suporte para o projeto de casos de teste, que é uma parte crítica no processo de teste.

Com relação ao projeto de casos de teste, o trabalho iniciado em (RIESCO; RODRÍGUEZ-HORTALÁ, 2015) aplicou o teste baseado em propriedades (CLAESSEN; HUGHES, 2000) para testar programas Spark. Essa técnica consiste em gerar dados aleatórios, executar o programa em teste com esses dados de entrada e, após, verificar o comportamento do programa através de oráculos que verificam se os resultados do programa atendem a certas propriedades que foram definidas através de expressões lógicas. O (RIESCO; RODRÍGUEZ-HORTALÁ, 2015) apresentou o sscheck4, uma biblioteca para a aplicação do teste baseado em propriedades em programas Spark. Esse trabalho foi estendido em (RIESCO; RODRÍGUEZ-HORTALÁ, 2016) e (RIESCO; RODRÍGUEZ- HORTALÁ, 2019) para teste de programas de processamento de fluxo contínuo de dados com o Spark Streaming. Os autores aplicaram lógica temporal para permitir a verificação de propriedades relacionados ao tempo, que é uma variável importante no processamento de dados contínuos. Esse trabalho foi adaptado para o Apache Flink em (ESPINOSA et al., 2019).

Além desses trabalhos que aplicam o teste baseado em propriedades em programas Spark e Flink, não identificamos, considerando o limite do nosso conhecimento, outros trabalhos que apresentam técnicas ou ferramentas de teste para programas nos sistemas

4 O sscheck foi implementado como uma extensão do ScalaCheck (NILSSON, 2014), uma implementação

Apache Spark, Apache Flink, Apache Beam ou DryadLINQ. Considerando isso e que os trabalhos apresentados anteriormente tinham como foco principal programas MapReduce, além de que muitos desses trabalhos não apresentam suporte ferramental ou não foram propriamente validados (CAMARGO; VERGILIO, 2013b; MORÁN; RIVA; TUYA, 2019), reforça que a área de teste de programas de processamento de grandes volumes de dados ainda carece de técnicas e ferramentas de teste, principalmente para o teste de programas que seguem um modelo baseado em fluxo de dados.