• Nenhum resultado encontrado

6.2 Estudo 2: Casos de Teste com Testes Reais do OurBackup

6.2.2 Execução e Resultados do Segundo Estudo de Caso

O primeiro passo de execução do estudo de caso consistiu em re-executar por diversas vezes os 12 testes do OurBackup na versão utilizando oThreadControl medindo seu tempo médio de espera. Os testes utilizados foram:

T1 - BackupSchedulerTest.testPurgeBackupWithOneVersion T2 - BackupSchedulerTest.testCreateNotSoSimpleBackup T3 - BackupSchedulerTest.testIncrementalOldReplicaRemove T4 - BackupSchedulerTest.testCreateBackupWithNotEnoughSpace T5 - BackupSchedulerTest.testCreateBackupWithoutOneFriend T6 - BackupSchedulerTest.testUpdateBackupWithOneVersion T7 - BackupControllsIntegrationTest.testCreateNotSoSimpleBackup T8 - BackupControllsIntegrationTest.testCreateBackupWithNotEnoughSpace T9 - BackupControllsIntegrationTest.testCreateBackupWithoutOneFriend T10 - BackupControllsIntegrationTest.testUpdateBackupWithOneVersion T11 - BackupControllsIntegrationTest.testPurgeBackupWithOneVersion

6.2 Estudo 2: Casos de Teste com Testes Reais do OurBackup 98

T12 - BackupControllsIntegrationTest.testIncrementalOldReplicaRemove

Para o cálculo do tempo médio de espera na versão comThreadControlforam utili- zadas 10.000 (dez mil) execuções visando obter, com 95% de confiança, um erro menor que 10% nas médias encontradas.

Após calcular esses tempos médios de espera, foram preparadas as versões de tratamento baseadas em atrasos explícitos correspondentes a 80%, 100% e 120% desses tempos. Foi também retirado da versão comThreadControlo código de instrumentação que media os tempos de espera.

Cada uma dessas versões e também a versão atual dos testes (Current Version) foi re- executada 10.000 (dez mil) vezes em uma máquina isolada da rede e sem carga a ela subme- tida. A intenção das re-execuções era identificar testes que falhavam, procurando classificar tais falhas. Um trabalho futuro interessante é também investigar com essa versão as falhas que ocorriam quando a máquina era submetida a carga.

Para realizar a classificação entre os tipos de falhas em testes, depurou-se o código do OurBackup junto com a equipe de desenvolvimento, considerando os testes que falhavam e foram identificadas as mensagens características de falhas por tempo e que apareciam nos logs de teste e também as mensagens dos logs que eram comuns quando o problema previa- mente conhecido (known bug) se manifestava.

O objetivo principal da classificação era identificar se em alguma das execuções com

ThreadControl(TC) havia alguma falha classificada no grupo das asserções antecipadas e tardias.

Como se propõe que a abordagem Thread Control for Tests seja combinada com abor- dagens que estimulem diferentes escalonamentos durante a execução dos testes, além das 10.000 execuções originais com ThreadControl, foram realizadas outras 10.000 re- execuções, só que deixando a máquina submetida a uma carga constante (rodando-se em paralelo 4 processos do aplicativoburnP6, que gera carga na máquina para efeito de testes de sistema).

Em resumo, foram medidas as quantidades de falhas de execução para as seguintes ver- sões de testes:

6.2 Estudo 2: Casos de Teste com Testes Reais do OurBackup 99

TC carga - Versão com ThreadControl em máquina rodando outros processos

concorrentemente;

Current - Versão corrente dos testes do OurBackup rodando em ambiente dedicado; ED(100%) - Versão utilizando atrasos explícitos (Explicit Delays) de espera corres-

pondente ao tempo médio de espera da versão com ThreadControl e executada em ambiente dedicado;

ED(80%) - Versão utilizando atrasos explícitos (Explicit Delays) de espera correspon-

dente a 80% do tempo médio de espera da versão comThreadControle executada em ambiente dedicado;

ED(120%) - Versão utilizando atrasos explícitos (Explicit Delays) de espera corres-

pondente a 120% do tempo médio de espera da versão comThreadControle exe- cutada em ambiente dedicado.

Seria interessante realizar o estudo de caso utilizando também carga em outras versões, além da TC carca, mas por restrições de tempo, já que esse estudo levou meses de execução, apenas as versões acima foram consideradas no estudo aqui descrito.

Análise

Os dados coletados relativos ao número de falhas de execução para cada um dos 12 testes, considerando cada um dos tratamentos estão mostrados na Tabela 6.4.

Ao considerar a classificação de falhas causadas por asserções antecipadas e tardias, foram obtidos os dados mostrados na Tabela 6.5.

Considerando as falhas dos grupos TC e TC carga, viu-se que nenhuma de suas falhas se enquadraram no grupo das falhas por asserções antecipadas e tardias, enquanto que estas eram bem comuns nas versões com atrasos explícitos e aconteceram em alguns testes da ver- são Current mesmo sem submeter a máquina em que esta estava rodando à nenhuma carga extra. Isso mostra, considerando os dados obtidos, e a análise feita com base nas mensa- gens de erro, que é diferente a quantidade de falhas em testes por asserções antecipadas e tardias quando se usa oThreadControldo que ao usar outras abordagens, o que invalida a hipótese nula investigada por este estudo de caso.

6.2 Estudo 2: Casos de Teste com Testes Reais do OurBackup 100

Tabela 6.4: Número de falhas em testes para cada tratamento considerando 10.000 execuções de cada

Porém, como se pôde ver, as execuções de testes com ThreadControl (com e sem carga) falharam nos testes T2 e T8. Ao executar o código responsável por classificar as falhas de acordo com as mensagens de erro produzidas, para todas essas execuções com falha de T2 apareciam as mensagens comuns em testes que falhavam pelo problema conhecido. Considerando T8, das 108 falhas de TC, 100 se deveram ao problema conhecido e 8 não puderam ser classificadas em nenhum dos 2 grupos. Das 12 falhas de TC carga, 4 foram classificadas como devidas ao problema conhecido e 8 delas se devem a outros motivos não identificados (suas mensagens de erro não se enquadravam nos padrões de mensagens que caracterizavam as asserções antecipadas e tardias e nem nos padrões de mensagens para o defeito conhecido). Até onde se pôde depurar, não se sabe o motivo das falhas atribuídas no grupo de outras falhas e o mais provável é que se refiram à outros defeitos da aplicação ou de suas bibliotecas auxiliares e cuja fonte ainda não havia sido descoberta. O uso de técnicas como replay e de outras ferramentas de apoio ao teste de sistemas multi-threaded poderia ser combinado com o ThreadControl para identificar o motivo de tais falhas nessas situações, algo não trivial, e que ficou apenas como trabalho futuro, para não desviar muito o foco desta tese para a depuração de problemas no sistema e que eram de difícil reprodução.

6.2 Estudo 2: Casos de Teste com Testes Reais do OurBackup 101

Tabela 6.5: Número de falhas classificadas como falhas causadas por asserções antecipadas e tardias para cada tratamento considerando 10.000 execuções de cada

total das faltas na aplicação, que nenhuma das falhas encontradas se deve de fato a asserções antecipadas e tardias, ele serviu para dar indícios de que com testes reais tais tipos de falhas não puderam ser encontradas quando o arcabouço de testes ThreadControl foi utilizado, já que nenhuma das falhas encontradas foi classificada neste grupo considerando as mensagens de logs. No entanto, mais testes devem ser feitos com o arcabouço e experimentos semelhan- tes aos estudos de caso feitos devem ser repetidos em outros sistemas e em testes sintéticos onde se tenha um maior controle sobre as faltas existentes na aplicação sendo testada. Além disso, é importante também evoluir o arcabouço e utilizar ferramentas adicionais para o teste de sistemas concorrentes, como técnicas de replay, como forma de validá-lo.

Outra observação importante resultante do estudo é que dependendo da abordagem utili- zada para esperar antes das asserções, pode-se obter falhas em um teste porque as verifica- ções não são feitas em um tempo apropriado. Essa conclusão pôde ser tomada observando o código exercitado nos testes e também fazendo um paralelo entre o tempo de espera utili- zado e o número de falhas na versão ExplicitDelaysVersion, que aumentava à medida que se diminuía o intervalo de espera desta versão. No entanto, a prática de aumentar o tempo de

6.2 Estudo 2: Casos de Teste com Testes Reais do OurBackup 102

espera não garante que os testes irão passar em máquinas diferentes e pode levar a asserções tardias, feitas depois que o estado esperado foi alcançado mas já se alterou.

Uma outra conclusão que pôde ser tirada desse segundo estudo de caso foi que até onde foi visto, a abordagem Thread Control for Tests foi capaz de evitar falhas nos testes do OurBackup que não eram causadas por defeitos na aplicação. Esse fato era esperado, observando-se a implementação do arcabouço, mas o estudo de caso foi importante para dar uma idéia de seu uso em casos práticos. Foi percebido que ao usar outras abordagens tais falhas aconteciam e sua frequência dependia de intervalos de espera escolhidos pelos testadores. Quando se aumenta muito os intervalos escolhidos, além de fazer com que os testes demorem mais, os desenvolvedores podem abandonar alguns dos testes ou raramente executá-los, até mesmo se estes forem os únicos a exercitar o sistema de uma maneira parti- cular.

Observou-se também, através desse estudo de caso que o uso do arcabouço de teste pro- posto poderia auxiliar desenvolvedores de teste. Ao usar este arcabouço, evitou-se que os desenvolvedores tivessem que prever tempos de espera apropriados a utilizar.

Embora trazendo tais benefícios, é importante perceber que a abordagem Thread Con-

trol for Tests também apresenta algumas limitações. Uma delas está relacionada ao fato de

que monitorar threads afeta a maneira em que as mesmas são escalonadas (thread interlea-

vings). Isso pode diminuir as chances de que um determinado escalonamento problemático

seja exercitado. Para evitar isso, técnicas e ferramentas para gerar diferentes escalonamen- tos [90][20] devem ser usadas em conjunto com a abordagem proposta neste trabalho. Isso foi investigado nesse trabalho e as conclusões parciais estão reportadas no Capítulo 8. Uma outra desvantagem da abordagem aqui proposta é que ela não é tão simples de implementar quanto atrasos explícitos. No entanto, acredita-se que este esforço é compensado pelo fato de se evitar falhas em testes devidas a asserções feitas em momentos inadequados, o que leva a testes mais confiáveis. Porém, caso se faça uma preparação da ferramenta de apoio a tes- tes da abordagem já adicionando-lhe bibliotecas que ofereçam operações específicas para a aplicação sendo testada, com cenários de espera comuns, por exemplo, tal esforço adicional por parte dos desenvolvedores de testes é minimizado.

6.3 Conclusões Parciais 103

6.3

Conclusões Parciais

Neste capítulo foram apresentadas algumas avaliações iniciais da abordagem utilizando o arcabouço ThreadControl em estudos de caso com o intuito de demonstrar que a abordagem é aplicável na prática.

De maneira geral, as avaliações feitas deram indícios de que o uso da abordagem pro- posta através do arcabouço ThreadControl tem conseguido evitar falhas em testes devidas a asserções feitas cedo ou tarde demais. O segundo estudo feito reforçou a necessidade de combinar a abordagem proposta com ferramentas para auxiliar na detecção de defeitos de concorrência e para tentar evitar o efeito de monitoração causado por esta. Um estudo inicial do uso combinado da abordagem com ferramentas desta natureza é apresentado no Capítulo 8.

Como forma de fortalecer a avaliação da abordagem Thread Control for Tests apresen- tada neste capítulo, o Capítulo 7 apresenta uma outra avaliação feita só que sem utilizar o arcabouçoThreadControlem si, mas apenas suas idéias por meio de um modelo utili- zando a linguagem TLA+, o que permite que este possa ser verificado e com que possam ser feitas simulações neste modelo.

Capítulo 7

Avaliação da Abordagem Thread Control

for Tests usando TLA+

No Capítulo 4 foi modelado o problema das asserções antecipadas e tardias. Naquele capí- tulo, demonstrou-se que quando as threads do sistema sob teste não são monitoradas durante a execução dos testes, não se pode garantir que uma asserção antecipada ou tardia não irá ocorrer.

Na Seção 4.2 mostrou-se que quando certas regras de causalidade são consideradas como restrições na execução de testes de um sistema, pode-se garantir que todas as execuções de teste equivalentes a uma execução de teste correta serão também corretas, o que significa que suas asserções não serão executadas em um momento não apropriado.

No Capítulo 5 foi apresentada a abordagem Thread Control for Tests. Através de um mapeamento entre esta abordagem e a solução modelada formalmente para evitar testes com falsos positivos por asserções antecipadas e tardias, obteve-se alguns indícios de que ela poderia evitar tal problema, mas isso não pôde ser provado formalmente.

Neste capítulo, será apresentada a validação da abordagem previamente apresentada de maneira formal, utilizando um modelo que possa ser verificado através de suporte ferramen- tal e mais próximo de implementações reais de testes em que não ocorrem os problemas das asserções feitas em momentos inapropriados. Para esta validação, utilizou-se a lingua- gem TLA+ [58] para modelar testes sem monitoração de threads e testes com monitoração e controle de threads seguindo o que é apresentado na abordagem Thread Control for Tests e também as idéias da sua ferramenta de suporte ThreadControl.

7.1 Motivação para usar TLA+ 105

O intuito deste capítulo é demonstrar que testes que utilizem essa abordagem não apre- sentam o problema das asserções antecipadas e tardias.

Para isso, apresenta-se inicialmente a motivação para se utilizar a linguagem de especi- ficação TLA+ e posteriormente são descritas especificações de execuções de teste utilizando essa linguagem. A seguir são mostradas as verificações automáticas feitas nos modelos espe- cificados no intuito de verificar estados alcançáveis em cada um dos modelos para se identifi- car se no modelo que representa o uso da abordagem Thread Control for Tests algum desses estados caracteriza um estado de asserções antecipadas ou tardias. Por fim, investiga-se também utilizando uma ferramenta de apoio da linguagem TLA+ se são verificados compor- tamentos (sequências de estado das threads) caracterizando asserções antecipadas ou tardias em simulações deste modelo.

7.1

Motivação para usar TLA+

A Lógica Temporal de Ações (Temporal Logic of Actions - TLA) é uma lógica para especi- ficar e raciocinar a respeito de sistemas concorrentes [57]. Esta lógica é a base para TLA+, uma linguagem completa de especificação.

A idéia principal de TLA+ é tornar prática a descrição de um sistema usando uma única fórmula. Nesse trabalho, TLA+ foi usada para preparar três especificações básicas: a) uma representando uma execução de testes sem monitoração de threads (mostrada no Apên- dice A); b) uma outra representando uma execução de teste em que as threads são moni- toradas de acordo com a abordagem Thread Control for Tests (mostrada no Apêndice B) e considerando uma invariante representando a ausência de asserções antecipadas e tardias nas possíveis execuções de teste; c) uma terceira, estendendo a primeira (a que não usa a abordagem Thread Control for Tests), mas também considerando a verificação da ausência de asserções antecipadas e tardias em testes.

A linguagem TLA+ foi usada porque ela se mostrou ser mais próxima do modelo geral apresentado nas seções 4.1 e 4.2 e também porque existem ferramentas de suporte para a linguagem TLA+ que permitem a verificação de especificações preparadas utilizando essa linguagem e também a checagem de modelos. Nesse trabalho, três dessas ferramentas foram utilizadas: [59]:

7.1 Motivação para usar TLA+ 106

TLATeX, um programa para composição tipográfica (typesetting) de especificações

TLA+ (e que foi utilizada para produzir os modelos mostrados nos Apêncides A, B e C)

O Syntactic Analyzer, um parser e verificador de sintaxe de especificações TLA+, e

TLC, um verificador de modelos e simulador para uma subclasse de especificações

TLA+ “executáveis”.

Na Lógica Temporal de Ações, em que se baseia TLA+, algoritmos são representados com fórmulas [59]. Fórmulas na Lógica de Ações são construídas usando: Valores, Variá- veis, Estados, Funções de Estado, e Ações. Um estado (state) é uma atribuição de valores a variáveis. Uma ação (action) é uma expressão de valor booleano consistindo de variáveis, variáveis denominadas primed (representam o novo valor da variável após um certo passo da execução) e símbolos constantes.

De maneira geral, a Lógica Temporal (Temporal Logic (TL)) é usada para descrever com- portamento dinâmico (sequências infinitas de estados) de programas. TL é usada para for- mular propriedades de programas. TL também permite que se raciocine a respeito de uma sequência de estados. Uma fórmula temporal é construída de fórmulas elementares usando operadores booleanos e os operadores unários  (sempre - always) e ♦ (eventualmente -

eventually).

Em TLA+, especifica-se um sistema indicando-se comportamentos possíveis – aqueles representando uma execução correta do sistema. Formalmente, um comportamento (beha-

vior) é definido como sendo uma sequência de estados (states), onde um estado é definido

como sendo uma atribuição de valores a variáveis [58]. Um par de estados sucessivos é chamado de um passo (step). Passos que deixam uma variável sem modificação são deno- minados stuttering steps ou passos “gagos”. Uma execução de um programa é representada por um comportamento consistindo na sequência de estados assumidos [59].

Um programa Π é descrito por quatro itens:

1. Uma coleção de variáveis de estado

2. Um predicado de estado Init especificando o estado inicial