TDD – Test Drive Development

Publicidade

 

Aviso 

Este artigo é uma compilação de informações coletadas na Internet e em livros com o intuito de resolver questões para concurso. Como o material foi criado em 2015, pode estar desatualizado. 

Uma pesquisa do Departamento de Comércio dos EUA, publicada em 2002, revelou que falhas de software são tão comuns e tão danosas que se estima que causem um prejuízo anual de mais de 60 bilhões de dólares para a economia americana. O estudo também alega que, embora não seja possível remover todos os erros, mais de um terço destes custos poderia ser eliminado caso se utilizasse uma infraestrutura de testes melhor, que permitisse identificar e remover defeitos mais cedo e de forma mais eficaz. Atualmente, calcula-se que cerca de 50% dos defeitos são encontrados apenas nas fases finais dos projetos, ou após os sistemas começarem a ser utilizados em produção. 

Test-Driven Development (TDD) ou Desenvolvimento Orientado a Testes é uma maneira diferente de escrever software. A diferença entre esta abordagem e a que você provavelmente está acostumado é que com TDD você vai evoluindo seu código aos poucos, conforme vai explorando o problema com o uso de testes automatizados escritos antes da solução sequer existir. 


Algumas vantagens desta abordagem são: 


Incentiva a simplicidade: como a solução vai surgindo pouco a pouco, a tendência é que não se perca tempo com aquilo que não tem certeza que será usado em seguida. Expressões como “You Ain’t Gonna Need It (YAGNI)” e “Keep It Simple, Stupid (KISS)” são recorrentes quando se está programando orientado a testes. 


Aumenta a confiança no código: o sistema funciona de uma determinada maneira porque existem testes que foram utilizados durante sua criação e validam o que foi criado. E se ainda assim algum erro surgir, um novo teste é criado para reproduzi-lo e garantir que depois de solucionado ele não irá se repetir. 


Ajuda como documentação: os testes quando bem definidos são mais simples de ler que o código e, embora nem sempre sirvam como uma especificação para o usuário final, eles são uma fonte eficiente para entender o que o software faz. Além disso, esta documentação sempre estará atualizada com a aplicação. 


Facilita refactorings: quanto mais testes existem no sistema, maior é a segurança para fazer refactorings. Um erro causado por algum refactoring dificilmente vai passar desapercebido quando um ou mais testes falharem após a mudança. 


Em TDD, um teste é um pedaço de software. A diferença entre teste e o código que está sendo produzido é que os testes têm 2 funções principais: 


  • De especificação, ou seja, definir uma regra que seu software deve obedecer; 

  • De validação, ou seja, verificar se uma determinada regra é obedecida pelo software. 


Geralmente os testes são criados com algum framework do tipo xUnit (jUnit, nUnit Test::Unit etc) , mas também podem ser feitos num nível de funcionalidades (através de softwares como o FitNesse e Selenium). Estas ferramentas servem basicamente para organizar os testes e facilitar na criação das verificações.

 

Test Driven Development (TDD) ou em português Desenvolvimento Dirigido por testes (Desenvolvimento Baseado em Testes) é uma técnica de desenvolvimento de software que baseia em um ciclo curto de repetições: Primeiramente o desenvolvedor escreve um caso de teste automatizado que define uma melhoria desejada ou uma nova funcionalidade. Então, é produzido código que possa ser validado pelo teste para posteriormente o código ser refatorado para um código sob padrões aceitáveis. Kent Beck, considerado o criador ou o "descobridor" da técnica, declarou em 2003 que TDD encoraja designs de código simples e inspira confiança. Desenvolvimento dirigido por testes é relacionado a conceitos de programação de Extreme Programming, iniciado em 1999, mas recentemente tem-se criado maior interesse pela mesma em função de seus próprios ideais. Através de TDD, programadores podem aplicar o conceito de melhorar e depurar código legado desenvolvido a partir de técnicas antigas.


Desenvolvimento dirigido por testes requer dos desenvolvedores criar testes de unidade automatizados que definam requisitos em código antes de escrever o código da aplicação. Os testes contém asserções que podem ser verdadeiras ou falsas. Após as mesmas serem consideradas verdadeiras após sua execução, os testes confirmam o comportamento correto, permitindo os desenvolvedores evoluir e refatorar o código. Desenvolvedores normalmente usam Frameworks de testes, como xUnit e jUnit, para criar e executar automaticamente uma série de casos de teste.


É importante que o código escrito seja apenas projetado para passar o teste específico. Nenhuma outra funcionalidade deve ser prevista ou permitida fora do escopo do teste em nenhum estágio do processo. 

O XP, por exemplo, adota como um elemento-chave a criação de testes unitários antes da codificação começar. 


Ciclo de Desenvolvimento 


 


1. Adicione um teste


Em Test Driven Development, cada nova funcionalidade inicia com a criação de um teste. Este teste precisa inevitavelmente falhar porque ele é escrito antes da funcionalidade a ser implementada (se ele não falha, então a funcionalidade ou melhoria 'proposta' é óbvia). Para escrever um teste, o desenvolvedor precisa claramente entender as especificações e requisitos da funcionalidade. O desenvolvedor pode fazer isso através de casos de uso ou user stories que cubram os requisitos e exceções condicionais. Esta é a diferenciação entre desenvolvimento dirigido a testes entre escrever testes de unidade 'depois' do código desenvolvido. Ele torna o desenvolvedor focado nos requisitos 'antes' do código, que é uma sutil, mas importante diferença. 


2. Execute todos os testes e veja se algum deles falha 


Esse passo valida se todos os testes estão funcionando corretamente e se o novo teste não traz nenhum equívoco, sem requerer nenhum código novo. Pode-se considerar que este passo então testa o próprio teste: ele regula a possibilidade de novo teste passar. 


O novo teste deve então falhar pela razão esperada: a funcionalidade não foi desenvolvida. Isto aumenta a confiança (por outro lado não exatamente a garante) que se está testando a coisa certa, e que o teste somente irá passar nos casos intencionados. 


3. Escrever código 


O próximo passo é escrever código que irá ocasionar ao teste passar. O novo código escrito até esse ponto poderá não ser perfeito e pode, por exemplo, passar no teste de uma forma não elegante. Isso é aceitável porque posteriormente ele será melhorado. 


O importante é que o código escrito deve ser construído somente para passar no teste; nenhuma funcionalidade (muito menos não testada) deve ser predita ou permitida em qualquer ponto. 


4. Execute os testes automatizados e veja-os executarem com sucesso 


Se todos os testes passam agora, o programador pode ficar confiante de que o código possui todos os requisitos testados. Este é um bom ponto que inicia o passo final do ciclo TDD. 


5. Refatorar o código 


Nesse ponto o código pode ser limpo como necessário. Ao reexecutar os testes, o desenvolvedor pode confiar que a refatoração não é um processo danoso a qualquer funcionalidade existente. Um conceito relevante nesse momento é o de remoção de duplicação de código, considerado um importante aspecto ao design de um software. Nesse caso, entretanto, isso aplica remover qualquer duplicação entre código de teste e código de produção — por exemplo, magic numbers or strings que nós repetimos nos testes e no código de produção, de forma que faça o teste passar no passo 3. 


6. Repita tudo 


Iniciando com outro teste, o ciclo é então repetido, empurrando a funcionalidade a frente. O tamanho dos passos deve ser pequeno - tão quanto de 1 a 10 edições de texto entre cada execução de testes. Se novo código não satisfaz rapidamente um novo teste, ou outros testes falham inesperadamente, o programador deve desfazer ou reverter as alterações ao invés do uso de excessiva depuração. A Integração contínua ajuda a prover pontos reversíveis. É importante lembrar que ao usar bibliotecas externas não é interessante gerar incrementos tão pequenos que possam efetivamente testar a biblioteca, a menos que haja alguma razão para acreditar que a biblioteca tenha defeitos ou não seja suficientemente completada com suas funcionalidades de forma a servir às necessidades do programa em que está sendo escrito. 


Estilos de Desenvolvimento 


Há vários aspectos ao usar desenvolvimento dirigido a testes, por exemplo os princípios "Keep It Simple, Stupid" (KISS) e "You Ain`t Gonna Need It" (YAGNI). Focando em escrever código somente para os testes passarem, o design do sistema pode ser mais limpo e claro do que o que é alcançado por outros métodos. Em Test-Driven Developmente By Example Kent Beck sugere o princípio "Fake it, till you make it". Para alcançar altos níveis conceituais de design (como o uso de Design Pattern), tests são escritos de forma que possam gerar o design. O código pode acabar permanecendo mais simples do que o padrão alvo, entretanto ele deve passar em todos os testes requeridos. Isto pode ser inaceitável de primeira mas ele permite o desenvolvedor focar somente no que é importante. 


Falhar primeiro os casos de testes. A ideia é garantir que o teste realmente funciona e consegue capturar um erro. Assim que ele é mostrado, a funcionalidade almejada pode ser implementada. Isto tem sido apontado como o "Test-Driven Mantra", conhecido como vermelho/verde/refatorar onde vermelho significa falhar onde pelo menos uma asserção falha, e verde é passar, que significa que todas as asserções foram verdadeiras. 

Desenvolvimento dirigido a testes constantemente repete os passos de adicionar casos de teste que falham, passando e refatorando-os. Ao receber o resultado esperado em cada estágio reforça ao desenvolvedor o modelo mental do código, aumentando a confiança e incrementando a produtividade. 


Práticas avançadas de desenvolvimento dirigido a testes encaminham para o desenvolvimento dirigido a testes de aceitação (ATDD), onde o critério especificado pelo cliente é automatizado em testes de aceitação, que então levam ao tradicional processo de desenvolvimento dirigido a testes de unidade. Este processo garante que o cliente tem um mecanismo automatizado para decidir como o software atende suas necessidades. Com ATDD, o desenvolvimento em equipe tem objetivo específico para satisfazer, e os testes de aceitação os mantém continuamente focados em o que o cliente realmente deseja daquela funcionalidade. 


Benefícios 


Um estudo de 2005 descobriu que usar TDD significava escrever mais testes, e logo, programadores que escreviam mais testes tendiam a ser mais produtivos. Hipóteses relacionando a qualidade de código e uma correlação direta entre TDD e produtividade foram inconclusivas. 


Desenvolvedores usando TDD puramente em novos projetos reportaram que raramente necessitaram a utilização de um depurador. Usado em junção com um Sistema de controle de versão, quando testes falham inesperadamente, reverter o código para a última versão em que os testes passaram pode ser mais produtivo do que depurar. 


Desenvolvimento dirigido por testes oferece mais do que somente um maneira simples de validação e de correção, pode orientar o design de um programa. Por focar em casos de testes primeiramente, deve-se imaginar como a funcionalidade será usada pelo cliente. Logo, o programador é somente com a interface e não com a implementação. Este benefício é complementar ao Design por Contrato, que através torna os casos de testes muito mais do que asserções matemáticas ou preconcepções. 


O poder que TDD oferece é a habilidade de pegar pequenas partes quando requeridas. Isso permite o desenvolvedor focar como objetivo fazer os testes atuais passarem. Casos excepcionais e tratamento de erros não são considerados inicialmente. Testes que criam estas circunstâncias estranhas são implementadas separadamente. Outra vantagem é que TDD quando usado apropriadamente, garante que todo o código desenvolvido seja coberto por um teste. Isto fornece a equipe de desenvolvimento, e ao usuários, subsequentemente, um grande nível de confiança ao código. 


Enquanto que é verdade que mais código é necessário ao usar TDD do que sem TDD, devido aos códigos de teste, o tempo total de implementação é tipicamente menor. Um grande número de testes ajudam a limitar o número de defeitos no código. A natureza periódica ajuda a capturar defeitos inicialmente no ciclo de desenvolvimento, prevenindo-os de se tornarem grandes e endêmicos problemas. Eliminando defeitos cedo no processo normalmente evita longos e entediantes períodos de depuração posteriores em um projeto.

 

TDD pode encaminhar a um nível que possibilite um código mais modularizado, flexível e extensível. Este efeito surge devido a metodologia requerer que os desenvolvedores pensem no software em pequenas unidades que podem ser reescritas, desenvolvidas e testadas independentemente e integradas depois. Isto implica menores e mais classes, evitando o acoplamento e permitindo interfaces mais limpas. O uso de Mock Object é um contribuidor para a modularização do código, pois este recurso requer que o código seja escrito de forma que possa ser facilmente trocado entre versões Mock, usados em testes de unidade, e "reais", usados na aplicação.

 

Devido a fato de que nenhum código é escrito a não ser para passar em um teste que esteja falhando, testes automatizados tendem a cobrir cada caminho de código. Por exemplo, para que um desenvolvedor possa adicionar um caminho alternativo "senão" em um "se", o desenvolvedor poderia primeiramente escrever um teste que motive o fluxo alternativo. Como resultado, os testes automatizados TDD tendem a ser mais perfeitos: eles irão mostrar qualquer mudança inesperada no comportamento do código. Isto ajuda a identificar problemas cedo que poderiam aparecer ao consertar uma funcionalidade que ao ser modificada inesperadamente altera outra funcionalidade. 


Limitações 


Desenvolvimento dirigido com testes é difícil de usar em situações onde testes totalmente funcionais são requeridos para determinar o sucesso ou falha. Exemplos disso são interfaces de usuários, programas que trabalham com base de dados, e muitos outros que dependem de configurações específicas de rede. TDD encoraja os desenvolvedores a incluir o mínimo de código funcional em módulos e maximizar a lógica, que é extraída em código de teste, usando Fakes mocks para representar o mundo externo.

 

Suporte gerencial é essencial. Se toda a organização não acreditar que TDD é para melhorar o produto, o gerenciamento irá considerar que o tempo gasto escrevendo teste é desperdício.

 

Os próprios testes se tornam parte da manutenção do projeto. Testes mal escritos, por exemplo, que incluem strings de erro embutidas ou aqueles que são susceptíveis a falha, são caros de manter. Há um risco em testes que geram falsas falhas de tenderem a serem ignorados. Assim quando uma falha real ocorre, ela pode não ser detectada. É possível escrever testes de baixa e fácil manutenção, por exemplo pelo reuso das strings de erro, podendo ser o objetivo durante a fase de refatoração descrita acima.

 

O nível de cobertura e detalhamento de teste alcançado durante repetitivos ciclos de TDD não pode ser facilmente recriado em uma data tardia. Com o passar do tempo os testes vão se tornando gradativamente preciosos. Se uma arquitetura pobre, um mal design ou uma estratégia de teste mal feita acarretar em mudança tardia, fazendo com que dezenas de testes falhem, por outro lado eles são individualmente consertáveis. Entretanto, simplesmente deletando, desabilitando ou alterando-os vagamente poderá criar buracos indetectáveis na cobertura de testes.

 

Lacunas inesperadas na cobertura de teste podem existir ou ocorrer por uma série de razões. Talvez um ou mais desenvolvedores em uma equipe não foram submetidos ao uso de TDD e não escrevem testes apropriadamente, talvez muitos conjuntos de testes foram invalidados, excluídos ou desabilitados acidentalmente ou com o intuito de melhorá-los posteriormente. Se isso acontece, a certeza é de que um enorme conjunto de testes TDD serão corrigidos tardiamente e refatorações serão mal acopladas. Alterações podem ser feitas não resultando em falhas, entretanto na verdade bugs estão sendo introduzidos imperceptivelmente, permanecendo indetectáveis.

 

Testes de unidade criados em um ambiente de desenvolvimento dirigido por testes são tipicamente criados pelo desenvolvedor que irá então escrever o código que está sendo testado. Os testes podem consequentemente compartilhar os 'pontos cegos' no código: Se por exemplo, um desenvolvedor não realizar determinadas entradas de parâmetros que precisam ser checadas, muito provavelmente nem o teste nem o código irá verificar essas entradas. Logo, se o desenvolvedor interpreta mal a especificação dos requisitos para o módulo que está sendo desenvolvido, tanto os testes como o código estarão errados.

 

O alto número de testes de unidades pode trazer um falso senso de segurança, resultando em menor nível de atividades de garantia de qualidade, como testes de integração e aceitação.

 

Visibilidade do Código 


O conjunto de teste claramente possibilita acessar o código que está se testando. Por outro lado critérios normais de design como Information Hiding, encapsulamento e separação de conceitos não devem ser comprometidos. Consequentemente teste de unidade são normalmente escritos no mesmo projeto ou módulo que o código está sendo testado.

 

Ao usar design orientado a objetos, este não provê acesso aos métodos e dados privados. Consequentemente, trabalho extra pode ser necessário para testes de unidade. Em Java e outras linguagens, um desenvolvedor pode usar reflexão para acessar campos que são marcados como privados. Alternativamente, uma classe inerente pode ser usada para suportar os testes de unidade, assim tendo visibilidade dos membros e atributos da classe. No .NET e em muitas outras linguagens, classes parciais podem ser usadas para expor métodos privados e dados para os testes acessarem.

 

O importante é que modificações brutas no testes não apareçam no código de produção. Em C# e em outras linguagens, diretivas de pré-compilação como #if DEBUG ... #endif podem ser posicionadas em volta de classes adicionais e realmente prevenir todos os outros códigos relacionados a teste de serem compilados no código de lançamento. Isto então significa que o código lançado não é exatamente o mesmo de quando testado. A execução regular de poucos mais completos testes de integração de aceitação ao final do lançamento do código podem garantir que não existe código de produção que subitamente dependa dos testes. Há muito debate entre os praticantes de TDD, documentados nos seus blogs e outros locais, com a dúvida se é de bom julgamento testar métodos privados e protegidos e dados de qualquer maneira. Muitos argumentam que poderia ser suficiente testar qualquer classe através da interface pública, considerando membros privados como meramente detalhes de implementações que podem mudar, e se deveria ser permitido fazer sem quebrar nenhum teste. Outros dizem que aspectos cruciais de uma funcionalidade podem ser implementados em métodos privados, e que ao fazer desta forma eles são indiretamente testados através da interface pública obscurecendo a ocorrência dos mesmos: Testes de unidade são para testar a menor unidade de funcionalidade possível.

 

Fakes, Mocks e Testes de Integração 


Testes de unidades são assim chamados por cada teste exercitar uma unidade de código. Se um módulo tem centenas de testes de unidade ou somente cinco é irrelevante. Um conjunto de testes em TDD nunca cruza os limites de um programa, nem deixa conexões de rede perdidas. Ao fazer essas ações, o mesmo introduz intervalos de tempo que podem tornar testes lentos ao serem executados, desencorajando desenvolvedores de executar toda a suite de testes. Introduzir dependências de módulos externos ou data transforma teste de unidade em testes de integração. Se um módulo se comporta mal em uma cadeia de módulos inter-relacionados, não fica imediatamente claro onde olhar a causa da falha.

 

Quando o código em desenvolvimento depende confiavelmente de uma base de dados, um serviço web ou qualquer outro processo externo ou serviço, obrigando em um separação unitária de teste é então uma oportunidade forçada de criar um design de código mais modular, mais testável e reusável. Dois passos são necessários:

 

  1. Toda vez que um acesso externo é necessário no design final, uma interface deve ser definida de forma a descrever que acessos irão ser disponíveis. O princípio de inversão de dependência fornece benefícios nessa situação em TDD.

  2.  

  1. A interface deve ser implementada de duas maneiras, uma que realmente acessa o processo externo, e outra que é um fake ou mock. Objetos fake precisam fazer um pouco mais do que adicionar mensagens "Objeto Pessoa salvo" criando registro de rastreio, identificando que asserções podem executadas para verificar o comportamento correto. Mock objects diferem pelo fato que eles mesmos contém asserções que podem fazer com que o teste falhe, por exemplo, se o nome da pessoa e outro dado não é como esperado. métodos de objetos fake e mock que retornem dados, aparentemente de uma armazenamento de dados ou de usuário, pode ajudar ao processo de teste sempre retornar o mesmo, dados que testes possam confiar. Eles podem ser muito usáveis em predefinidos modos de falha em que rotinas de tratamento de erro pode ser desenvolvidas e confiavelmente testadas. Servicos fake dentre outros armazenamento de dados podem ser usáveis em TDD: Um serviço fake de criptografia pode não, criptografar o dado passado; serviços fake de número aleatório podem sempre retornar 1. Implementações de fakes e mocks são exemplos de injeção de dependência.

  2.  

A proposta da injeção de dependência é que a base de dados ou qualquer ou código de acesso externo nunca é testado pelo processo TDD. Para desviar de erros que possam aparecer em função disso, outros testes com a real implementação das interfaces discutidas acima são necessários. Esses testes são separados dos testes unitários e são realmente testes de integração. Eles serão poucos, e eles precisam ser menos executados os testes de unidades. Eles podem ser implementados sem nenhum problema usando o mesmo framework de testes, como xUnit.

 

Testes de integração que alteram qualquer armazenamento persistente ou banco de dados deve ser designado cuidadosamente, levando em consideração os estados iniciais e finais dos arquivos e base de dados, independente se um teste falha. Isto é muitas vezes adquirido usando várias combinações das seguintes técnicas:

 

  • O método TearDown, que é integrado ao muitos frameworks de teste. 

  • Estruturas try...catch...finally de tratamento de exceções, quando disponíveis. 

  • Transações de banco de dados onde ela atomicamente inclui talvez um escrita, uma leitura e uma operação de deleção. 

  • Capturando o "estado" do banco de dados antes de executar qualquer teste e após a execução, desfazar para o "estado" antes do teste ser executado. Isso pode ser automatizado usando a framework como o Ant ou NAnt ou um sistema de integração contínua como o CruiseControl. 

  • Inicializando o banco de dados para um estado limpo antes dos testes, ao invés de limpar depois da execução dos testes. Isto pode ser relevante onde limpar depois pode tornar difícil de diagnosticar falhas de teste ao deletar o estado final do banco de dados antes que um diagnóstico detalhado possa ser feito.

  •  

Framework como Moq, jMock, NMock, EasyMock, TypeMock, jMockit, Mockito, PowerMock e Rhino Mocks existem para tornar o processo de criar e usar objetos mock complexos fácilmente.

  

Resolução de Questões de Concursos Anteriores 


MPOGTecnologia da Informação – 2013 – CESPE 

Ao realizar o TDD (test-driven development), o programador é conduzido a pensar em decisões de design antes de pensar em código de implementação, o que cria um maior acoplamento, uma vez que seu objetivo é pensar na lógica e nas responsabilidades de cada classe. 

 

Certo ou Errado? 

RESPOSTA: Errado


SERPROAnalista Desenvolvimento de Sistemas – 2013 – CESPE 

Usando-se o TDD, as funcionalidades devem estar completas e da forma como serão apresentadas aos seus usuários para que possam ser testadas e consideradas corretas. 

 

Certo ou Errado? 

RESPOSTA: Errado

 

O TDD é justamente o contrário disso, o teste vem antes.

 

Segundo Pressman: 


Em desenvolvimento baseado em teste (test-driven development— TDD), requisitos para um componente de software servem de base para a criação de uma série de casos de teste que exercitam a interface e tentam encontrar erros nas estruturas de dados e funcionalidade fornecida pelo componente. A TDD não é realmente um a nova tecnologia, mas sim uma tendência que enfatiza o projeto de casos de teste antes da criação do código-fonte.


O processo TDD segue o fluxo procedural simples. Antes de ser criado o primeiro segmento de código, um engenheiro de software cria um teste para exercitar o código (tentando fazer o código falhar). É então rescrito o código para satisfazer ao teste. Se passar, um novo teste é criado para o próximo segmento de código a ser desenvolvido. O processo continua até que o componente esteja completamente codificado e todos os testes executam sem erro. No entanto, se algum teste conseguir descobrir um erro, o código existente é refeito (corrigido) e todos os testes criados até aquele ponto são executados novamente. Esse fluxo iterativo continua até que não haja mais teste a ser criado, implicando que o componente satisfaz a todos o s requisitos definidos para ele.

 

Durante o TDD, o código é desenvolvido em incrementos muito pequenos (uma subfunção de cada vez), e nenhum código é escrito enquanto não houver um teste para experimentá-lo. Você deve observar que cada iteração resulta em um ou mais novos testes que são acrescentados a um conjunto de testes de regressão que roda em cada mudança. Isso é feito para garantir que o novo código não tenha gerado efeitos colaterais que causam erros no código anterior. 

 

TRE-SPTécnico Judiciário – 2012 – FCC 

Sobre desenvolvimento baseado em testes, considere: 

 

I. Este processo requer que desenvolvedores criem unidades de testes para definir os requisitos que um determinado código deve conter. Estes testes devem ser criados assim que uma pequena parte funcional do código esteja disponível. 

 

II. Frequentemente são utilizados frameworks de teste pelos desenvolvedores como o xUnit ou jUnit para a criação de casos de teste automatizados. 

 

III. É importante que o código escrito seja apenas projetado para passar o teste específico. Nenhuma outra funcionalidade deve ser prevista ou permitida fora do escopo do teste em nenhum estágio do processo. 

 

Está correto o que consta em 

 

(A) I, apenas. 

(B) II, apenas. 

(C) I e III, apenas. 

(D) II e III, apenas. 

(E) I, II e III. 

RESPOSTA: D


No TDD (Test-driven Development) o foco são pequenos ciclos de desenvolvimento. 


  1. Começa desenvolvendo o caso de teste. 

  1. Aplica-se o teste ao software (Como o software não existe, ele obviamente falha no teste) 

  1. Em caso de falha Corrige-se a falha e volta-se ao passo 2 

  1. Incremento pronto 


Os casos de teste definem o escopo do incremento. Por isso não devemos implementar nada fora do escopo, ou seja que não possua teste definido. 


TRT 6ª RegiãoAnalista Judiciário – 2012 – FCC 

Sobre testes de sistemas, considere: 

 

I. Testes de cenário são úteis pois podem garantir que não restam erros no sistema. Neste ponto diferem dos testes de componentes que apenas garantem a integridade de módulos isolados do sistema, mas não garantem que a totalidade do sistema está isenta de erros.  

 

II. Testes de desenvolvimento incluem testes unitários, nos quais são testados objetos e métodos específicos; testes de componentes, nos quais são testados diversos grupos de objetos; testes de sistema, nos quais são testados sistemas parciais e sistemas completos.  

 

III. Os testes de usuário podem ser divididos em três fases: teste alfa, em que os usuários do software trabalham com a equipe de desenvolvimento para efetuar testes no local do desenvolvedor; teste beta, em que um release de software é disponibilizado aos usuários para que possam experimentar e levantar os problemas descobertos com os desenvolvedores do sistema; teste de sistema, em que os clientes testam um sistema para decidir se ele está pronto para ser implantado no ambiente de trabalho.  

 

Está correto o que se afirma em  

 

a) I, II e III. 

b) II, apenas. 

c) I e II, apenas. 

d) III, apenas. 

e) II e III, apenas. 

RESPOSTA: B

 

I. Testes de cenário são úteis pois podem garantir que não restam erros no sistema. Neste ponto diferem dos testes de componentes que apenas garantem a integridade de módulos isolados do sistema, mas não garantem que a totalidade do sistema está isenta de erros.

 

Está se referindo a testes de sistema. Além disso, a afirmação de que "garante que não restam erros no sistema" é forte, é muito difícil garantir que o sistema está livre de erros. Até mesmo porque é dito que em um local que foi encontrado erro, é provável que seja encontrados mais. E que “ao se remover um erro, é adicionado um ou mais erros.

 

Teste de Sistema: É efetuado em ambiente operacional, levando em consideração todos os requisitos do sistema, tais como pessoas, hardware, software, processos, informações etc. São conduzidos em um ambiente completo e integrado, por várias pessoas (não só os desenvolvedores).

 

III - Os testes de usuário podem ser divididos em três fases: teste alfa, em que os usuários do software trabalham com a equipe de desenvolvimento para efetuar testes no local do desenvolvedor; teste beta, em que um release de software é disponibilizado aos usuários para que possam experimentar e levantar os problemas descobertos com os desenvolvedores do sistema; teste de sistema teste de aceitação, em que os clientes testam um sistema para decidir se ele está pronto para ser implantado no ambiente de trabalho. 


Teste de sistema é definido no Item II da questão e não são testados pelos clientes...


Além disso no teste beta os erros não são descobertos com o desenvolvedor, isso ocorre no teste alfa.

 

  • Teste Alfa: São testes conduzidos pelo cliente nas instalações do desenvolvedor, ou seja no ambiente de desenvolvimento. 


  • Teste Beta: É conduzido em um ou mais locais do cliente, pelo usuário final do produto, geralmente sem a presença do desenvolvedor, o cliente reporta aos desenvolvedores os possíveis defeitos ou erros encontrados. 


TSTTécnico Judiciário – 2012 – FCC 

O processo de desenvolvimento orientado a testes, de uma forma geral, é baseado em 3 passos. Estes 3 passos são repetidos até que não se consiga pensar em novos testes, o que indicaria, então, que a funcionalidade está pronta. Um destes passos e o que nele deve ser feito está expresso corretamente em: 

 

a) Refatore é o passo 3. Uma vez que o teste tenha passado, deve-se verificar o que pode ser melhorado no código e remover as duplicações. Essas melhorias no código, no entanto, devem permitir que os testes continuem passando.  

 

b) Escreva um teste que falhe é o passo 2. Neste passo definem-se quais são as verificações que precisam ser feitas. Deve-se pensar primeiro no teste e só depois que este estiver pronto cria-se o código necessário para que ele compile e falhe ao ser executado.  

 

c) Faça o teste passar é o passo 1. Neste passo escreve-se apenas código suficiente para que o teste passe. Mesmo que se saiba que o código deve fazer mais coisas, fazer os testes passarem deve ser a única preocupação nesta etapa.  

 

d) Keep it simple é o passo 1. Como a solução vai surgindo pouco a pouco, a tendência é que não se perca tempo com aquilo que não se tem certeza que será usado em seguida, então, o foco deve estar no planejamento de testes simples.  

 

e) Documente o teste é o passo 3. Os testes, quando bem definidos, são mais simples de ler que o código e, embora nem sempre sirvam como uma especificação para o usuário final, eles são uma fonte eficiente para entender o que o software faz. Além disso, esta documentação sempre estará atualizada com a aplicação.  

RESPOSTA: A

 

Processo conhecido como RED, GREEN, REFACTOR (Ciclo de Desenvolvimento do TDD):

 

  • Escreva um teste que falhe (Red); 

  • Crio o código até que o teste passe (Green); 

  • Refatore o Código.