O primeiro post deve ser o mais difícil pelo tanto que estou sofrendo :') ....Enfim, decidi compartilhar aquilo que sei para que juntos possamos aprender cada vez mais! Esse primeiro post tem por objetivo fazer uma introdução praticamente acadêmica acerca do tema em geral e é um resumo de um dos capítulos do meu TCC.
Espero que gostem!
\O/
Obs: Neste e nos próximos posts colocarei bonitinhas as referências assim que estruturar todas!
Enjoy!
Teste de Software
Com o passar do tempo a tecnologia
da informação se fez cada vez mais presente em diversas atividades humanas,
chegando a se tornar crucial para o
funcionamento de algumas áreas, o que levou se exigir cada vez mais qualidade
dos softwares desenvolvidos [COSTA, 2004]. Sendo assim,a sociedade, atualmente,
depende cada vez mais de sistemas computacionais de qualidade pois seu uso
cresce de forma exponencial nos mais diversos setores desempenhando tarefas
críticas. Se alguns sistemas de uso global deixarem de funcionar,
aproximadamente 40% da população sofrerá as consequências deste problema [REED,
2000]. Entretanto, é possivel afirmar que apesar do quão significativos
softwares são, uma grande parte dos projetos de software não possui uma estrutura
sólida para implementação de métodos que venham a proporcionar a garantia da
qualidade de seu produto final. Em uma pesquisa recente realizada pelo
Ministério da Ciência e Tecnologia, cerca de 10% das empresas entrevistadas
realizam algum teste de software no Brasil [MOLINARI, 2008].
“A qualidade é relativa. O que é
qualidade para uma pessoa pode ser falta de qualidade para outra (G.
Weinberg)”. Embora o conceito de qualidade aparente ser intuitivo, ao
analisá-lo conclui-se que, na verdade, é complexo e defini-lo não é uma tarefa
fácil. Segundo [CROSBY ,1992] a qualidade é a conformidade aos requisitos, um
conjunto de características a serem satisfeitas em um determinado grau, de modo
que o produto de software atenda às necessidades explícitas e implícitas de
seus usuário [ROCHA, 1994]. Conforme a
ISO 9003-3-1991, qualidade é a totalidade de características e funções de um produtos ou serviço que habilitem a
satisfação de necessidades implícitas ou especificadas.Qualidade ainda, segundo
a atual norma brasileira sobre o assunto (NBR ISO 8402), é a totalidade das
características de uma entidade que lhe confere a capacidade de satisfazer às
necessidades explícitas e implícitas. Entretanto, para a obtenção da qualidade
em um produto final é necessária a compreensão de que esta é intimamente ligada
a todo os segmentos do ciclo de desenvolvimento de um software e não somente a
uma fase específica.
[MOLINARI,2008] afirma que existem
três elementos que compõe e sustentam a qualidade de software, sendo estes a
gerência de configuração, a gerência de requisitos e os testes. A gerência de configuração aborda a gerência,
controle e registro dos artefatos que compõe o software, incluindo todo o
histórico de mudança deste. Já a gerência de requisitos trata da gerência, controle
e registro das necessidades do sistema e dos usuários em todos os níveis,
resultando no acompanhamento dos requisitos e suas mudanças. Já o segmento de
teste vai desde o gerenciamento de todo
o planejamento, controle e até a execução dos mesmos.
Somente a existência de testes no
processo de desenvolvimento de um
software não é capaz de creditar a este a característica qualidade, entretanto pode auxiliar no processo de controlá-la e garanti-la,
aumentando o grau de confiabilidade do sistema. Segundo [HAROLD, 2000] o processo de teste é executado para dar
a garantia de qualidade ao produto de
software e é a mais popular estratégia de gerenciamento de risco [MOLINARI,2008].
Este procedimento faz-se necessário pois o desenvolvimento de sistemas de
software envolvem uma série de atividades de produção em que oportunidades para
injetar a faliabilidade humana são enormes.
[DEUTSCH, 1979] afirma que erros podem vir a ocorrer até no início do
processo de desenvolvimento onde os
objetivos podem ser erroneamente ou imperfeitamente especificados, bem como
em estágios posteriores de projeto e
desenvolvimento por causa da inabilidade humana de realizar e comunicar com
imperfeição.
“Se eu tivesse oito horas para
derrubar uma árvore, passaria seis afiando o meu machado. " Abraham
Lincoln, esta frase pode representar uma
analogia ao processo de testes, uma vez esta atividade é uma das mais onerosas
do processo de produção de um software. Estudos indicam que testes podem vir a
consumir mais de 50% do custo de desenvolvimento de um software [HAROLD, 2000].
A rigor o teste de software que envolve vidas (por exemplo, controle de tráfego
aéreo, monitoramento de reatores nucleares) pode custar de três a cinco vezes
mais do que todos os outros passos de engenharia de software combinados
[PRESSMAN, 2002]. Segundo um estudo realizado pelo National Institute of
Stanandarts and Tecnology (NIST) durante o ano de 2002, somente no Estados
Unidos, perdas causadas por erros em sistemas somaram cerca de U$ 59.5 bilhões de dólares, este estudo aponta ainda que o investimento na melhoria da
infra-estrutura para a área de testes geraria uma economia de U$ 22 bilhões ao
país.
A figura 1 representa um gráfico de
custo médio de um erro por etapas do processo de desenvolvimento. Ela
representa o ciclo de custo de um defeito, demonstrando que ele cresce em uma
proporção média de 10 vezes a cada etapa de desenvolvimento. Sendo assim um
erro encontrado na especificação tem seu custo em 10 centavos de dólar para ser
corrigido. Já para o caso do mesmo erro ser esquecido e ser detectado na fase
de implantação o custo seria de 100 dólares (BARTIÉ, 2002).
Fonte: Bartie Alexandre (2002)
Figura 1. Custo médio de um erro em Dólar
Atividades de teste devem ser
cuidadosamente planejadas para fornecer um nível adequado de confiabilidade,
atingir aos requisitos, dentro das condições especificadas, contribuindo para
qualidade de software, já que testes bem planejados são capazes de remover 60%
dos defeitos de um programa [BOEHM e BASILI, 2001], isto aplica-se também ao
fato de que um bom teste não é redundante. Na prática não se pode garantir que
um software é perfeito, devido principalmente a complexidade envolvida em sua
construção, entretanto a não ou má
execução deste processo em alguns projetos além de custos altíssimos podem
acarretar em graves acidentes pondo em risco vidas humanas. Em novembro de 2000
no Instituto Nacional do Cancro da Cidade do Panamá, ao menos oito pacientes
morreram e outros 20 foram afetados devido a uma falha no software de controle
da máquina de raios, havia um erro no
cálculo na dose de radiação que um paciente deveria receber durante uma terapia
radiológica. Um exemplo de fracasso de um projeto de orçamento astronômico,
avaliado em U$ 300 milhões, ocorreu em 3
de dezembro de 1999, quando a sonda da NASA Mars Polar Lander desapareceu
na tentativa de um pouso em Marte. O motivo da falha foi um bit inesperado no
conjunto de instruções do programa que ocasionou um problema na “cama de pouso”
da sonda [MOLINARI, 2008].
Testes de software são elementos
críticos da garantia de qualidade de software e representam uma revisão final
da especificação, projeto e geração de código [PRESSMAN, 2002]. A definição
clássica de teste de software foi dada por Myers em 1979 em um dos primeiros
trabalhos a estudar a fundo esta atividade, caracterizando-se como o processo
de executar o programa com a intenção de encontrar erros, partindo da premissa
de que se o objetivo dos testes fossem somente provar a boa funcionalidade de
um aplicativo seriam encontrados menos defeitos em relação a outra frente de
pensamento, uma vez que toda a energia do processo de testes seria direcionada
apenas na comprovação deste fato
[BARTIÉ, 2002]. Conforme [DIJKSTRA et
al, 1972], os testes podem mostrar apenas a presença de erros e não a sua
ausência. Logo, a atividade de teste demonstra que as funções do software estão
sendo executadas de acordo com as especificações, que os requisitos de
desempenho foram cumpridos e que, por conseqüência, as informações geradas por
ele são confiáveis.
Afirma [NEVES, 1999] que os testes
tem por objetivo no início de cada fase do ciclo de desenvolvimento de um
software, verificar se aquela etapa corresponde exatamente aos requisitos e
definições da fase imediatamente anterior, para assim garantir que o produto
encomendado e o gerado pela atividade de desenvolvimento do software sejam os
mesmos, através dos diversos níveis de refinamento. A finalidade dos testes é
expor defeitos latentes em um software antes de este ser entregue [SOMMERVILLE,
2003], consistindo em atividades que devem verificar se não existem erros na
lógica no código ou de projeto, no fluxo de dados, na compreensão dos
requisitos, no desempenho do sistema, na integração do sistema com outros
componentes de software e hardware, para posteriormente interferir na presença
do erro.
Desta forma, segundo [KOSCIANSKI,
2006], quando a atividade de testes é
planejada de maneira sistemática e rigorosa, pode ser utilizada como um dos
parâmetros para estimar a confiabilidade e qualidade do software construído,
testes servem em si, para aumentar o grau de confiança de que se esta
construindo um produto com o comportamento desejado.Um bom caso de teste é
aquele que tem uma elevada probabilidade de descobrir um erro e um teste bem
sucedido é aquele que revela um erro ainda não descoberto. Conforme [LEWIS, 2004],o teste "É uma estratégia popular para o
gerenciamento de risco". O teste de software é usado para verificar que
requisitos funcionais e não-funcionais foram devidamente implementados.
Pyhäjärvi e Rautiainen (2004) mencionam que Testes de Software também representa uma importante ferramenta
na busca pela satisfação do cliente – um dos principais objetivos das pesquisas
em sistemas de informação e pela melhoria do processo de desenvolvimento.
Como em qualquer outra fase do ciclo de
desenvolvimento de um software, a fase de testes requer certos cuidados em
relação à compreensão de seus princípios básicos antes de sua aplicação de
fato. Segundo [MYERS, 1979] a tarefa de testar um software é extremamente
criativa e intelectualmente desafiadora, portanto sugeriu princípios para
condicionar a acrescentar sustentabilidade ao projeto de teste e execução
destes, são elas: o programador deve evitar de testar seu próprio programa,
deve-se inspecionar completamente os resultados de cada teste. A probabilidade
da existência de mais erros em uma seção de um programa é proporcional ao
número de erros já encontrados naquela seção, não se deve planejar nenhum caso
de teste sob a suposição de que nenhum erro será encontrado e que uma parte
extremamente necessária de um caso de teste é a definição de uma saída ou
resultado esperado. [PRESSMAN, 2002] acrescenta outros seis princípios, sendo
estes: [1] todos os testes devem ser relacionados aos requisitos do cliente,
[2] os testes devem ser planejados muito antes do início do teste, [3] o
princípio de Pareto se aplica ao teste de software, [4] teste completo não é
possível, [5] o teste começa em nível de componente e prossegue “para fora”,
[6] o teste e a depuração são atividades diferentes entretanto a depuração deve
ser acomodada em qualquer estratégia de teste.
Conforme Crespo et al as dificuldades
em se testar um software pode ser descrito da
seguinte maneira:
Devido a algumas características próprias do software como flexibilidade para mudanças, complexidade e intangibilidade, o teste não é uma tarefa trivial. A dificuldade em testar software é caracterizada por alguns pontos importantes como: o teste de software é um processo caro; existe uma falta de conhecimento sobre a relação custo/benefício do teste; há falta de profissionais especializados na área de teste; existem dificuldades em implantar um processo de teste; há o desconhecimento de um procedimento de teste adequado; há o desconhecimento de técnicas de teste adequadas; há o desconhecimento sobre como planejar a atividade de teste; e finalmente, a preocupação com a atividade de teste somente na fase final do projeto.(2004).
Entretanto, a medida que é reduzida
a complexidade da atividade de teste seu custo tende a diminuir. Sendo assim,
no momento em que componentes que agregam características que tornam um
software mais facilmente testável são utilizados seu grau de testabilidade
evolui. A testabilidade consiste na facilidade em que um programa tem de ser
testado. Segundo a [IEE,1990], a testabilidade fornece o grau de dificuldade
que será encontrado para detectar o defeito, refere-se a quanto esforço será
necessário para cada teste e se o software apresenta suas falhas no momento em
que são inseridas as entradas de teste, caracterizando-se como um programa com
alta testabilidade. Do modo contrário ocorre um software com baixa
testabilidade possuindo tendencia a ocultas as falhas que deveriam ser
detectadas durante os testes.
As seguintes características levam a
um software testável e devem ser levadas em conta quando ele é construído
[ZADROSNY,2006],[PRESSMAN,2002]:
● Operabilidade: o software deve ser projetado e
implementado com qualidade. ”Quanto melhor funciona, mais eficientemente pode ser usado e testado”.
● Observabilidade: variáveis devem ser visíveis ou
consultáveis durante a execução. “O que você vê é o que você testa.”
● Controlabilidade: variáveis devem poder ser
controladas diretamente pelo engenheiro de teste. ”Quanto mais você pode
controlar o software, mais o teste pode ser automatizado e otimizado”.
●Decomponibilidade: módulos independentes podem ser
testados independentemente. ”Controlando o escopo do teste, podemos isolar
problemas mais rapidamente e realizar retestagem mais racionalmente”.
● Simplicidade: o conjunto de características deve
ser o mínimo necessário para atender os requisitos. ”Quanto menos há a testar,
mais rapidamente podemos testá-lo”.
● Estabilidade: o software se recupera bem de
falhas. ”Quanto menos modificações, menos interrupções no teste”.
● Compreensibilidade: a documentação técnica é acessível
instantaneamente, bem organizada, específica, detalhada e precisa.”Quanto mais
documentação temos, mais racionalmente vamos testar”.
Conforme [ CRESPO et al,2004]
e [KOSCIANSKI, 2006] existem, basicamente
duas técnicas de teste para qualquer produto que passa por engenharia.
Sendo uma delas o teste estrutural
também conhecido como teste de caixa-branca, que caracteriza-se por ser uma
técnica de teste que adota critérios para a geração dos casos de teste com a
finalidade de identificar defeitos nas estruturas internas do software, através
de situações que exercitem adequadamente todas as estruturas utilizadas na
codificação. Nesta técnica , o conhecimento interno de um produto oferece
informações para testar se todas as operações internas estão sendo realizadas
conforme as especificações e se todos os componentes internos estão sendo
exercitados corretamente [PRESSMAN, 2002]. Já a segunda forma, chamada de teste funcional também conhecida como teste de caixa preta, é
técnica de teste que adota critérios para a geração dos casos de teste com a
finalidade de garantir que os requisitos do software que foi construído sejam
plenamente atendidos. Desta maneira, o conhecimento da função para que o
produto foi projetado para efetuar oferece informações para realização de
testes que demonstrem que cada função está plenamente operacional, ao mesmo
tempo em que erros são procurados em cada uma das funções, conforme critérios
[PRESSMAN, 2002].
A visão do objeto a ser testado
afeta no modo em que os testes serão realizados, [PFLEEGER, 2004] complementa
que se o objeto for visto de uma
perspectiva externa, o teste consistirá em alimentar o objeto com
entradas e observar se as saídas correspondem com o esperado, e ao se observar
o objeto a ser testado sob uma perspectiva interna, para planejar os casos de testes
será utilizada a estrutura do objeto.
Deve-se levar em consideração também a fase de desenvolvimento em que o teste
será aplicado, já que a técnica de teste direciona a escolha de critérios para
geração de casos de teste que, ao serem executados, vão exercitar os elementos
requeridos pela abordagem do teste. Portanto, para realizar esta atividade de
teste deve-se utilizar técnicas de testes de software bem estabelecidas e estas
devem ser realizadas de forma sistemática. [MYERS, 1979] sugere que uma estratégia
de testes onde sejam combinadas as técnicas de caixa-branca e caixa preta,
sendo os casos de teste estruturais
realizados como complementares aos testes funcionais, já que um número
razoável de técnicas deve ser aplicado a ao teste de software, mas nenhuma
isoladamente.
Segundo [KOSCIANSKI, 2006] os testes
de caixa-branca são projetados em função da estrutura do componente e podem
permitir a verificação mais precisa de comportamento do produto, permitindo ao
testador focar sua atenção nos pontos mais importantes ou delicados do código
de uma maneira mais precisa. Consistindo em uma abordagem de testes em que
estes são derivados do conhecimento da estrutura e da implementação do
software, permitindo uma verificação
mais precisa do produto [SOMMERVILLE, 2003]. Desta forma, os dados de teste são dirigidos para examinar
a lógica do programa, sem interesse nas especificações do mesmo [LEWIS, 2000]. Este teste objetiva
verificar se a estrutura interna da unidade está correta e para isso são
realizados para os caso de teste que
visam percorrer todos os caminhos internos possíveis da unidade, abrangendo
também, a manipulação dos valores dos
atributos, verifica os resultados quando loops são executados até o seu limite
visando identificar os caminhos críticos de cada procedimento, entretanto
percorrer todos os caminhos acaba tornando esta atividade complexa. Os casos de
teste do tipo estrutural devem garantir que todos os caminhos independentes de
um módulo tenham sido exercitados pelo menos uma vez, exercitando todas as
decisões lógicas em seus lados verdadeiro e falso,executando assim todos os ciclos nos seus limites dentro de
seus intervalos operacionais desta forma exercitando as estruturas de dados
internas.
Grafos
de fluxo caracterizam-se como uma
ferramenta de representação baseada em em nodos e arestas que são importantes
ferramentas conceituais. [MYERS, 1979] e [PRESSMAN, 2002] definem que cada
círculo, chamado de nó do grafo de fluxo representa um bloco de comandos que
são executados sequencialmente e cada seta, chamada aresta, arco ou ligação,
indica a transferência de controle entre segmentos e sempre deve terminar em um
nó. A figura 1 apresenta a notação de um grafo de fluxo.
Figura 2 -Notação Grafo de Fluxo
Através deste tipo de ferramenta é
possível aplicar uma estratégia de teste estrutural, denominada teste de
caminho. [SOMMERVILLE, 2003] afirma que este tipo de teste tem por objetivo
exercitar todo caminho distinto ou independente ao longo do código, ao menos
uma vez, em algum teste. Afirma ainda que se todo caminho independente for
executado, logo todas as afirmações do código devem ter sido executadas, e todas
as declarações condicionais testadas para os casos verdadeiros e falsos.
Entretanto, a execução de testes de caminhos para todas as combinações
possíveis torna-se um objetivo impossível, já que há uma quantidade infinita de
possíveis combinações de caminhos em programas com loops, então este
tipo de teste é aplicado somente em caminhos básicos [MYERS, 1979]. Este método
permite definir um conjunto mínimo de caminhos de execução que garante o exercício de cada comando do
programa ao menos uma vez durante a atividade de teste [PRESSMAN, 2002].
Outro exemplo de teste estrutural
seria o teste de unidade que foca os módulos e componentes de um software.
[MYERS, 1979] define este tipo de teste como um processo para testar
subprogramas, individuais ou subrotinas em um programa, com o objetivo testar o
funcionamento deste grupo de funções [SOMMERVILLE, 2003]. Este teste é
realizado para mostrar que a unidade não satisfaz a sua especificação funcional
e/ou que sua estrutura implementada não corresponde com a planejada. Os dados
de teste são derivados conforme uma analise do código de um componente e,
depois são utilizados como entrada para os testes, que são executados e geram
saídas conforme ilustra a figura 3.
Figura 3.Teste unitário.
Quando se faz uso do paradigma de
teste caixa preta, que também pode ser chamado de teste comportamental ou teste
de caixa fechada, se testa o programa sob a perspectiva do usuário, não levando
em consideração sua estrutura interna ou meios de desenvolvimento. Segundo
[SOMMERVILLE, 2003] seu comportamento do software ou parte dele só pode ser
determinado através de estudos de suas entradas e suas respectivas saídas. A
figura 4 é uma abstração desta técnica, e serve para elucidar demais
conceituações sobre o assunto. Este tipo de teste tem como objetivo medir a qualidade funcional
de componentes de um sistema [MOLINARI, 2010], avaliando-os conforme seu
comportamento externo. Quando se realiza um teste funcional está na verdade
confrontando com o que se espera que o sistema vá fazer, ou seja, incluindo
entrada de dados, processamento e resposta. [AGUIAR, 2007] afirma que este é o
único tipo de teste possível para se aplicar no momento em que não se dispões
do código-fonte, e ele é particularmente útil para encontrar problemas, como:
funções incorretas ou omitidas, erros de interface, erros de comportamento ou
desempenho e erros de iniciação [KOSCIANSKI, 2006].
Figura
4. Teste funcional
O teste de caixa-preta basea-se nos
requisitos funcionais do software. Como não há conhecimento sobre a operação
interna do programa, o avaliador se concentra nas funções que o software deve
desempenhar [LOURENÇO, 2011]. A partir da especificação são determinadas as
saídas esperadas para certos conjuntos de entrada de dados.[PEZZÈ, 2008] afirma
que os testes funcionais tipicamente são usados como base para o projeto de
casos de teste, já que estes devem começar como parte do processo de
especificação de requisitos e continuar ao longo de cada nível de projeto e
especificação de interface sendo a única técnica de projeto de teste com uma
aplicabilidade tão ampla. Pode-se afirmar que testes de caixa preta podem ser
aplicadados a qualquer descrição do comportamento de um software, sendo esta
formal, parcial ou até mesmo informal, desde um módulo até abranger todo o
sistema. Este tipo de caso de teste é mais barato para projetar e executar em
relação ao modelo estrutural.
O teste de caixa preta exercita o
programa sob diversas massas de dados preparadas anteriormente para provocar
situações esperadas, validando aquela função ou estimulando a probabilidade de
uma falha ocorrer através de situações mais propícias a esta condição.
[HEINEBERG, 2008] afirma que o processo de teste funcional normalmente envolve
a criação de cenários de testes para o uso na avaliação das funcionalidades da
aplicação, validando se o que foi especificado foi implementado corretamente.
Segundo [SOMMERVILLE, 2003] os testes funcionais são abordagens derivadas das
especificações dos programas ou dos componentes, e possuem características de
caixa-preta. [MYERS, 1979] define os testes funcionais com um processo na
tentativa de encontrar divergências entre requisitos e programa. Conforme
[PFLEEGER,2004] cita os testes relatados anteriormente concentravam-se nos
componentes e integração dos mesmos, a abordagem dos testes funcionais ignora a
estrutura interna do programa e foca seu
objetivo na funcionalidade do sistema, os testes funcionais tem como base os
requisitos funcionais.
Exemplo de um tipo de teste que aborda esta
técnica chamada de particionamento por equivalência, também conhecido por
classes de equivalência, é um método que divide o domínio de entrada de um programa em classes de dados a partir das quais podem ser criados casos de teste. Segundo
[PRESSMAN, 2011] um caso de teste ideal descobre sozinho uma classe de erros
que poderia de outro modo, requerer que fossem executados muitos casos de teste
até que o erro geral aparecesse. O projeto de casos de teste para
particionamento de equivalência é baseado numa avaliação das classes de
equivalência para uma certa condição de entrada, desta forma eliminando os
casos de teste redundantes. Outro exemplo de técnica de teste de caixa preta é
o teste baseado em modelo que faz uso de informações contidas no modelo de
requisitos como base para a geração de casos de teste.Uma abordagem mais realista
para o teste de caixa-preta é escolher um subconjunto de entradas que maximize
a riqueza do teste.
As
atividades de Teste de Software ainda podem ser divididas de acordo com a fase
do desenvolvimento e a abordagem empregada, seja procedimental ou orientada a
objeto (OO), conforme Beizer (1990) e Maldonado e Fabbri (2001). As fases são:
○ Teste
de unidade – aplicado a sub-rotinas e funções (na abordagem procedimental) e a
métodos (na abordagem OO);
○ Teste
de integração – aplicado à relação entre dois ou mais subsistemas (na abordagem
procedimental) e à classe, cluster, componente e subclasse (na abordagem OO); e
○ Teste
de sistema – na abordagem procedimental e na OO, é aplicado para verificação de
se o sistema está de acordo com as especificações.
Este texto apresentou uma visão
geral sobre qualidade e testes de software, caracterizando os objetivos desta
fase e as divisões que permeiam as técnicas de teste . Conclui-se que a área de teste de software vive em constante
transformação, que segue de perto o contínuo crescimento do mercado de
desenvolvimento de software. Na mesma medida em que ocorrem mudanças
tecnológicas na área de desenvolvimento, também se torna necessária uma
adequação das praticas de teste.