O TDD realmente funciona para projetos complexos?

52

Estou fazendo essa pergunta sobre problemas que experimentei durante os projetos do TDD. Tenho notado os seguintes desafios ao criar testes de unidade.

  • Gerando e mantendo dados simulados

É difícil e irrealista manter grandes dados simulados. É ainda mais difícil quando a estrutura do banco de dados sofre alterações.

  • GUI de teste

Mesmo com o MVVM e a capacidade de testar a GUI, é preciso muito código para reproduzir o cenário da GUI.

  • Testando o negócio

Tenho experiência que o TDD funciona bem se você o limitar a uma lógica de negócios simples. No entanto, a lógica de negócios complexa é difícil de testar, pois o número de combinações de testes (espaço de teste) é muito grande.

  • Contradição nos requisitos

Na realidade, é difícil capturar todos os requisitos em análise e design. Muitas vezes, os requisitos de uma nota levam à contradição porque o projeto é complexo. A contradição é encontrada no final da fase de implementação. O TDD exige que os requisitos estejam 100% corretos. Nesses casos, pode-se esperar que requisitos conflitantes sejam capturados durante a criação de testes. Mas o problema é que este não é o caso em cenários complexos.

Eu li esta pergunta: Por que o TDD funciona?

O TDD realmente funciona para projetos empresariais complexos, ou é praticamente limite para o tipo de projeto?

    
por Amir Rezaei 31.01.2011 / 12:26
fonte

14 respostas

52

It’s hard and unrealistic to maintain large mock data. It’s is even harder when database structure undergoes changes.

Falso.

O teste de unidade não requer dados simulados "grandes". Requer dados simulados suficientes para testar os cenários e nada mais.

Além disso, os programadores realmente preguiçosos pedem aos especialistas no assunto que criem planilhas simples dos vários casos de teste. Apenas uma planilha simples.

Em seguida, o programador preguiçoso escreve um script simples para transformar as linhas da planilha em casos de teste de unidade. É bem simples, na verdade.

Quando o produto evolui, as planilhas de casos de teste são atualizadas e novos testes de unidade são gerados. Faça isso o tempo todo. Isso realmente funciona.

Even with MVVM and ability to test GUI, it’s takes a lot of code to reproduce the GUI scenario.

O que? "Reproduzir"?

O objetivo do TDD é projetar coisas para testabilidade (Test Drive Development). Se a GUI for esse complexo, ela precisará ser reprojetada para ser mais simples e mais testável. Mais simples também significa mais rápido, mais fácil de manter e mais flexível. Mas principalmente mais simples significa mais testável.

I have experience that TDD works well if you limit it to simple business logic. However complex business logic is hard to test since the number of combination of test (test space) is very large.

Isso pode ser verdade.

No entanto, pedir ao especialista que forneça os principais casos de teste de forma simples (como uma planilha) realmente ajuda.

As planilhas podem se tornar bastante grandes. Mas tudo bem, já que usei um script Python simples para transformar as planilhas em casos de teste.

E. Eu tive que escrever alguns casos de teste manualmente porque as planilhas estavam incompletas.

No entanto. Quando os usuários relataram "bugs", eu simplesmente perguntei qual teste da planilha estava errado.

Naquele momento, os especialistas no assunto corrigiam a planilha ou adicionavam exemplos para explicar o que deveria acontecer. Os relatórios de erros podem - em muitos casos - ser claramente definidos como um problema no caso de teste. De fato, pela minha experiência, definir o bug como um caso de teste quebrado torna a discussão muito mais simples.

Em vez de ouvir os especialistas tentarem explicar um processo de negócios super-complexo, os especialistas têm que produzir exemplos concretos do processo.

TDD requires that requirements are 100% correct. In such cases one could expect that conflicting requirements would be captured during creating of tests. But the problem is that this isn’t the case in complex scenario.

O não uso do TDD exige que os requisitos estejam 100% corretos. Alguns afirmam que o TDD pode tolerar requisitos incompletos e variáveis, em que uma abordagem não-TDD não pode funcionar com requisitos incompletos.

Se você não usa o TDD, a contradição é encontrada tarde na fase de implementação.

Se você usar o TDD, a contradição será encontrada mais cedo quando o código passar em alguns testes e falhar em outros testes. De fato, o TDD fornece uma prova de uma contradição no início do processo, muito antes da implementação (e dos argumentos durante o teste de aceitação do usuário).

Você tem código que passa em alguns testes e falha em outros. Você olha para somente esses testes e encontra a contradição. Isso funciona muito bem na prática, porque agora os usuários têm que discutir sobre a contradição e produzir exemplos consistentes e concretos do comportamento desejado.

    
por 31.01.2011 / 13:57
fonte
27

Sim

Minha primeira exposição ao TDD foi trabalhar nos componentes de middleware para um telefone celular baseado em Linux. Isso acabou sendo milhões de linhas de código-fonte, que por sua vez geraram cerca de 9 gigabytes de código-fonte para vários componentes de código aberto.

Esperava-se que todos os autores de componentes propusessem uma API e um conjunto de testes de unidade, e fizessem com que eles fossem revisados por um comitê de pares. Ninguém esperava perfeição nos testes, mas todas as funções expostas publicamente tinham que ter pelo menos um teste, e uma vez que um componente fosse submetido ao controle de origem, todos os testes de unidade tinham que passar (mesmo se o fizessem porque o componente estava falsamente reportando funcionou bem).

Sem dúvida, pelo menos em parte devido a TDD e uma insistência para que todos os testes unitários sempre passem, a versão 1.0 chegou cedo, abaixo do orçamento e com uma estabilidade surpreendente.

Após a versão 1.0, porque a empresa queria ser capaz de mudar rapidamente o escopo devido às demandas do cliente, eles nos disseram que parássemos de fazer o TDD e removeram o requisito que os testes de unidade passam. Foi surpreendente a rapidez com que a qualidade caiu no vaso sanitário e, em seguida, o cronograma seguiu-o.

    
por 01.02.2011 / 06:20
fonte
18

Eu diria que quanto mais complexo for o projeto, mais benefícios você terá com o TDD. Os principais benefícios são os efeitos colaterais de como o TDD forçará você a escrever o código em partes menores e muito mais independentes. Os principais benefícios são:

a) Você obtém uma validação muito mais antiga do seu design porque o seu ciclo de feedback é muito mais restrito devido a testes desde o início.

b) Você pode mudar pedaços e ver como o sistema reage porque você está construindo uma colcha de cobertura de teste o tempo todo.

c) O código final será muito melhor como resultado.

    
por 31.01.2011 / 15:33
fonte
10

O TDD realmente funciona para projetos complexos?
Sim. Nem todo projeto me diz que funciona bem com o TDD, mas a maioria dos aplicativos de negócios são bons, e eu aposto que os que não funcionam bem quando são escritos em uma forma pura de TDD podem ser escritos de forma ATDD sem grandes problemas.

Gerando e mantendo dados simulados
Mantê-lo pequeno e só tem o que você precisa e isso não é a questão assustadora parece. Não me entenda mal, é uma dor. Mas vale a pena.

Testing GUI
Teste o MVVM e certifique-se de que ele possa ser testado sem a exibição. Eu não achei isso mais difícil do que testar qualquer outra lógica de negócios. Testando a visão no código eu não faço, tudo o que você está testando, no entanto, neste ponto, é a lógica de ligação, que se espera será capturada rapidamente quando você fizer um teste manual rápido.

Testando o negócio
Não foi encontrado para ser um problema. Muitos pequenos testes. Como eu disse acima, alguns casos (resolvedores de quebra-cabeças Sudoku parecem ser populares) são aparentemente difíceis de fazer TDD.

> TDD requer que os requisitos estejam 100% corretos
Não, não tem. De onde você tirou essa ideia? Todas as práticas ágeis aceitam que os requisitos mudam. Você precisa saber o que está fazendo antes de fazê-lo, mas isso não é o mesmo que exigir que os requisitos sejam 100%. O TDD é uma prática comum no Scrum, onde os requisitos (User Stories) são, por definição, não 100% completos.

    
por 31.01.2011 / 13:54
fonte
9
Primeiro, acredito que o seu problema é mais sobre o teste unitário em geral do que sobre o TDD, já que não vejo nada realmente específico para o TDD (teste primeiro + red-green-refactor cycle) no que você diz.

It’s hard and unrealistic to maintain large mock data.

O que você quer dizer com dados simulados? Supõe-se que uma simulação contenha quase todos os dados, ou seja, nenhum campo além do um ou dois necessário no teste e nenhuma dependência além do sistema em teste. Configurar uma expectativa simulada ou valor de retorno pode ser feito em uma linha, então nada terrível.

It’s is even harder when database structure undergoes changes.

Se você quer dizer que o banco de dados sofre alterações sem que as modificações apropriadas tenham sido feitas no modelo de objeto, testes de unidades de poço estão precisamente aqui para avisá-lo disso. Caso contrário, mudanças no modelo devem ser refletidas nos testes de unidade, obviamente, mas com indicações de compilação é uma coisa fácil de fazer.

Even with MVVM and ability to test GUI, it takes a lot of code to reproduce the GUI scenario.

Você está certo, a unidade testando a GUI (View) não é fácil, e muitas pessoas estão indo bem sem ela (além disso, testar a GUI não faz parte do TDD). Em contraste, a unidade testando seu Controller / Presenter / ViewModel / qualquer camada intermediária é altamente recomendada, na verdade, é uma das principais razões pelas quais padrões como MVC ou MVVM são.

I have experience that TDD works well if you limit it to simple business logic. However complex business logic is hard to test since the number of combinations of tests (test space) is very large.

Se sua lógica de negócios é complexa, é normal que os testes de unidade sejam difíceis de projetar. Cabe a você torná-los o mais atômico possível, cada um testando apenas uma responsabilidade do objeto sob teste. Os testes unitários são ainda mais necessários em um ambiente complexo, pois fornecem uma rede de segurança garantindo que você não quebre as regras ou os requisitos de negócios ao fazer alterações no código.

TDD requires that requirements are 100% correct.

Absolutamente não. Software bem-sucedido requer que os requisitos estejam 100% corretos;) Os testes de unidade apenas refletem qual é a sua visão atual dos requisitos; se a visão é falha, o seu código e o seu software serão também, testes de unidade ou não ... E é aí que os testes de unidade brilham: com títulos de teste suficientemente explícitos, suas decisões de design e interpretação de requisitos se tornam transparentes, o que torna mais fácil apontar o que precisa ser alterado na próxima vez que seu cliente disser: "essa regra de negócios não é tão Eu gostaria de ".

    
por 31.01.2011 / 18:54
fonte
6

Eu tenho que rir quando ouço alguém reclamar que a razão pela qual eles não podem usar o TDD para testar sua aplicação é porque o aplicativo deles é muito complicado. Qual é a alternativa? Os macacos do teste bateram em acres de teclados? Deixe os usuários serem os testadores? O quê mais? Claro que é difícil e complexo. Você acha que a Intel não testa suas chips até que elas sejam enviadas? Como "head-in-the-sand" é isso?

    
por 01.02.2011 / 05:30
fonte
4
> Does TDD really work for complex projects?

Da minha experiência: Sim para Unittests (teste de módulos / recursos isoladamente) porque esses principalmente não tem os problemas que você menciona: (Gui, Mvvm, Business-Modell). Eu nunca tive mais que 3 mocks / stubs para preencher um teste unitário (mas talvez seu domínio precise de mais).

No entanto, eu não tenho certeza se TDD poderia resolver os problemas que você mencionou na integração ou no teste de ponta a ponta com testes no estilo do BDD.

Mas pelo menos alguns problemas podem ser reduzidos .

> However complex business logic is hard to test since the number 
> of combinations of tests (test space) is very large.

Isso é verdade se você quiser fazer uma cobertura completa no nível de teste de integração ou teste end-to-end. Pode ser mais fácil fazer a cobertura completa em um nível de teste unitário.

Exemplo: verificação de permissões de usuário complexas

Testando a função IsAllowedToEditCusterData() em um nível de teste de integração         exigiria pedir diferente         objetos para informações sobre usuário, domínio, cliente, ambiente .....

Zombando dessas partes         é bastante difícil. Isso é especialmente verdadeiro se IsAllowedToEditCusterData() tiver que saber         esses objetos diferentes.

Em um Nível de Unito, você teria a Função IsAllowedToEditCusterData() , que considera, por exemplo, 20 parâmetros que contêm tudo o que a função precisa saber. Desde a IsAllowedToEditCusterData() não precisa saber quais campos user , a domain , a customer , .... tem isso fácil de testar.

Quando tive que implementar IsAllowedToEditCusterData() i tive duas sobrecargas:

Uma sobrecarga que não faz nada além de obter esses 20 parâmetros e depois chamar a sobrecarga com os 20 parâmetros que tomam decisões.

(meu IsAllowedToEditCusterData() tinha apenas 5 parâmetros e eu precisava de 32 combinações diferentes para testá-lo completamente)

Exemplo

// method used by businesslogic
// difficuilt to test because you have to construct
// many dependant objects for the test
public boolean IsAllowedToEditCusterData() {
    Employee employee = getCurrentEmployee();
    Department employeeDepartment = employee.getDepartment();
    Customer customer = getCustomer();
    Shop shop = customer.getShop();

    // many more objects where the permittions depend on

    return IsAllowedToEditCusterData(
            employee.getAge(),
            employeeDepartment.getName(),
            shop.getName(),
            ...
        );
}

// method used by junittests
// much more easy to test because only primitives
// and no internal state is needed
public static boolean IsAllowedToEditCusterData(
        int employeeAge,
        String employeeDepartmentName,
        String shopName,
        ... ) 
{
    boolean isAllowed; 
    // logic goes here

    return isAllowed;
}
    
por 31.01.2011 / 18:54
fonte
3

Eu descobri que o TDD (e testes unitários em geral) é virtualmente impossível por um motivo relacionado: Algoritmos complexos, novos e / ou difusos. A questão que mais me deparo nos protótipos de pesquisa que escrevo é que não tenho a menor ideia do que é a resposta certa senão executando meu código. É muito complicado descobrir a mão para qualquer coisa além de casos ridiculamente triviais. Isso é especialmente verdadeiro se o algoritmo envolve heurísticas, aproximações ou não-determinismo. Eu ainda tento testar a funcionalidade de nível inferior de que este código depende e uso intensamente como verificações de sanidade. Meu método de teste de último recurso é escrever duas implementações diferentes, idealmente em dois idiomas diferentes, usando dois conjuntos diferentes de bibliotecas e comparar os resultados.

    
por 14.04.2011 / 03:53
fonte
2

A triste resposta é que nada realmente funciona para grandes projetos complexos!

O TDD é tão bom quanto qualquer outra coisa e melhor que a maioria, mas o TDD sozinho não garante sucesso em um projeto grande. No entanto, aumentará suas chances de sucesso. Especialmente quando usado em combinação com outras disciplinas de gerenciamento de projetos (verificação de requisitos, casos de uso, matriz de tratabilidade de requisitos, explicações passo a passo etc.).

    
por 25.05.2013 / 06:42
fonte
1

Lembre-se de que os testes de unidade são especificações impostas . Isso é especialmente valioso em projetos complexos. Se a sua antiga base de código não tiver nenhum teste para fazer backup, ninguém ousará mudar alguma coisa porque terá medo de quebrar alguma coisa.

"Wtf. Por que essa ramificação de código está lá? Não sei, talvez alguém precise, melhor deixar lá do que incomodar alguém ..." Com o tempo, os projetos complexos se tornam uma terra de lixo.

Com os testes, qualquer um pode dizer com segurança: "Fiz alterações drásticas, mas todos os testes ainda estão passando". Por definição, ele não quebrou nada. Isso leva a projetos mais ágeis que podem evoluir. Talvez uma das razões pelas quais ainda precisamos de pessoas para manter o COBOL é porque o teste não era popular desde então: P

    
por 31.01.2011 / 18:24
fonte
1

Eu vi um grande projeto complexo falhar completamente quando o TDD foi usado exclusivamente, ou seja, sem pelo menos configurar em um depurador / IDE. Os dados simulados e / ou testes mostraram-se insuficientes. Os dados reais dos clientes Beta eram confidenciais e não podiam ser copiados ou registrados. Assim, a equipe de desenvolvimento nunca poderia consertar os erros fatais que se manifestavam quando apontava para dados reais, e todo o projeto foi descartado, todo mundo atirou, todo o processo.

A maneira de ter resolvido este problema teria sido ativá-lo em um depurador no site do cliente, enfrentar os dados reais, percorrer o código, com pontos de interrupção, variáveis de observação, memória de observação, etc. No entanto, essa equipe, que achava que seu código estaria apto a adornar as melhores torres de marfim, durante um período de quase um ano, nunca acionou o aplicativo. Isso me surpreendeu.

Então, como tudo, o equilíbrio é a chave. O TDD pode ser bom, mas não confie nele exclusivamente.

    
por 31.01.2013 / 14:49
fonte
0

Acho que sim, veja Desenvolvimento orientado a testes realmente funciona

In 2008, Nachiappan Nagappan, E. Michael Maximilien, Thirumalesh Bhat, and Laurie Williams wrote a paper called “Realizing quality improvement through test driven development: results and experiences of four industrial teams“ (PDF link). The abstract:

Test-driven development (TDD) is a software development practice that has been used sporadically for decades. With this practice, a software engineer cycles minute-by-minute between writing failing unit tests and writing implementation code to pass those tests. Test-driven development has recently re-emerged as a critical enabling practice of agile software development methodologies. However, little empirical evidence supports or refutes the utility of this practice in an industrial context. Case studies were conducted with three development teams at Microsoft and one at IBM that have adopted TDD. The results of the case studies indicate that the pre-release defect density of the four products decreased between 40% and 90% relative to similar projects that did not use the TDD practice. Subjectively, the teams experienced a 15–35% increase in initial development time after adopting TDD.

     

Em 2012, as práticas de desenvolvimento do Ruby on Rails assumem o TDD. Eu pessoalmente confio em ferramentas como o rspec para escrever testes e zombarias, factory_girl para criação de objetos, capivara para automação de navegadores, simplecov para cobertura de código e guarda para automatizar estes testes.

     

Como resultado do uso desta metodologia e dessas ferramentas, eu tenho a tendência de concordar subjetivamente com Nagappan et al ...

    
por 26.01.2012 / 19:28
fonte
0

Se a combinação de orçamento, requisitos e habilidades de equipe estiverem no quadrante do espaço do projeto, "abandonem a esperança de todos vocês que entram aqui", então, por definição, é esmagadoramente provável que o projeto falhe.

Talvez os requisitos sejam complexos e voláteis, a infraestrutura instável, a equipe júnior e com alta rotatividade, ou o arquiteto seja um idiota.

Em um projeto TDD, o sintoma dessa falha iminente é que os testes não podem ser gravados no horário; você tenta, apenas descobrir 'isso vai levar isso por muito tempo, e nós só temos isso '.

Outras abordagens mostrarão sintomas diferentes quando falharem; mais comumente entrega de um sistema que não funciona. A política e os contratos determinarão se isso é preferível.

    
por 06.03.2014 / 23:11
fonte
-1

TDD pode soar como uma dor inicial, mas no longo prazo seria seu melhor amigo, confie em mim TDD realmente tornará a aplicação sustentável e segura em longo prazo.

    
por 01.02.2011 / 19:42
fonte

Tags